diff --git a/DEPS b/DEPS index c4552768..b777de93 100644 --- a/DEPS +++ b/DEPS
@@ -96,11 +96,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': 'e7df0bb900ec266021bc6bf4477d533ce1b1f749', + 'skia_revision': 'a2595f925596aca234d4ac4e35da689ef13cc27c', # 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': '9ef8a461214813207c0032d3ad41730adce0539b', + 'v8_revision': '9c5f77a1382ee3825f708aba48f5675fb55c84e1', # 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. @@ -108,7 +108,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '3b9b027c59f38580cb038f94d49887e98a80b082', + 'angle_revision': 'e95a7f077e8bda81cbff51bf84ee80cbf2841e1d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -120,7 +120,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': 'e5c0fa97c2da104426dbc1cecfc0ed488a22efe5', + 'pdfium_revision': 'df1298a228abb59eb167d0be43d46a50c0333497', # 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. @@ -156,7 +156,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': '08f785343ab32fb8cc511fdd28d85d417654d94a', + 'catapult_revision': '718dbe7d32442fbc27b7a150ec2573ab93abea55', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -498,7 +498,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'da3ce5f235a237f27646db55ece4bfdbe04fb832', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9520b5b98bd364e4d0090c92d05c0f8b1eb9cd02', 'condition': 'checkout_linux', }, @@ -523,7 +523,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5ae86d2021277b545889959125e778820849cf15', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3806b7fbd0ea6704d2c35d1eb64a2a505e29ca53', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -653,7 +653,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'e4194dc7bbb3305d84cbb1b294274ca70d230721', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'f61e46dbee9d539a32551493e3bcc1dea92f83ec', 'src/third_party/icu4j': { 'packages': [ @@ -968,7 +968,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7c0541da63f571512c49758cbc0767117997a270', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '826738b78c6ab72a0d927339c177fd41848d02df', # commit position 21742 + Var('webrtc_git') + '/src.git' + '@' + 'd6f86e8fca212e0f1b9b390dd31ef7579b66cc3e', # commit position 21742 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1002,7 +1002,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9ad6814d5f1e026662cac01f07248d671c48b4da', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@59e400635dcd78dd874a63a90fa65300b9945f94', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index b935668..1cf49ac 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -571,7 +571,7 @@ '|chrome/browser/resources/settings/', }, 'browsing_data': { - 'filepath': 'chrome/browser/browsing_data/', + 'filepath': '/browsing_data/', }, 'bubble': { 'filepath': 'ui/views/bubble/|'\ @@ -2180,7 +2180,8 @@ 'nacl': ['native-client-reviews@googlegroups.com'], 'native_client_sdk': ['binji+watch@chromium.org', 'sbc@chromium.org'], - 'navigation': ['creis+watch@chromium.org', + 'navigation': ['alexmos+watch@chromium.org', + 'creis+watch@chromium.org', 'nasko+codewatch@chromium.org'], 'net': ['cbentzel+watch@chromium.org', 'net-reviews@chromium.org'], @@ -2276,6 +2277,7 @@ 'settings_reset_prompt': ['alito+watch@chromium.org'], 'site_engagement': ['dominickn+watch@chromium.org'], 'site_instance': ['ajwong+watch@chromium.org', + 'alexmos+watch@chromium.org', 'creis+watch@chromium.org', 'nasko+codewatch@chromium.org'], 'smb': ['cros-enterprise-lax+smbwatch@chromium.org'],
diff --git a/android_webview/browser/aw_field_trial_creator.cc b/android_webview/browser/aw_field_trial_creator.cc index 8ff0875..c5e2044 100644 --- a/android_webview/browser/aw_field_trial_creator.cc +++ b/android_webview/browser/aw_field_trial_creator.cc
@@ -5,6 +5,9 @@ #include "android_webview/browser/aw_field_trial_creator.h" #include <memory> +#include <set> +#include <string> +#include <vector> #include "android_webview/browser/aw_metrics_service_client.h" #include "base/base_switches.h" @@ -27,24 +30,11 @@ // TODO(kmilka): Update to work properly in environments both with and without // UMA enabled. std::unique_ptr<const base::FieldTrial::EntropyProvider> -CreateLowEntropyProvider() { +CreateLowEntropyProvider(const std::string& client_id) { return std::unique_ptr<const base::FieldTrial::EntropyProvider>( // Since variations are only enabled for users opted in to UMA, it is // acceptable to use the SHA1EntropyProvider for randomization. - new variations::SHA1EntropyProvider( - // Synchronous read of the client id is permitted as it is fast - // enough to have minimal impact on startup time, and is behind the - // webview-enable-finch flag. - android_webview::AwMetricsServiceClient::GetClientId())); -} - -// Synchronous read of variations data is permitted as it is fast -// enough to have minimal impact on startup time, and is behind the -// webview-enable-finch flag. -bool ReadVariationsSeedDataFromFile(PrefService* local_state) { - // TODO(kmilka): The data read is being moved to java and the data will be - // passed in via JNI. - return false; + new variations::SHA1EntropyProvider(client_id)); } } // anonymous namespace @@ -81,18 +71,19 @@ } void AwFieldTrialCreator::SetUpFieldTrials() { - AwMetricsServiceClient::LoadOrCreateClientId(); + // If the client ID isn't available yet, don't delay startup by creating it. + // Instead, variations will be disabled for this run. + std::string client_id; + if (!AwMetricsServiceClient::GetPreloadedClientId(&client_id)) + return; DCHECK(!field_trial_list_); // Set the FieldTrialList singleton. - field_trial_list_ = - std::make_unique<base::FieldTrialList>(CreateLowEntropyProvider()); + field_trial_list_ = std::make_unique<base::FieldTrialList>( + CreateLowEntropyProvider(client_id)); std::unique_ptr<PrefService> local_state = CreateLocalState(); - if (!ReadVariationsSeedDataFromFile(local_state.get())) - return; - variations::UIStringOverrider ui_string_overrider; client_ = std::make_unique<AwVariationsServiceClient>(); variations_field_trial_creator_ = @@ -114,7 +105,7 @@ variations_field_trial_creator_->SetupFieldTrials( cc::switches::kEnableGpuBenchmarking, switches::kEnableFeatures, switches::kDisableFeatures, unforceable_field_trials, - std::vector<std::string>(), CreateLowEntropyProvider(), + std::vector<std::string>(), CreateLowEntropyProvider(client_id), std::make_unique<base::FeatureList>(), aw_field_trials_.get(), &ignored_safe_seed_manager); }
diff --git a/android_webview/browser/aw_metrics_service_client.cc b/android_webview/browser/aw_metrics_service_client.cc index ea6ccb9..19d8e55f 100644 --- a/android_webview/browser/aw_metrics_service_client.cc +++ b/android_webview/browser/aw_metrics_service_client.cc
@@ -4,10 +4,16 @@ #include "android_webview/browser/aw_metrics_service_client.h" +#include <jni.h> +#include <stdint.h> +#include <vector> + #include "android_webview/browser/aw_metrics_log_uploader.h" #include "android_webview/common/aw_switches.h" #include "android_webview/jni/AwMetricsServiceClient_jni.h" #include "base/android/build_info.h" +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/bind.h" #include "base/files/file_util.h" @@ -41,8 +47,10 @@ const int kUploadIntervalMinutes = 30; -// A GUID in text form is composed of 32 hex digits and 4 hyphens. -const size_t GUID_SIZE = 32 + 4; +// A GUID in text form is composed of 32 hex digits and 4 hyphens. These values +// must match those in AwMetricsServiceClient.java. +const size_t kGuidSize = 32 + 4; +const char* const kGuidFileName = "metrics_guid"; // Client ID of the app, read and cached synchronously at startup base::LazyInstance<std::string>::Leaky g_client_id = LAZY_INSTANCE_INITIALIZER; @@ -79,9 +87,22 @@ return g_lazy_instance_.Pointer(); } +bool AwMetricsServiceClient::GetPreloadedClientId(std::string* client_id) { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef<jbyteArray> client_id_java = + Java_AwMetricsServiceClient_getPreloadedClientId(env); + if (client_id_java.is_null()) + return false; + std::vector<uint8_t> client_id_vector; + base::android::JavaByteArrayToByteVector(env, client_id_java.obj(), + &client_id_vector); + *client_id = std::string(client_id_vector.begin(), client_id_vector.end()); + return true; +} + void AwMetricsServiceClient::LoadOrCreateClientId() { // This function should only be called once at start up. - DCHECK_NE(g_client_id.Get().length(), GUID_SIZE); + DCHECK_NE(g_client_id.Get().length(), kGuidSize); // UMA uses randomly-generated GUIDs (globally unique identifiers) to // anonymously identify logs. Every WebView-using app on every device @@ -96,11 +117,12 @@ } const base::FilePath guid_file_path = - user_data_dir.Append(FILE_PATH_LITERAL("metrics_guid")); + user_data_dir.Append(FILE_PATH_LITERAL(kGuidFileName)); - // Try to read an existing GUID. - if (base::ReadFileToStringWithMaxSize(guid_file_path, &g_client_id.Get(), - GUID_SIZE)) { + // Try to get an existing GUID. + if (GetPreloadedClientId(&g_client_id.Get()) || + base::ReadFileToStringWithMaxSize(guid_file_path, &g_client_id.Get(), + kGuidSize)) { if (base::IsValidGUID(g_client_id.Get())) return; LOG(ERROR) << "Overwriting invalid GUID"; @@ -119,7 +141,7 @@ std::string AwMetricsServiceClient::GetClientId() { // This function should only be called if LoadOrCreateClientId() was // previously called. - DCHECK_EQ(g_client_id.Get().length(), GUID_SIZE); + DCHECK_EQ(g_client_id.Get().length(), kGuidSize); return g_client_id.Get(); } @@ -134,24 +156,17 @@ pref_service_ = pref_service; request_context_ = request_context; - // If variations are enabled for WebView the GUID will already have been read - // at startup - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableWebViewVariations)) { - InitializeWithClientId(); - } else { - base::PostTaskWithTraitsAndReply( - FROM_HERE, {base::MayBlock()}, - base::BindOnce(&AwMetricsServiceClient::LoadOrCreateClientId), - base::BindOnce(&AwMetricsServiceClient::InitializeWithClientId, - base::Unretained(this))); - } + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&AwMetricsServiceClient::LoadOrCreateClientId), + base::BindOnce(&AwMetricsServiceClient::InitializeWithClientId, + base::Unretained(this))); } void AwMetricsServiceClient::InitializeWithClientId() { // The guid must have already been initialized at this point, either // synchronously or asynchronously depending on the kEnableWebViewFinch flag - DCHECK_EQ(g_client_id.Get().length(), GUID_SIZE); + DCHECK_EQ(g_client_id.Get().length(), kGuidSize); pref_service_->SetString(metrics::prefs::kMetricsClientID, g_client_id.Get()); in_sample_ = IsInSample(g_client_id.Get());
diff --git a/android_webview/browser/aw_metrics_service_client.h b/android_webview/browser/aw_metrics_service_client.h index a850a91..5880206 100644 --- a/android_webview/browser/aw_metrics_service_client.h +++ b/android_webview/browser/aw_metrics_service_client.h
@@ -44,6 +44,10 @@ public: static AwMetricsServiceClient* GetInstance(); + // If the client ID was pre-loaded on the Java side, store it in "client_id" + // and return true; otherwise, return false. + static bool GetPreloadedClientId(std::string* client_id); + // Retrieve the client ID or generate one if none exists. static void LoadOrCreateClientId();
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java index aabb08a0..0f16254 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -22,6 +22,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.SystemClock; import android.print.PrintDocumentAdapter; import android.util.Log; import android.util.SparseArray; @@ -62,6 +63,7 @@ import org.chromium.android_webview.renderer_priority.RendererPriority; import org.chromium.base.BuildInfo; import org.chromium.base.ThreadUtils; +import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample; import org.chromium.components.autofill.AutofillProvider; import org.chromium.content_public.browser.NavigationHistory; import org.chromium.content_public.browser.SmartClipProvider; @@ -72,6 +74,7 @@ import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; /** * This class is the delegate to which WebViewProxy forwards all API calls. @@ -149,6 +152,8 @@ // so is ignored. TODO: remove it from WebViewProvider. public void init(final Map<String, Object> javaScriptInterfaces, final boolean privateBrowsing) { + long startTime = SystemClock.elapsedRealtime(); + boolean isFirstWebViewInit = !mFactory.hasStarted(); try (ScopedSysTraceEvent e1 = ScopedSysTraceEvent.scoped("WebViewChromium.init")) { if (privateBrowsing) { mFactory.startYourEngines(true); @@ -170,7 +175,10 @@ // comes from a single thread. (Note in JB MR2 this exception was in WebView.java). if (mAppTargetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR2) { mFactory.startYourEngines(false); - checkThread(); + try (ScopedSysTraceEvent e2 = ScopedSysTraceEvent.scoped( + "WebViewChromium.checkThreadInsideInit")) { + checkThread(); + } } else if (!mFactory.hasStarted()) { if (Looper.myLooper() == Looper.getMainLooper()) { mFactory.startYourEngines(true); @@ -190,8 +198,11 @@ final boolean doNotUpdateSelectionOnMutatingSelectionRange = mAppTargetSdkVersion <= Build.VERSION_CODES.M; - mContentsClientAdapter = - mFactory.createWebViewContentsClientAdapter(mWebView, mContext); + try (ScopedSysTraceEvent e2 = ScopedSysTraceEvent.scoped( + "WebViewChromiumFactoryProvider.createWebViewContentsClientAdapter")) { + mContentsClientAdapter = + mFactory.createWebViewContentsClientAdapter(mWebView, mContext); + } try (ScopedSysTraceEvent e2 = ScopedSysTraceEvent.scoped("WebViewChromium.ContentSettingsAdapter")) { mWebSettings = new ContentSettingsAdapter(new AwSettings(mContext, @@ -227,6 +238,15 @@ } } }); + } finally { + // The real initialization may be deferred, in which case we don't record this. + if (!mFactory.hasStarted()) return; + + TimesHistogramSample histogram = new TimesHistogramSample( + "Android.WebView.Startup.CreationTime.Stage2.ProviderInit." + + (isFirstWebViewInit ? "Cold" : "Warm"), + TimeUnit.MILLISECONDS); + histogram.record(SystemClock.elapsedRealtime() - startTime); } }
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 883afe5..6d11e32 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
@@ -12,6 +12,7 @@ import android.net.Uri; import android.os.Build; import android.os.StrictMode; +import android.os.SystemClock; import android.os.UserManager; import android.provider.Settings; import android.util.Log; @@ -44,6 +45,7 @@ import org.chromium.base.PathUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.library_loader.NativeLibraries; +import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample; import org.chromium.components.autofill.AutofillProvider; import org.chromium.content.browser.selection.LGEmailActionModeWorkaround; @@ -51,6 +53,7 @@ import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; /** * Entry point to the WebView. The system framework talks to this class to get instances of the @@ -163,6 +166,7 @@ @TargetApi(Build.VERSION_CODES.N) // For getSystemService() and isUserUnlocked(). private void initialize(WebViewDelegate webViewDelegate) { + long startTime = SystemClock.elapsedRealtime(); try (ScopedSysTraceEvent e1 = ScopedSysTraceEvent.scoped("WebViewChromiumFactoryProvider.initialize")) { // The package is used to locate the services for copying crash minidumps and requesting @@ -253,6 +257,11 @@ shouldDisableThreadChecking(ContextUtils.getApplicationContext()); setSingleton(this); + } finally { + TimesHistogramSample histogram = new TimesHistogramSample( + "Android.WebView.Startup.CreationTime.Stage1.FactoryInit", + TimeUnit.MILLISECONDS); + histogram.record(SystemClock.elapsedRealtime() - startTime); } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwMetricsServiceClient.java b/android_webview/java/src/org/chromium/android_webview/AwMetricsServiceClient.java index d2f22eb..0e168e26 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwMetricsServiceClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwMetricsServiceClient.java
@@ -9,10 +9,15 @@ import android.content.pm.PackageManager; import org.chromium.base.Log; +import org.chromium.base.PathUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + /** * Determines user consent and app opt-out for metrics. * @@ -26,6 +31,11 @@ * This happens in parallel with native AwMetricsServiceClient initialization; either * nativeInitialized or setConsentSetting might fire first. Whichever fires second should call * nativeSetHaveMetricsConsent. + * + * Also, pre-loads the client ID for variations. Variations setup begins before native init (so it + * can't use the native code to load the client ID), reading the client ID and other variations + * files in the background. Completion of this task blocks WebView startup, so we want to do minimal + * work; unlike the native loader, this loader does not create a new client ID when none is found. */ @JNINamespace("android_webview") public class AwMetricsServiceClient { @@ -38,6 +48,60 @@ private static boolean sIsClientReady; // Is the native AwMetricsServiceClient initialized? private static boolean sShouldEnable; // Have steps 1 and 2 passed? + // A GUID in text form is composed of 32 hex digits and 4 hyphens. These values must match those + // in aw_metrics_service_client.cc. + private static final int GUID_SIZE = 32 + 4; + private static final String GUID_FILE_NAME = "metrics_guid"; + + private static byte[] sClientId; + private static Object sClientIdLock = new Object(); + + private static byte[] readFixedLengthFile(File file, int length) throws IOException { + if (file.length() != length) { + throw new IOException("File is not of expected length " + length); + } + FileInputStream in = null; + try { + in = new FileInputStream(file); + byte[] buf = new byte[length]; + int read = 0; + int offset = 0; + while (offset < length) { + read = in.read(buf, offset, length - offset); + if (read < 1) throw new IOException("Premature EOF"); + offset += read; + } + return buf; + } finally { + if (in != null) in.close(); + } + } + + /** + * Load the metrics client ID, if any. + */ + public static void preloadClientId() { + File clientIdFile = new File(PathUtils.getDataDirectory(), GUID_FILE_NAME); + if (!clientIdFile.exists() || clientIdFile.length() != GUID_SIZE) return; + byte[] clientId = null; + try { + clientId = readFixedLengthFile(clientIdFile, GUID_SIZE); + } catch (IOException e) { + Log.e(TAG, "Failed to pre-load GUID file " + clientIdFile + " - " + e.getMessage()); + return; + } + synchronized (sClientIdLock) { + sClientId = clientId; + } + } + + @CalledByNative + public static byte[] getPreloadedClientId() { + synchronized (sClientIdLock) { + return sClientId; + } + } + private static boolean isAppOptedOut(Context appContext) { try { ApplicationInfo info = appContext.getPackageManager().getApplicationInfo(
diff --git a/android_webview/java/src/org/chromium/android_webview/VariationsSeedLoader.java b/android_webview/java/src/org/chromium/android_webview/VariationsSeedLoader.java index 00616a2..adee16ce 100644 --- a/android_webview/java/src/org/chromium/android_webview/VariationsSeedLoader.java +++ b/android_webview/java/src/org/chromium/android_webview/VariationsSeedLoader.java
@@ -44,12 +44,14 @@ * by the Runnable. * * The Runnable and FutureTask together perform these steps: - * 1. Load the new seed file, if any. - * 2. If no new seed file, load the old seed file, if any. - * 3. Make the loaded seed available via get() (or null if there was no seed). - * 4. If there was a new seed file, replace the old with the new (but only after making the loaded + * 1. Pre-load the metrics client ID. This is needed to seed the EntropyProvider. If there is no + * client ID, variations can't be used on this run. + * 2. Load the new seed file, if any. + * 3. If no new seed file, load the old seed file, if any. + * 4. Make the loaded seed available via get() (or null if there was no seed). + * 5. If there was a new seed file, replace the old with the new (but only after making the loaded * seed available, as the replace need not block startup). - * 5. If there was no seed, or the loaded seed was expired, request a new seed (but don't request + * 6. If there was no seed, or the loaded seed was expired, request a new seed (but don't request * more often than MAX_REQUEST_PERIOD_MILLIS). * * VariationsSeedLoader should be used during WebView startup like so: @@ -76,6 +78,10 @@ // is exceeded, proceed with variations disabled. private static final long SEED_LOAD_TIMEOUT_MILLIS = 20; + // If false, then variations will be enabled if either the CMD flag or the AGSA experiment file + // is present. If true, then variations will be enabled regardless of flag or experiment file. + private static boolean sVariationsAlwaysEnabled = false; + private static void recordLoadSeedResult(int result) { EnumeratedHistogramSample histogram = new EnumeratedHistogramSample( "Variations.SeedLoadResult", LoadSeedResult.ENUM_SIZE); @@ -121,6 +127,8 @@ mEnabledByExperiment = checkEnabledByExperiment(); if (!(mEnabledByCmd || mEnabledByExperiment)) return null; + AwMetricsServiceClient.preloadClientId(); + File newSeedFile = VariationsUtils.getNewSeedFile(); File oldSeedFile = VariationsUtils.getSeedFile(); @@ -208,7 +216,7 @@ // mEnabledByExperiment is set in mLoadTask, so isVariationsEnabled() should only be called // after run() returns. public boolean isVariationsEnabled() { - return mEnabledByCmd || mEnabledByExperiment; + return sVariationsAlwaysEnabled || mEnabledByCmd || mEnabledByExperiment; } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 62da806..78c8f02 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -227,6 +227,8 @@ "frame/caption_buttons/frame_size_button.cc", "frame/caption_buttons/frame_size_button.h", "frame/caption_buttons/frame_size_button_delegate.h", + "frame/custom_frame_header.cc", + "frame/custom_frame_header.h", "frame/custom_frame_view_ash.cc", "frame/custom_frame_view_ash.h", "frame/default_frame_header.cc", @@ -603,6 +605,16 @@ "system/locale/locale_notification_controller.h", "system/media_security/multi_profile_media_tray_item.cc", "system/media_security/multi_profile_media_tray_item.h", + "system/message_center/ash_popup_alignment_delegate.cc", + "system/message_center/ash_popup_alignment_delegate.h", + "system/message_center/fullscreen_notification_blocker.cc", + "system/message_center/fullscreen_notification_blocker.h", + "system/message_center/inactive_user_notification_blocker.cc", + "system/message_center/inactive_user_notification_blocker.h", + "system/message_center/notification_tray.cc", + "system/message_center/notification_tray.h", + "system/message_center/session_state_notification_blocker.cc", + "system/message_center/session_state_notification_blocker.h", "system/model/clock_model.cc", "system/model/clock_model.h", "system/model/enterprise_domain_model.cc", @@ -780,6 +792,8 @@ "system/tray/actionable_view.h", "system/tray/hover_highlight_view.cc", "system/tray/hover_highlight_view.h", + "system/tray/interacted_by_tap_recorder.cc", + "system/tray/interacted_by_tap_recorder.h", "system/tray/label_tray_view.cc", "system/tray/label_tray_view.h", "system/tray/size_range_layout.cc", @@ -889,16 +903,6 @@ "system/virtual_keyboard/virtual_keyboard_observer.h", "system/virtual_keyboard/virtual_keyboard_tray.cc", "system/virtual_keyboard/virtual_keyboard_tray.h", - "system/web_notification/ash_popup_alignment_delegate.cc", - "system/web_notification/ash_popup_alignment_delegate.h", - "system/web_notification/fullscreen_notification_blocker.cc", - "system/web_notification/fullscreen_notification_blocker.h", - "system/web_notification/inactive_user_notification_blocker.cc", - "system/web_notification/inactive_user_notification_blocker.h", - "system/web_notification/session_state_notification_blocker.cc", - "system/web_notification/session_state_notification_blocker.h", - "system/web_notification/web_notification_tray.cc", - "system/web_notification/web_notification_tray.h", "touch/ash_touch_transform_controller.cc", "touch/ash_touch_transform_controller.h", "touch/touch_devices_controller.cc", @@ -1078,6 +1082,8 @@ "wm/splitview/split_view_divider.h", "wm/splitview/split_view_drag_indicators.cc", "wm/splitview/split_view_drag_indicators.h", + "wm/splitview/split_view_highlight_view.cc", + "wm/splitview/split_view_highlight_view.h", "wm/splitview/split_view_utils.cc", "wm/splitview/split_view_utils.h", "wm/stacking_controller.cc", @@ -1556,6 +1562,7 @@ "app_list/app_list_presenter_delegate_unittest.cc", "app_list/model/app_list_item_list_unittest.cc", "app_list/model/app_list_model_unittest.cc", + "assistant/ash_assistant_controller_unittest.cc", "autoclick/autoclick_unittest.cc", "detachable_base/detachable_base_handler_unittest.cc", "detachable_base/detachable_base_notification_controller_unittest.cc", @@ -1679,6 +1686,10 @@ "system/ime_menu/ime_menu_tray_unittest.cc", "system/keyboard_brightness/tray_keyboard_brightness_unittest.cc", "system/media_security/multi_profile_media_tray_item_unittest.cc", + "system/message_center/ash_popup_alignment_delegate_unittest.cc", + "system/message_center/inactive_user_notification_blocker_unittest.cc", + "system/message_center/notification_tray_unittest.cc", + "system/message_center/session_state_notification_blocker_unittest.cc", "system/network/network_icon_unittest.cc", "system/network/sms_observer_unittest.cc", "system/network/tray_network_unittest.cc", @@ -1735,10 +1746,6 @@ "system/unified/unified_system_info_view_unittest.cc", "system/update/tray_update_unittest.cc", "system/user/tray_user_unittest.cc", - "system/web_notification/ash_popup_alignment_delegate_unittest.cc", - "system/web_notification/inactive_user_notification_blocker_unittest.cc", - "system/web_notification/session_state_notification_blocker_unittest.cc", - "system/web_notification/web_notification_tray_unittest.cc", "test/ash_test_helper_unittest.cc", "test/ash_unittests.cc", "tooltips/tooltip_controller_unittest.cc", @@ -1780,6 +1787,7 @@ "wm/screen_pinning_controller_unittest.cc", "wm/session_state_animator_impl_unittest.cc", "wm/splitview/split_view_controller_unittest.cc", + "wm/splitview/split_view_highlight_view_unittest.cc", "wm/stacking_controller_unittest.cc", "wm/system_gesture_event_filter_unittest.cc", "wm/system_modal_container_layout_manager_unittest.cc", @@ -2088,6 +2096,8 @@ "wm/cursor_manager_test_api.h", "wm/lock_state_controller_test_api.cc", "wm/lock_state_controller_test_api.h", + "wm/splitview/split_view_highlight_view_test_api.cc", + "wm/splitview/split_view_highlight_view_test_api.h", "wm/test_activation_delegate.cc", "wm/test_activation_delegate.h", "wm/test_child_modal_parent.cc",
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 01ece8fb..12beafa 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -40,6 +40,7 @@ #include "ash/system/brightness_control_delegate.h" #include "ash/system/ime_menu/ime_menu_tray.h" #include "ash/system/keyboard_brightness_control_delegate.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/palette/palette_tray.h" #include "ash/system/palette/palette_utils.h" #include "ash/system/power/power_button_controller.h" @@ -49,7 +50,6 @@ #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/unified/unified_system_tray.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/touch/touch_hud_debug.h" #include "ash/utility/screenshot_controller.h" #include "ash/voice_interaction/voice_interaction_controller.h" @@ -409,7 +409,7 @@ StatusAreaWidget* status_area_widget = Shelf::ForWindow(target_root)->shelf_widget()->status_area_widget(); return status_area_widget && - status_area_widget->web_notification_tray()->visible(); + status_area_widget->notification_tray()->visible(); } void HandleToggleMessageCenterBubble() { @@ -419,8 +419,7 @@ Shelf::ForWindow(target_root)->shelf_widget()->status_area_widget(); if (!status_area_widget) return; - WebNotificationTray* notification_tray = - status_area_widget->web_notification_tray(); + NotificationTray* notification_tray = status_area_widget->notification_tray(); if (!notification_tray->visible()) return; if (notification_tray->IsMessageCenterVisible())
diff --git a/ash/accessibility/key_accessibility_enabler_unittest.cc b/ash/accessibility/key_accessibility_enabler_unittest.cc index 055c960..42146119 100644 --- a/ash/accessibility/key_accessibility_enabler_unittest.cc +++ b/ash/accessibility/key_accessibility_enabler_unittest.cc
@@ -7,7 +7,7 @@ #include "ash/accessibility/accessibility_controller.h" #include "ash/accessibility/accessibility_observer.h" #include "ash/shell.h" -#include "ash/system/web_notification/web_notification_tray.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/run_loop.h" @@ -23,7 +23,7 @@ KeyAccessibilityEnablerTest() {} void SetUp() override { - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); ui::SetEventTickClockForTesting(&clock_); AshTestBase::SetUp(); Shell::Get()->accessibility_controller()->AddObserver(this);
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 7fb4960..971b7451 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -750,7 +750,7 @@ </message> <message name="IDS_AURA_SET_DESKTOP_WALLPAPER" desc="The label used for change wallpaper in context menu"> - Set wallpaper... + Set wallpaper </message> <message name="IDS_ASH_STATUS_TRAY_TRACING" desc="The status tray item indicating that performance tracing is running.">
diff --git a/ash/assistant/ash_assistant_controller.cc b/ash/assistant/ash_assistant_controller.cc index 005aaf5..2fc222ed 100644 --- a/ash/assistant/ash_assistant_controller.cc +++ b/ash/assistant/ash_assistant_controller.cc
@@ -25,9 +25,11 @@ assistant_event_subscriber_binding_(this), assistant_bubble_(std::make_unique<AssistantBubble>(this)) { AddInteractionModelObserver(this); + Shell::Get()->highlighter_controller()->AddObserver(this); } AshAssistantController::~AshAssistantController() { + Shell::Get()->highlighter_controller()->RemoveObserver(this); RemoveInteractionModelObserver(this); assistant_controller_binding_.Close(); @@ -133,6 +135,15 @@ } } +void AshAssistantController::OnHighlighterEnabledChanged(bool enabled) { + // TODO(warx): add a reason enum to distinguish the case of deselecting the + // tool and done with a stylus selection. + assistant_bubble_timer_.Stop(); + assistant_interaction_model_.SetInputModality(InputModality::kStylus); + assistant_interaction_model_.SetInteractionState( + enabled ? InteractionState::kActive : InteractionState::kInactive); +} + void AshAssistantController::OnInteractionStarted() { assistant_bubble_timer_.Stop(); assistant_interaction_model_.SetInteractionState(InteractionState::kActive);
diff --git a/ash/assistant/ash_assistant_controller.h b/ash/assistant/ash_assistant_controller.h index 6e6f5c1..e21df13 100644 --- a/ash/assistant/ash_assistant_controller.h +++ b/ash/assistant/ash_assistant_controller.h
@@ -11,6 +11,7 @@ #include "ash/assistant/model/assistant_interaction_model.h" #include "ash/assistant/model/assistant_interaction_model_observer.h" +#include "ash/highlighter/highlighter_controller.h" #include "ash/public/interfaces/ash_assistant_controller.mojom.h" #include "ash/public/interfaces/assistant_card_renderer.mojom.h" #include "base/macros.h" @@ -30,7 +31,8 @@ class AshAssistantController : public mojom::AshAssistantController, public chromeos::assistant::mojom::AssistantEventSubscriber, - public AssistantInteractionModelObserver { + public AssistantInteractionModelObserver, + public HighlighterController::Observer { public: AshAssistantController(); ~AshAssistantController() override; @@ -81,6 +83,9 @@ // AssistantInteractionModelObserver: void OnInteractionStateChanged(InteractionState interaction_state) override; + // HighlighterController::Observer: + void OnHighlighterEnabledChanged(bool enabled) override; + // chromeos::assistant::mojom::AssistantEventSubscriber: void OnInteractionStarted() override; void OnInteractionFinished(
diff --git a/ash/assistant/ash_assistant_controller_unittest.cc b/ash/assistant/ash_assistant_controller_unittest.cc new file mode 100644 index 0000000..5d0c25e --- /dev/null +++ b/ash/assistant/ash_assistant_controller_unittest.cc
@@ -0,0 +1,54 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/assistant/ash_assistant_controller.h" + +#include "ash/highlighter/highlighter_controller.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "base/macros.h" +#include "base/test/scoped_feature_list.h" +#include "chromeos/chromeos_switches.h" + +namespace ash { + +class AshAssistantControllerTest : public AshTestBase { + protected: + AshAssistantControllerTest() = default; + ~AshAssistantControllerTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + chromeos::switches::kAssistantFeature); + ASSERT_TRUE(chromeos::switches::IsAssistantEnabled()); + AshTestBase::SetUp(); + controller_ = Shell::Get()->ash_assistant_controller(); + DCHECK(controller_); + } + + const AssistantInteractionModel* interaction_model() { + return controller_->interaction_model(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + AshAssistantController* controller_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(AshAssistantControllerTest); +}; + +TEST_F(AshAssistantControllerTest, HighlighterEnabledStatus) { + HighlighterController* highlighter_controller = + Shell::Get()->highlighter_controller(); + highlighter_controller->SetEnabled(true); + EXPECT_EQ(InputModality::kStylus, interaction_model()->input_modality()); + EXPECT_EQ(InteractionState::kActive, + interaction_model()->interaction_state()); + + highlighter_controller->SetEnabled(false); + EXPECT_EQ(InteractionState::kInactive, + interaction_model()->interaction_state()); +} + +} // namespace ash
diff --git a/ash/assistant/ui/assistant_bubble.cc b/ash/assistant/ui/assistant_bubble.cc index 5ca6f36..d6f3757 100644 --- a/ash/assistant/ui/assistant_bubble.cc +++ b/ash/assistant/ui/assistant_bubble.cc
@@ -69,10 +69,17 @@ int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; } + void RequestFocus() override { + if (assistant_bubble_view_) + assistant_bubble_view_->RequestFocus(); + } + private: void InitLayout() { SetLayoutManager(std::make_unique<views::FillLayout>()); - AddChildView(new AssistantBubbleView(assistant_controller_)); + + assistant_bubble_view_ = new AssistantBubbleView(assistant_controller_); + AddChildView(assistant_bubble_view_); } void SetAnchor() { @@ -89,7 +96,10 @@ SetAnchorRect(anchor); } - AshAssistantController* assistant_controller_; // Owned by Shell. + AshAssistantController* const assistant_controller_; // Owned by Shell. + + // Owned by view hierarchy. + AssistantBubbleView* assistant_bubble_view_ = nullptr; DISALLOW_COPY_AND_ASSIGN(AssistantContainerView); }; @@ -110,8 +120,14 @@ container_view_->GetWidget()->RemoveObserver(this); } -void AssistantBubble::OnWidgetClosing(views::Widget* widget) { - widget->RemoveObserver(this); +void AssistantBubble::OnWidgetActivationChanged(views::Widget* widget, + bool active) { + if (active) + container_view_->RequestFocus(); +} + +void AssistantBubble::OnWidgetDestroying(views::Widget* widget) { + container_view_->GetWidget()->RemoveObserver(this); container_view_ = nullptr; } @@ -128,16 +144,16 @@ } void AssistantBubble::Show() { - if (!container_view_) + if (!container_view_) { container_view_ = new AssistantContainerView(assistant_controller_); - - container_view_->GetWidget()->AddObserver(this); - container_view_->GetWidget()->ShowInactive(); + container_view_->GetWidget()->AddObserver(this); + } + container_view_->GetWidget()->Show(); } void AssistantBubble::Dismiss() { if (container_view_) - container_view_->GetWidget()->Close(); + container_view_->GetWidget()->Hide(); } } // namespace ash
diff --git a/ash/assistant/ui/assistant_bubble.h b/ash/assistant/ui/assistant_bubble.h index 9830200..e7ddccb 100644 --- a/ash/assistant/ui/assistant_bubble.h +++ b/ash/assistant/ui/assistant_bubble.h
@@ -28,7 +28,8 @@ ~AssistantBubble() override; // views::WidgetObserver: - void OnWidgetClosing(views::Widget* widget) override; + void OnWidgetActivationChanged(views::Widget* widget, bool active) override; + void OnWidgetDestroying(views::Widget* widget) override; // AssistantInteractionModelObserver: void OnInteractionStateChanged(InteractionState interaction_state) override;
diff --git a/ash/assistant/ui/assistant_bubble_view.cc b/ash/assistant/ui/assistant_bubble_view.cc index 7c2fa3a..f00c2fd 100644 --- a/ash/assistant/ui/assistant_bubble_view.cc +++ b/ash/assistant/ui/assistant_bubble_view.cc
@@ -360,6 +360,7 @@ new InteractionContainer(assistant_controller->interaction_model())), ui_element_container_(new UiElementContainer()), suggestions_container_(new SuggestionsContainer(this)), + dialog_plate_(new DialogPlate(assistant_controller)), render_request_weak_factory_(this) { InitLayout(); @@ -384,13 +385,26 @@ } void AssistantBubbleView::ChildVisibilityChanged(views::View* child) { + // When toggling the visibility of the dialog plate, we also need to update + // the bottom padding of the layout. + if (child == dialog_plate_) { + const int padding_bottom_dip = dialog_plate_->visible() ? 0 : kPaddingDip; + layout_manager_->set_inside_border_insets( + gfx::Insets(kPaddingDip, 0, padding_bottom_dip, 0)); + } PreferredSizeChanged(); } void AssistantBubbleView::InitLayout() { - SetLayoutManager(std::make_unique<views::BoxLayout>( + // Dialog plate is not visible when using the stylus input modality. + const bool show_dialog_plate = + assistant_controller_->interaction_model()->input_modality() != + InputModality::kStylus; + + layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, - gfx::Insets(kPaddingDip, 0, 0, 0), kSpacingDip)); + gfx::Insets(kPaddingDip, 0, show_dialog_plate ? 0 : kPaddingDip, 0), + kSpacingDip)); // Interaction container. AddChildView(interaction_container_); @@ -404,7 +418,8 @@ AddChildView(suggestions_container_); // Dialog plate. - AddChildView(new DialogPlate(assistant_controller_)); + dialog_plate_->SetVisible(show_dialog_plate); + AddChildView(dialog_plate_); } void AssistantBubbleView::SetProcessingUiElement(bool is_processing) { @@ -429,6 +444,9 @@ } void AssistantBubbleView::OnInputModalityChanged(InputModality input_modality) { + // Dialog plate is not visible when using stylus input modality. + dialog_plate_->SetVisible(input_modality != InputModality::kStylus); + // If the query for the interaction is empty, we may need to update the prompt // to reflect the current input modality. if (assistant_controller_->interaction_model()->query().empty()) { @@ -553,4 +571,8 @@ ui_element_container_->SetVisible(true); } +void AssistantBubbleView::RequestFocus() { + dialog_plate_->RequestFocus(); +} + } // namespace ash
diff --git a/ash/assistant/ui/assistant_bubble_view.h b/ash/assistant/ui/assistant_bubble_view.h index 80013522..e288a315 100644 --- a/ash/assistant/ui/assistant_bubble_view.h +++ b/ash/assistant/ui/assistant_bubble_view.h
@@ -15,12 +15,17 @@ #include "ui/app_list/views/suggestion_chip_view.h" #include "ui/views/view.h" +namespace views { +class BoxLayout; +} // namespace views + namespace ash { class AshAssistantController; class AssistantCardElement; class AssistantTextElement; class AssistantUiElement; +class DialogPlate; namespace { class InteractionContainer; @@ -39,6 +44,7 @@ gfx::Size CalculatePreferredSize() const override; void ChildPreferredSizeChanged(views::View* child) override; void ChildVisibilityChanged(views::View* child) override; + void RequestFocus() override; // AssistantInteractionModelObserver: void OnInputModalityChanged(InputModality input_modality) override; @@ -73,6 +79,9 @@ InteractionContainer* interaction_container_; // Owned by view hierarchy. UiElementContainer* ui_element_container_; // Owned by view hierarchy. SuggestionsContainer* suggestions_container_; // Owned by view hierarchy. + DialogPlate* dialog_plate_; // Owned by view hierarchy. + + views::BoxLayout* layout_manager_ = nullptr; // Owned by view hierarchy. // Uniquely identifies cards owned by AssistantCardRenderer. std::vector<base::UnguessableToken> id_token_list_;
diff --git a/ash/assistant/ui/dialog_plate.cc b/ash/assistant/ui/dialog_plate.cc index 177636d0..b70c9b5 100644 --- a/ash/assistant/ui/dialog_plate.cc +++ b/ash/assistant/ui/dialog_plate.cc
@@ -68,7 +68,9 @@ // DialogPlate ----------------------------------------------------------------- DialogPlate::DialogPlate(AshAssistantController* assistant_controller) - : assistant_controller_(assistant_controller), icon_(new views::View()) { + : assistant_controller_(assistant_controller), + textfield_(new views::Textfield()), + icon_(new views::View()) { InitLayout(); // The Assistant controller indirectly owns the view hierarchy to which @@ -93,18 +95,17 @@ views::Textfield::GetDefaultFontList().DeriveWithSizeDelta(4); // Textfield. - views::Textfield* textfield = new views::Textfield(); - textfield->SetBackgroundColor(SK_ColorTRANSPARENT); - textfield->SetBorder(views::NullBorder()); - textfield->set_controller(this); - textfield->SetFontList(font_list); - textfield->set_placeholder_font_list(font_list); - textfield->set_placeholder_text(base::UTF8ToUTF16(kHint)); - textfield->set_placeholder_text_color(kTextColorHint); - textfield->SetTextColor(kTextColorPrimary); - AddChildView(textfield); + textfield_->SetBackgroundColor(SK_ColorTRANSPARENT); + textfield_->SetBorder(views::NullBorder()); + textfield_->set_controller(this); + textfield_->SetFontList(font_list); + textfield_->set_placeholder_font_list(font_list); + textfield_->set_placeholder_text(base::UTF8ToUTF16(kHint)); + textfield_->set_placeholder_text_color(kTextColorHint); + textfield_->SetTextColor(kTextColorPrimary); + AddChildView(textfield_); - layout->SetFlexForView(textfield, 1); + layout->SetFlexForView(textfield_, 1); // TODO(dmblack): Replace w/ stateful icon. // Icon. @@ -186,4 +187,8 @@ SchedulePaint(); } +void DialogPlate::RequestFocus() { + textfield_->RequestFocus(); +} + } // namespace ash
diff --git a/ash/assistant/ui/dialog_plate.h b/ash/assistant/ui/dialog_plate.h index b550a54..8d2a793 100644 --- a/ash/assistant/ui/dialog_plate.h +++ b/ash/assistant/ui/dialog_plate.h
@@ -21,6 +21,9 @@ explicit DialogPlate(AshAssistantController* assistant_controller); ~DialogPlate() override; + // views::View: + void RequestFocus() override; + // AssistantInteractionModelObserver: void OnInputModalityChanged(InputModality input_modality) override; void OnMicStateChanged(MicState mic_state) override; @@ -36,6 +39,7 @@ void UpdateIcon(); AshAssistantController* const assistant_controller_; // Owned by Shell. + views::Textfield* textfield_; // Owned by view hierarchy. views::View* icon_; // Owned by view hierarchy. DISALLOW_COPY_AND_ASSIGN(DialogPlate);
diff --git a/ash/display/cros_display_config.cc b/ash/display/cros_display_config.cc index 451c544..20af98b 100644 --- a/ash/display/cros_display_config.cc +++ b/ash/display/cros_display_config.cc
@@ -292,8 +292,10 @@ info->display_zoom_factor = display_info.zoom_factor(); if (has_active_mode) { - info->available_display_zoom_factors = - display::GetDisplayZoomFactors(active_mode); + const auto zoom_levels = display::GetDisplayZoomFactors(active_mode); + info->available_display_zoom_factors.assign(zoom_levels.begin(), + zoom_levels.end()); + } else { info->available_display_zoom_factors.push_back(display_info.zoom_factor()); }
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index 008efbd..932818a 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc
@@ -1403,7 +1403,7 @@ display_manager()->UpdateDisplays(); // Enumerate the zoom factors for display. - const std::vector<double> zoom_factors_1 = + const std::vector<float> zoom_factors_1 = display::GetDisplayZoomFactors(modes_1[0]); // Set the zoom factor to one of the enumerated zoom factors for the said @@ -1413,36 +1413,36 @@ zoom_factors_1[zoom_factor_idx_1]); // Make sure the chage was successful. - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), - zoom_factors_1[zoom_factor_idx_1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + zoom_factors_1[zoom_factor_idx_1]); // Zoom out the display. This should have no effect, since the display is // already at the minimum zoom level. display_manager()->ZoomDisplay(info_1.id(), true /* up */); - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), - zoom_factors_1[zoom_factor_idx_1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + zoom_factors_1[zoom_factor_idx_1]); // Ensure that this call did not modify the zoom value for the other display. - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), 1.f, - 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), + 1.f); // Zoom in the display. display_manager()->ZoomDisplay(info_1.id(), false /* up */); // The zoom factor for the display should be set to the next zoom factor in // list. - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), - zoom_factors_1[zoom_factor_idx_1 + 1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + zoom_factors_1[zoom_factor_idx_1 + 1]); // Zoom out the display. display_manager()->ZoomDisplay(info_1.id(), true /* up */); // The zoom level should decrease from the previous level. - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), - zoom_factors_1[zoom_factor_idx_1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + zoom_factors_1[zoom_factor_idx_1]); // Enumerate the zoom factors for display. - const std::vector<double> zoom_factors_2 = + const std::vector<float> zoom_factors_2 = display::GetDisplayZoomFactors(modes_2[0]); // Set the zoom factor to one of the enumerated zoom factors for the said @@ -1452,38 +1452,38 @@ zoom_factors_2[zoom_factor_idx_2]); // Make sure the chage was successful. - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), - zoom_factors_2[zoom_factor_idx_2], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), + zoom_factors_2[zoom_factor_idx_2]); // Zoom in the display. This should have no effect since we are already at // maximum zoom. display_manager()->ZoomDisplay(info_2.id(), false /* up */); - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), - zoom_factors_2[zoom_factor_idx_2], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), + zoom_factors_2[zoom_factor_idx_2]); // Zoom out the display display_manager()->ZoomDisplay(info_2.id(), true /* up */); - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), - zoom_factors_2[zoom_factor_idx_2 - 1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), + zoom_factors_2[zoom_factor_idx_2 - 1]); // Ensure that this call did not modify the zoom value for the other display. - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), - zoom_factors_1[zoom_factor_idx_1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + zoom_factors_1[zoom_factor_idx_1]); // Reset the zoom value for displays. display_manager()->ResetDisplayZoom(info_1.id()); - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), 1.f, - 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + 1.f); // Resetting the zoom level of one display should not effect the other display - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), - zoom_factors_2[zoom_factor_idx_2 - 1], 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), + zoom_factors_2[zoom_factor_idx_2 - 1]); // Now reset the zoom value for other display. display_manager()->ResetDisplayZoom(info_2.id()); - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), 1.f, - 0.001f); - EXPECT_NEAR(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), 1.f, - 0.001f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_2.id()).zoom_factor(), + 1.f); + EXPECT_FLOAT_EQ(display_manager()->GetDisplayInfo(info_1.id()).zoom_factor(), + 1.f); } TEST_F(DisplayManagerTest, TestDeviceScaleOnlyChange) {
diff --git a/ash/display/display_prefs.cc b/ash/display/display_prefs.cc index 34c4de2..8dcd6d26 100644 --- a/ash/display/display_prefs.cc +++ b/ash/display/display_prefs.cc
@@ -83,7 +83,7 @@ constexpr char kMirroringSourceId[] = "mirroring_source_id"; constexpr char kMirroringDestinationIds[] = "mirroring_destination_ids"; -constexpr char kDisplayZoom[] = "display_zoom"; +constexpr char kDisplayZoom[] = "display_zoom_factor"; constexpr char kDisplayPowerAllOn[] = "all_on"; constexpr char kDisplayPowerInternalOffExternalOn[] = @@ -282,14 +282,12 @@ if (ValueToInsets(*dict_value, &insets)) insets_to_set = &insets; - // Set the default zoom percentage to 100. - int display_zoom_percentage = 100; - dict_value->GetInteger(kDisplayZoom, &display_zoom_percentage); + double display_zoom = 1.0; + dict_value->GetDouble(kDisplayZoom, &display_zoom); GetDisplayManager()->RegisterDisplayProperty( id, rotation, ui_scale, insets_to_set, resolution_in_pixels, - device_scale_factor, - static_cast<float>(display_zoom_percentage) / 100.f); + device_scale_factor, display_zoom); } } @@ -577,10 +575,7 @@ property_value.get()); } - // Store the display zoom as a percentage. - int display_zoom_percentage = std::round(info.zoom_factor() * 100.f); - - property_value->SetInteger(kDisplayZoom, display_zoom_percentage); + property_value->SetDouble(kDisplayZoom, info.zoom_factor()); pref_data->Set(base::Int64ToString(id), std::move(property_value)); }
diff --git a/ash/display/display_prefs_unittest.cc b/ash/display/display_prefs_unittest.cc index 1b124cd..b0bc64f 100644 --- a/ash/display/display_prefs_unittest.cc +++ b/ash/display/display_prefs_unittest.cc
@@ -467,7 +467,7 @@ 1.0 /* ui_scale */, 1.25f /* device_scale_factor */); display_manager()->SetDisplayMode(id2, mode); - float zoom_factor_1 = 1.75f; + float zoom_factor_1 = 1.f / 2.25f; float zoom_factor_2 = 1.60f; display_manager()->UpdateZoomFactor(id1, zoom_factor_1); display_manager()->UpdateZoomFactor(id2, zoom_factor_2); @@ -483,9 +483,9 @@ EXPECT_FALSE(property->GetInteger("width", &width)); EXPECT_FALSE(property->GetInteger("height", &height)); - int display_zoom_1; - EXPECT_TRUE(property->GetInteger("display_zoom", &display_zoom_1)); - EXPECT_EQ(display_zoom_1, static_cast<int>(zoom_factor_1 * 100)); + double display_zoom_1; + EXPECT_TRUE(property->GetDouble("display_zoom_factor", &display_zoom_1)); + EXPECT_NEAR(display_zoom_1, zoom_factor_1, 0.0001); // External display's resolution must be stored this time because // it's not best. @@ -499,9 +499,9 @@ EXPECT_EQ(200, height); EXPECT_EQ(1250, device_scale_factor); - int display_zoom_2; - EXPECT_TRUE(property->GetInteger("display_zoom", &display_zoom_2)); - EXPECT_EQ(display_zoom_2, static_cast<int>(zoom_factor_2 * 100)); + double display_zoom_2; + EXPECT_TRUE(property->GetDouble("display_zoom_factor", &display_zoom_2)); + EXPECT_NEAR(display_zoom_2, zoom_factor_2, 0.0001); // The layout is swapped. EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc b/ash/frame/custom_frame_header.cc similarity index 72% rename from chrome/browser/ui/views/frame/browser_frame_header_ash.cc rename to ash/frame/custom_frame_header.cc index 933f6846..216c342 100644 --- a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc +++ b/ash/frame/custom_frame_header.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/frame/browser_frame_header_ash.h" +#include "ash/frame/custom_frame_header.h" #include "ash/ash_layout_constants.h" #include "ash/frame/caption_buttons/frame_caption_button.h" @@ -25,6 +25,8 @@ #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" +namespace ash { + namespace { // Color for the window title text. @@ -100,47 +102,40 @@ } // namespace /////////////////////////////////////////////////////////////////////////////// -// BrowserFrameHeaderAsh, public: +// CustomFrameHeader, public: -BrowserFrameHeaderAsh::BrowserFrameHeaderAsh() = default; +CustomFrameHeader::CustomFrameHeader() = default; -BrowserFrameHeaderAsh::~BrowserFrameHeaderAsh() = default; +CustomFrameHeader::~CustomFrameHeader() = default; -void BrowserFrameHeaderAsh::Init( +void CustomFrameHeader::Init( views::View* view, AppearanceProvider* appearance_provider, bool incognito, - views::View* window_icon, - ash::FrameCaptionButtonContainerView* caption_button_container, - ash::FrameCaptionButton* back_button) { + FrameCaptionButtonContainerView* caption_button_container) { DCHECK(view); DCHECK(appearance_provider); - // window_icon may be null. DCHECK(caption_button_container); - // back_button may be null. view_ = view; appearance_provider_ = appearance_provider; is_incognito_ = incognito; - window_icon_ = window_icon; caption_button_container_ = caption_button_container; - back_button_ = back_button; } -int BrowserFrameHeaderAsh::GetMinimumHeaderWidth() const { +int CustomFrameHeader::GetMinimumHeaderWidth() const { // Ensure we have enough space for the window icon and buttons. We allow // the title string to collapse to zero width. return GetTitleBounds().x() + caption_button_container_->GetMinimumSize().width(); } -void BrowserFrameHeaderAsh::PaintHeader(gfx::Canvas* canvas, Mode mode) { +void CustomFrameHeader::PaintHeader(gfx::Canvas* canvas, Mode mode) { Mode old_mode = mode_; mode_ = mode; if (mode_ != old_mode) { - if (!initial_paint_ && - ash::FrameHeaderUtil::CanAnimateActivation(GetWidget())) { + if (!initial_paint_ && FrameHeaderUtil::CanAnimateActivation(GetWidget())) { activation_animation_.SetSlideDuration(kActivationCrossfadeDurationMs); if (mode_ == MODE_ACTIVE) activation_animation_.Show(); @@ -164,31 +159,30 @@ } } -void BrowserFrameHeaderAsh::LayoutHeader() { - // Purposefully set |painted_height_| to an invalid value. We cannot use - // |painted_height_| because the computation of |painted_height_| may depend - // on having laid out the window controls. - painted_height_ = -1; +void CustomFrameHeader::LayoutHeader() { LayoutHeaderInternal(); + // Default to the header height; owning code may override via + // SetHeaderHeightForPainting(). + painted_height_ = GetHeaderHeight(); } -int BrowserFrameHeaderAsh::GetHeaderHeight() const { +int CustomFrameHeader::GetHeaderHeight() const { return caption_button_container_->height(); } -int BrowserFrameHeaderAsh::GetHeaderHeightForPainting() const { +int CustomFrameHeader::GetHeaderHeightForPainting() const { return painted_height_; } -void BrowserFrameHeaderAsh::SetHeaderHeightForPainting(int height) { +void CustomFrameHeader::SetHeaderHeightForPainting(int height) { painted_height_ = height; } -void BrowserFrameHeaderAsh::SchedulePaintForTitle() { +void CustomFrameHeader::SchedulePaintForTitle() { view_->SchedulePaintInRect(GetTitleBounds()); } -void BrowserFrameHeaderAsh::SetPaintAsActive(bool paint_as_active) { +void CustomFrameHeader::SetPaintAsActive(bool paint_as_active) { SkColor frame_color = appearance_provider_->GetFrameHeaderColor(paint_as_active); caption_button_container_->SetPaintAsActive(paint_as_active); @@ -199,7 +193,7 @@ } } -void BrowserFrameHeaderAsh::OnShowStateChanged(ui::WindowShowState show_state) { +void CustomFrameHeader::OnShowStateChanged(ui::WindowShowState show_state) { if (show_state == ui::SHOW_STATE_MINIMIZED) return; // Call LayoutHeaderInternal() instead of LayoutHeader() here because @@ -207,18 +201,34 @@ LayoutHeaderInternal(); } -/////////////////////////////////////////////////////////////////////////////// -// gfx::AnimationDelegate overrides: +void CustomFrameHeader::SetLeftHeaderView(views::View* left_header_view) { + window_icon_ = left_header_view; +} -void BrowserFrameHeaderAsh::AnimationProgressed( - const gfx::Animation* animation) { +void CustomFrameHeader::SetBackButton(FrameCaptionButton* back_button) { + back_button_ = back_button; +} + +FrameCaptionButton* CustomFrameHeader::GetBackButton() const { + return back_button_; +} + +void CustomFrameHeader::SetFrameColors(SkColor active_frame_color, + SkColor inactive_frame_color) { view_->SchedulePaintInRect(GetPaintedBounds()); } /////////////////////////////////////////////////////////////////////////////// -// BrowserFrameHeaderAsh, private: +// gfx::AnimationDelegate overrides: -void BrowserFrameHeaderAsh::LayoutHeaderInternal() { +void CustomFrameHeader::AnimationProgressed(const gfx::Animation* animation) { + view_->SchedulePaintInRect(GetPaintedBounds()); +} + +/////////////////////////////////////////////////////////////////////////////// +// CustomFrameHeader, private: + +void CustomFrameHeader::LayoutHeaderInternal() { UpdateCaptionButtons(); const gfx::Size caption_button_container_size = caption_button_container_->GetPreferredSize(); @@ -236,11 +246,11 @@ // container. const gfx::Size icon_size(window_icon_->GetPreferredSize()); const int icon_offset_y = (GetHeaderHeight() - icon_size.height()) / 2; - window_icon_->SetBounds(ash::FrameHeaderUtil::GetLeftViewXInset(), - icon_offset_y, icon_size.width(), icon_size.height()); + window_icon_->SetBounds(FrameHeaderUtil::GetLeftViewXInset(), icon_offset_y, + icon_size.width(), icon_size.height()); } -void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) { +void CustomFrameHeader::PaintFrameImages(gfx::Canvas* canvas, bool active) { int alpha = activation_animation_.CurrentValueBetween(0, 0xFF); if (!active) alpha = 0xFF - alpha; @@ -257,15 +267,15 @@ int corner_radius = 0; if (!GetWidget()->IsMaximized() && !GetWidget()->IsFullscreen()) - corner_radius = ash::FrameHeaderUtil::GetTopCornerRadiusWhenRestored(); + corner_radius = FrameHeaderUtil::GetTopCornerRadiusWhenRestored(); PaintFrameImagesInRoundRect(canvas, frame_image, frame_overlay_image, alpha, background_color, GetPaintedBounds(), corner_radius, - ash::FrameHeaderUtil::GetThemeBackgroundXInset()); + FrameHeaderUtil::GetThemeBackgroundXInset()); } -void BrowserFrameHeaderAsh::PaintTitleBar(gfx::Canvas* canvas) { +void CustomFrameHeader::PaintTitleBar(gfx::Canvas* canvas) { // The window icon is painted by its own views::View. canvas->DrawStringRectWithFlags( GetWidget()->widget_delegate()->GetWindowTitle(), @@ -276,21 +286,19 @@ gfx::Canvas::NO_SUBPIXEL_RENDERING); } -void BrowserFrameHeaderAsh::UpdateCaptionButtons() { +void CustomFrameHeader::UpdateCaptionButtons() { // When |frame_| minimized, avoid tablet mode toggling to update caption // buttons as it would cause mismatch beteen window state and size button. if (GetWidget()->IsMinimized()) return; - caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_MINIMIZE, - ash::kWindowControlMinimizeIcon); - caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_CLOSE, - ash::kWindowControlCloseIcon); - caption_button_container_->SetButtonImage( - ash::CAPTION_BUTTON_ICON_LEFT_SNAPPED, - ash::kWindowControlLeftSnappedIcon); - caption_button_container_->SetButtonImage( - ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED, - ash::kWindowControlRightSnappedIcon); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_MINIMIZE, + kWindowControlMinimizeIcon); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_CLOSE, + kWindowControlCloseIcon); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_LEFT_SNAPPED, + kWindowControlLeftSnappedIcon); + caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_RIGHT_SNAPPED, + kWindowControlRightSnappedIcon); const bool is_maximized_or_fullscreen = GetWidget()->IsMaximized() || GetWidget()->IsFullscreen(); @@ -298,25 +306,27 @@ is_maximized_or_fullscreen || appearance_provider_->IsTabletMode() ? AshLayoutSize::kBrowserCaptionMaximized : AshLayoutSize::kBrowserCaptionRestored; - const gfx::VectorIcon* const size_icon = - is_maximized_or_fullscreen ? &ash::kWindowControlRestoreIcon - : &ash::kWindowControlMaximizeIcon; + const gfx::VectorIcon* const size_icon = is_maximized_or_fullscreen + ? &kWindowControlRestoreIcon + : &kWindowControlMaximizeIcon; caption_button_container_->SetButtonImage( - ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, *size_icon); + CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, *size_icon); caption_button_container_->SetButtonSize(GetAshLayoutSize(button_size_type)); } -gfx::Rect BrowserFrameHeaderAsh::GetPaintedBounds() const { +gfx::Rect CustomFrameHeader::GetPaintedBounds() const { return gfx::Rect(view_->width(), painted_height_); } -gfx::Rect BrowserFrameHeaderAsh::GetTitleBounds() const { +gfx::Rect CustomFrameHeader::GetTitleBounds() const { views::View* left_view = window_icon_ ? window_icon_ : back_button_; - return ash::FrameHeaderUtil::GetAvailableTitleBounds( + return FrameHeaderUtil::GetAvailableTitleBounds( left_view, caption_button_container_, GetHeaderHeight()); } -views::Widget* BrowserFrameHeaderAsh::GetWidget() { +views::Widget* CustomFrameHeader::GetWidget() { return view_->GetWidget(); } + +} // namespace ash
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.h b/ash/frame/custom_frame_header.h similarity index 74% rename from chrome/browser/ui/views/frame/browser_frame_header_ash.h rename to ash/frame/custom_frame_header.h index 0a7db2d..8eaa05b1 100644 --- a/chrome/browser/ui/views/frame/browser_frame_header_ash.h +++ b/ash/frame/custom_frame_header.h
@@ -2,43 +2,47 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_HEADER_ASH_H_ -#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_HEADER_ASH_H_ +#ifndef ASH_FRAME_CUSTOM_FRAME_HEADER_H_ +#define ASH_FRAME_CUSTOM_FRAME_HEADER_H_ +#include "ash/ash_export.h" #include "ash/frame/frame_header.h" #include "base/callback.h" #include "base/macros.h" #include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/animation/slide_animation.h" -namespace ash { -class FrameCaptionButton; -class FrameCaptionButtonContainerView; -} // namespace ash - namespace gfx { class ImageSkia; class Rect; } // namespace gfx + namespace views { class View; class Widget; } // namespace views -// Helper class for managing the browser window header. -class BrowserFrameHeaderAsh : public ash::FrameHeader, - public gfx::AnimationDelegate { +namespace ash { + +class FrameCaptionButton; +class FrameCaptionButtonContainerView; + +// Helper class for drawing a custom frame (such as for a themed Chrome Browser +// frame). +class ASH_EXPORT CustomFrameHeader : public FrameHeader, + public gfx::AnimationDelegate { public: class AppearanceProvider { public: + virtual ~AppearanceProvider() = default; virtual SkColor GetFrameHeaderColor(bool active) = 0; virtual gfx::ImageSkia GetFrameHeaderImage(bool active) = 0; virtual gfx::ImageSkia GetFrameHeaderOverlayImage(bool active) = 0; virtual bool IsTabletMode() = 0; }; - BrowserFrameHeaderAsh(); - ~BrowserFrameHeaderAsh() override; + CustomFrameHeader(); + ~CustomFrameHeader() override; // BrowserFrameHeaderAsh does not take ownership of any of the parameters. // |view| is the view into which |this| will paint. |back_button| can be @@ -46,11 +50,9 @@ void Init(views::View* view, AppearanceProvider* appearance_provider, bool incognito, - views::View* window_icon, - ash::FrameCaptionButtonContainerView* caption_button_container, - ash::FrameCaptionButton* back_button); + FrameCaptionButtonContainerView* caption_button_container); - // ash::FrameHeader overrides: + // FrameHeader overrides: int GetMinimumHeaderWidth() const override; void PaintHeader(gfx::Canvas* canvas, Mode mode) override; void LayoutHeader() override; @@ -60,6 +62,11 @@ void SchedulePaintForTitle() override; void SetPaintAsActive(bool paint_as_active) override; void OnShowStateChanged(ui::WindowShowState show_state) override; + void SetLeftHeaderView(views::View* left_header_view) override; + void SetBackButton(FrameCaptionButton* back_button) override; + FrameCaptionButton* GetBackButton() const override; + void SetFrameColors(SkColor active_frame_color, + SkColor inactive_frame_color) override; private: // gfx::AnimationDelegate override: @@ -98,8 +105,8 @@ bool is_incognito_ = false; views::View* window_icon_ = nullptr; - ash::FrameCaptionButton* back_button_ = nullptr; - ash::FrameCaptionButtonContainerView* caption_button_container_ = nullptr; + FrameCaptionButton* back_button_ = nullptr; + FrameCaptionButtonContainerView* caption_button_container_ = nullptr; int painted_height_ = 0; // Whether the header is painted for the first time. @@ -110,7 +117,9 @@ gfx::SlideAnimation activation_animation_{this}; - DISALLOW_COPY_AND_ASSIGN(BrowserFrameHeaderAsh); + DISALLOW_COPY_AND_ASSIGN(CustomFrameHeader); }; -#endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_HEADER_ASH_H_ +} // namespace ash + +#endif // ASH_FRAME_CUSTOM_FRAME_HEADER_H_
diff --git a/ash/frame/custom_frame_view_ash.cc b/ash/frame/custom_frame_view_ash.cc index dc1a0e5b..27249f34 100644 --- a/ash/frame/custom_frame_view_ash.cc +++ b/ash/frame/custom_frame_view_ash.cc
@@ -10,6 +10,7 @@ #include "ash/frame/caption_buttons/frame_caption_button.h" #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" +#include "ash/frame/default_frame_header.h" #include "ash/frame/frame_border_hit_test.h" #include "ash/frame/header_view.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" @@ -179,48 +180,6 @@ bool CustomFrameViewAsh::use_empty_minimum_size_for_test_ = false; /////////////////////////////////////////////////////////////////////////////// -// CustomFrameViewAsh::AvatarObserver - -// AvatarObserver watches the frame window's avatar icon property and updates -// HeaderView with it. -class CustomFrameViewAsh::AvatarObserver : public aura::WindowObserver { - public: - AvatarObserver(views::Widget* frame, HeaderView* header_view) - : frame_window_(frame->GetNativeWindow()), header_view_(header_view) { - frame_window_->AddObserver(this); - } - - ~AvatarObserver() override { - if (frame_window_) - frame_window_->RemoveObserver(this); - } - - // aura::WindowObserver: - void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) override { - DCHECK_EQ(frame_window_, window); - if (key != aura::client::kAvatarIconKey) - return; - - gfx::ImageSkia* const avatar_icon = - frame_window_->GetProperty(aura::client::kAvatarIconKey); - header_view_->SetAvatarIcon(avatar_icon ? *avatar_icon : gfx::ImageSkia()); - } - - void OnWindowDestroyed(aura::Window* window) override { - DCHECK_EQ(frame_window_, window); - frame_window_ = nullptr; - } - - private: - aura::Window* frame_window_; - HeaderView* const header_view_; - - DISALLOW_COPY_AND_ASSIGN(AvatarObserver); -}; - -/////////////////////////////////////////////////////////////////////////////// // CustomFrameViewAsh::OverlayView // View which takes up the entire widget and contains the HeaderView. HeaderView @@ -317,19 +276,18 @@ header_view_(new HeaderView(frame, window_style, std::move(model))), overlay_view_(new OverlayView(header_view_)), immersive_delegate_(immersive_delegate ? immersive_delegate - : header_view_), - avatar_observer_(std::make_unique<AvatarObserver>(frame_, header_view_)) { + : header_view_) { aura::Window* frame_window = frame->GetNativeWindow(); wm::InstallResizeHandleWindowTargeterForWindow(frame_window, nullptr); // |header_view_| is set as the non client view's overlay view so that it can // overlay the web contents in immersive fullscreen. frame->non_client_view()->SetOverlayView(overlay_view_); frame_window->SetProperty(aura::client::kTopViewColor, - header_view_->GetInactiveFrameColor()); + DefaultFrameHeader::GetDefaultFrameColor()); frame_window->SetProperty(ash::kFrameActiveColorKey, - header_view_->GetActiveFrameColor()); + DefaultFrameHeader::GetDefaultFrameColor()); frame_window->SetProperty(ash::kFrameInactiveColorKey, - header_view_->GetInactiveFrameColor()); + DefaultFrameHeader::GetDefaultFrameColor()); frame_window->AddObserver(this); // A delegate for a more complex way of fullscreening the window may already @@ -362,7 +320,6 @@ void CustomFrameViewAsh::SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color) { - header_view_->SetFrameColors(active_frame_color, inactive_frame_color); aura::Window* frame_window = frame_->GetNativeWindow(); frame_window->SetProperty(aura::client::kTopViewColor, inactive_frame_color); frame_window->SetProperty(ash::kFrameActiveColorKey, active_frame_color); @@ -428,7 +385,6 @@ void CustomFrameViewAsh::UpdateWindowIcon() {} void CustomFrameViewAsh::UpdateWindowTitle() { - header_view_->set_title(GetFrameTitle()); header_view_->SchedulePaintForTitle(); } @@ -527,19 +483,6 @@ if (key == aura::client::kShowStateKey) { header_view_->OnShowStateChanged( window->GetProperty(aura::client::kShowStateKey)); - return; - } - - if (key == ash::kFrameActiveColorKey) { - header_view_->SetFrameColors(window->GetProperty(ash::kFrameActiveColorKey), - header_view_->GetInactiveFrameColor()); - return; - } - - if (key == ash::kFrameInactiveColorKey) { - header_view_->SetFrameColors( - header_view_->GetActiveFrameColor(), - window->GetProperty(ash::kFrameInactiveColorKey)); } } @@ -548,11 +491,11 @@ } SkColor CustomFrameViewAsh::GetActiveFrameColorForTest() const { - return header_view_->GetActiveFrameColor(); + return frame_->GetNativeWindow()->GetProperty(ash::kFrameActiveColorKey); } SkColor CustomFrameViewAsh::GetInactiveFrameColorForTest() const { - return header_view_->GetInactiveFrameColor(); + return frame_->GetNativeWindow()->GetProperty(ash::kFrameInactiveColorKey); } void CustomFrameViewAsh::UpdateHeaderView() {
diff --git a/ash/frame/custom_frame_view_ash.h b/ash/frame/custom_frame_view_ash.h index a7af5ef..3c2d7ee 100644 --- a/ash/frame/custom_frame_view_ash.h +++ b/ash/frame/custom_frame_view_ash.h
@@ -144,7 +144,6 @@ void UpdateHeaderView(); private: - class AvatarObserver; class OverlayView; friend class CustomFrameViewAshSizeLock; friend class CustomFrameTestWidgetDelegate; @@ -171,9 +170,6 @@ ImmersiveFullscreenControllerDelegate* immersive_delegate_; - // Observes avatar icon change and updates |header_view_|. - std::unique_ptr<AvatarObserver> avatar_observer_; - static bool use_empty_minimum_size_for_test_; // Track whether the device is in overview mode. Set this to true when
diff --git a/ash/frame/default_frame_header.cc b/ash/frame/default_frame_header.cc index 3e8de22..e18a32b 100644 --- a/ash/frame/default_frame_header.cc +++ b/ash/frame/default_frame_header.cc
@@ -10,14 +10,12 @@ #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/frame/frame_header_util.h" #include "ash/public/cpp/vector_icons/vector_icons.h" -#include "ash/resources/grit/ash_resources.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/debug/leak_annotations.h" #include "base/logging.h" // DCHECK #include "third_party/skia/include/core/SkPath.h" -#include "ui/base/resource/resource_bundle.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" @@ -38,8 +36,6 @@ // Color for the window title text. const SkColor kTitleTextColor = SkColorSetRGB(40, 40, 40); const SkColor kLightTitleTextColor = SK_ColorWHITE; -// The default color of the frame. -const SkColor kDefaultFrameColor = SkColorSetRGB(0xFD, 0xFE, 0xFF); // Duration of crossfade animation for activating and deactivating frame. const int kActivationCrossfadeDurationMs = 200; @@ -73,15 +69,13 @@ DefaultFrameHeader::DefaultFrameHeader( views::Widget* frame, views::View* header_view, - FrameCaptionButtonContainerView* caption_button_container, - mojom::WindowStyle window_style) - : window_style_(window_style), - frame_(frame), + FrameCaptionButtonContainerView* caption_button_container) + : frame_(frame), view_(header_view), back_button_(nullptr), left_header_view_(nullptr), - active_frame_color_(kDefaultFrameColor), - inactive_frame_color_(kDefaultFrameColor), + active_frame_color_(GetDefaultFrameColor()), + inactive_frame_color_(GetDefaultFrameColor()), caption_button_container_(caption_button_container), painted_height_(0), mode_(MODE_INACTIVE), @@ -136,28 +130,11 @@ flags.setAntiAlias(true); TileRoundRect(canvas, flags, GetLocalBounds(), corner_radius); - if (!frame_->IsMaximized() && !frame_->IsFullscreen() && - mode_ == MODE_INACTIVE && !UsesCustomFrameColors()) { - PaintHighlightForInactiveRestoredWindow(canvas); - } - if (frame_->widget_delegate()->ShouldShowWindowTitle() && !title_.empty()) + if (frame_->widget_delegate()->ShouldShowWindowTitle() && !GetTitle().empty()) PaintTitleBar(canvas); } void DefaultFrameHeader::LayoutHeader() { - // TODO(sky): this needs to reset images as well. - if (window_style_ == mojom::WindowStyle::BROWSER) { - const bool is_in_tablet_mode = Shell::Get() - ->tablet_mode_controller() - ->IsTabletModeWindowManagerEnabled(); - const bool use_maximized_size = - frame_->IsMaximized() || frame_->IsFullscreen() || is_in_tablet_mode; - const gfx::Size button_size(GetAshLayoutSize( - use_maximized_size ? AshLayoutSize::kBrowserCaptionMaximized - : AshLayoutSize::kBrowserCaptionRestored)); - caption_button_container_->SetButtonSize(button_size); - } - caption_button_container_->SetBackgroundColor(GetCurrentFrameColor()); caption_button_container_->SetColorMode(button_color_mode_); UpdateSizeButtonImages(); @@ -222,6 +199,18 @@ LayoutHeader(); } +void DefaultFrameHeader::SetLeftHeaderView(views::View* left_header_view) { + left_header_view_ = left_header_view; +} + +void DefaultFrameHeader::SetBackButton(FrameCaptionButton* back_button) { + back_button_ = back_button; +} + +FrameCaptionButton* DefaultFrameHeader::GetBackButton() const { + return back_button_; +} + void DefaultFrameHeader::SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color) { button_color_mode_ = FrameCaptionButton::ColorMode::kDefault; @@ -233,10 +222,6 @@ SetFrameColorsImpl(theme_color, theme_color); } -SkColor DefaultFrameHeader::GetCurrentFrameColor() const { - return mode_ == MODE_ACTIVE ? active_frame_color_ : inactive_frame_color_; -} - void DefaultFrameHeader::SetFrameColorsImpl(SkColor active_frame_color, SkColor inactive_frame_color) { bool updated = false; @@ -255,19 +240,16 @@ } } -SkColor DefaultFrameHeader::GetActiveFrameColor() const { - return active_frame_color_; -} - -SkColor DefaultFrameHeader::GetInactiveFrameColor() const { - return inactive_frame_color_; -} - SkColor DefaultFrameHeader::GetTitleColor() const { return color_utils::IsDark(GetCurrentFrameColor()) ? kLightTitleTextColor : kTitleTextColor; } +// static +SkColor DefaultFrameHeader::GetDefaultFrameColor() { + return SkColorSetRGB(0xFD, 0xFE, 0xFF); +} + /////////////////////////////////////////////////////////////////////////////// // gfx::AnimationDelegate overrides: @@ -278,39 +260,11 @@ /////////////////////////////////////////////////////////////////////////////// // DefaultFrameHeader, private: -void DefaultFrameHeader::PaintHighlightForInactiveRestoredWindow( - gfx::Canvas* canvas) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - gfx::ImageSkia top_edge = - *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_TOP); - gfx::ImageSkia left_edge = - *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_LEFT); - gfx::ImageSkia right_edge = - *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_RIGHT); - gfx::ImageSkia bottom_edge = - *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM); - - int left_edge_width = left_edge.width(); - int right_edge_width = right_edge.width(); - canvas->DrawImageInt(left_edge, 0, 0); - canvas->DrawImageInt(right_edge, view_->width() - right_edge_width, 0); - canvas->TileImageInt(top_edge, left_edge_width, 0, - view_->width() - left_edge_width - right_edge_width, - top_edge.height()); - - DCHECK_EQ(left_edge.height(), right_edge.height()); - int bottom = left_edge.height(); - int bottom_height = bottom_edge.height(); - canvas->TileImageInt(bottom_edge, left_edge_width, bottom - bottom_height, - view_->width() - left_edge_width - right_edge_width, - bottom_height); -} - void DefaultFrameHeader::PaintTitleBar(gfx::Canvas* canvas) { // The window icon is painted by its own views::View. gfx::Rect title_bounds = GetAvailableTitleBounds(); title_bounds.set_x(view_->GetMirroredXForRect(title_bounds)); - canvas->DrawStringRect(title_, + canvas->DrawStringRect(GetTitle(), views::NativeWidgetAura::GetWindowTitleFontList(), GetTitleColor(), title_bounds); } @@ -371,9 +325,12 @@ left_view, caption_button_container_, GetHeaderHeight()); } -bool DefaultFrameHeader::UsesCustomFrameColors() const { - return active_frame_color_ != kDefaultFrameColor || - inactive_frame_color_ != kDefaultFrameColor; +base::string16 DefaultFrameHeader::GetTitle() const { + return frame_->widget_delegate()->GetWindowTitle(); +} + +SkColor DefaultFrameHeader::GetCurrentFrameColor() const { + return mode_ == MODE_ACTIVE ? active_frame_color_ : inactive_frame_color_; } } // namespace ash
diff --git a/ash/frame/default_frame_header.h b/ash/frame/default_frame_header.h index 7e541ce..59fcc12 100644 --- a/ash/frame/default_frame_header.h +++ b/ash/frame/default_frame_header.h
@@ -10,7 +10,6 @@ #include "ash/ash_export.h" #include "ash/frame/caption_buttons/frame_caption_button.h" #include "ash/frame/frame_header.h" -#include "ash/public/interfaces/window_style.mojom.h" #include "base/compiler_specific.h" // override #include "base/gtest_prod_util.h" #include "base/macros.h" @@ -37,11 +36,9 @@ public gfx::AnimationDelegate { public: // DefaultFrameHeader does not take ownership of any of the parameters. - DefaultFrameHeader( - views::Widget* frame, - views::View* header_view, - FrameCaptionButtonContainerView* caption_button_container, - mojom::WindowStyle window_style = mojom::WindowStyle::DEFAULT); + DefaultFrameHeader(views::Widget* frame, + views::View* header_view, + FrameCaptionButtonContainerView* caption_button_container); ~DefaultFrameHeader() override; // FrameHeader overrides: @@ -54,29 +51,23 @@ void SchedulePaintForTitle() override; void SetPaintAsActive(bool paint_as_active) override; void OnShowStateChanged(ui::WindowShowState show_state) override; + void SetLeftHeaderView(views::View* left_header_view) override; + void SetBackButton(FrameCaptionButton* back_button) override; + FrameCaptionButton* GetBackButton() const override; + void SetFrameColors(SkColor active_frame_color, + SkColor inactive_frame_color) override; - void set_left_header_view(views::View* left_header_view) { - left_header_view_ = left_header_view; - } - - void set_back_button(FrameCaptionButton* back_button) { - back_button_ = back_button; - } - FrameCaptionButton* back_button() { return back_button_; } - - void set_title(const base::string16& title) { title_ = title; } - - // Sets the active and inactive frame colors. Note the inactive frame color - // will have some transparency added when the frame is drawn. - void SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color); void SetThemeColor(SkColor theme_color); - SkColor GetActiveFrameColor() const; - SkColor GetInactiveFrameColor() const; - SkColor GetCurrentFrameColor() const; // Gets the color of the title text. SkColor GetTitleColor() const; + // The default frame color for both active and inactive. + static SkColor GetDefaultFrameColor(); + + SkColor active_frame_color_for_testing() { return active_frame_color_; } + SkColor inactive_frame_color_for_testing() { return inactive_frame_color_; } + protected: // Updates the frame colors and ensures buttons are up to date. void SetFrameColorsImpl(SkColor active_frame_color, @@ -98,10 +89,6 @@ // gfx::AnimationDelegate override: void AnimationProgressed(const gfx::Animation* animation) override; - // Paints highlight around the edge of the header for inactive restored - // windows. - void PaintHighlightForInactiveRestoredWindow(gfx::Canvas* canvas); - // Update all the images in the caption buttons. void UpdateAllButtonImages(); @@ -113,10 +100,10 @@ // same width as |view_|. gfx::Rect GetLocalBounds() const; - // Returns whether the frame uses custom frame coloring. - bool UsesCustomFrameColors() const; + base::string16 GetTitle() const; - const mojom::WindowStyle window_style_; + SkColor GetCurrentFrameColor() const; + views::Widget* frame_; views::View* view_; FrameCaptionButton* back_button_; // May be nullptr. @@ -126,7 +113,6 @@ SkColor active_frame_color_; SkColor inactive_frame_color_; FrameCaptionButtonContainerView* caption_button_container_; - base::string16 title_; // The height of the header to paint. int painted_height_;
diff --git a/ash/frame/default_frame_header_unittest.cc b/ash/frame/default_frame_header_unittest.cc index 4077dc1..90ac002d 100644 --- a/ash/frame/default_frame_header_unittest.cc +++ b/ash/frame/default_frame_header_unittest.cc
@@ -33,7 +33,7 @@ DefaultFrameHeader frame_header(w.get(), w->non_client_view()->frame_view(), &container); - frame_header.set_left_header_view(&window_icon); + frame_header.SetLeftHeaderView(&window_icon); frame_header.LayoutHeader(); gfx::Rect title_bounds = frame_header.GetAvailableTitleBounds(); EXPECT_EQ(window_icon.bounds().CenterPoint().y(), @@ -48,7 +48,7 @@ DefaultFrameHeader frame_header(w.get(), w->non_client_view()->frame_view(), &container); - frame_header.set_back_button(&back); + frame_header.SetBackButton(&back); frame_header.LayoutHeader(); gfx::Rect title_bounds = frame_header.GetAvailableTitleBounds(); // The back button should be positioned at the left edge, and
diff --git a/ash/frame/frame_header.h b/ash/frame/frame_header.h index 9d799664..0878a5a 100644 --- a/ash/frame/frame_header.h +++ b/ash/frame/frame_header.h
@@ -6,14 +6,21 @@ #define ASH_FRAME_FRAME_HEADER_H_ #include "ash/ash_export.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/base/ui_base_types.h" namespace gfx { class Canvas; } +namespace views { +class View; +} + namespace ash { +class FrameCaptionButton; + // Helper class for managing the window header. class ASH_EXPORT FrameHeader { public: @@ -48,6 +55,15 @@ // Called when frame show state is changed. virtual void OnShowStateChanged(ui::WindowShowState show_state) = 0; + + virtual void SetLeftHeaderView(views::View* view) = 0; + virtual void SetBackButton(FrameCaptionButton* view) = 0; + virtual FrameCaptionButton* GetBackButton() const = 0; + + // Sets the active and inactive frame colors. Note the inactive frame color + // will have some transparency added when the frame is drawn. + virtual void SetFrameColors(SkColor active_frame_color, + SkColor inactive_frame_color) = 0; }; } // namespace ash
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc index d318f21..fd2e094 100644 --- a/ash/frame/header_view.cc +++ b/ash/frame/header_view.cc
@@ -11,14 +11,59 @@ #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/frame/custom_frame_view_ash.h" #include "ash/frame/default_frame_header.h" +#include "ash/public/cpp/config.h" +#include "ash/public/cpp/window_properties.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_state.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/window.h" #include "ui/views/controls/image_view.h" #include "ui/views/widget/widget.h" namespace ash { +namespace { + +// An appearance provider that relies on window properties which have been set +// by the client. Only used in Mash. +class WindowPropertyAppearanceProvider + : public CustomFrameHeader::AppearanceProvider { + public: + explicit WindowPropertyAppearanceProvider(aura::Window* window) + : window_(window) {} + ~WindowPropertyAppearanceProvider() override = default; + + SkColor GetFrameHeaderColor(bool active) override { + return window_->GetProperty(active ? ash::kFrameActiveColorKey + : ash::kFrameInactiveColorKey); + } + + gfx::ImageSkia GetFrameHeaderImage(bool active) override { + // TODO(estade): handle !active. + gfx::ImageSkia* image = window_->GetProperty(kFrameImageActiveKey); + return image ? *image : gfx::ImageSkia(); + } + + gfx::ImageSkia GetFrameHeaderOverlayImage(bool active) override { + // TODO(estade): implement. + return gfx::ImageSkia(); + } + + bool IsTabletMode() override { + return Shell::Get() + ->tablet_mode_controller() + ->IsTabletModeWindowManagerEnabled(); + } + + private: + aura::Window* window_; + + DISALLOW_COPY_AND_ASSIGN(WindowPropertyAppearanceProvider); +}; + +} // namespace + HeaderView::HeaderView(views::Widget* target_widget, mojom::WindowStyle window_style, std::unique_ptr<CaptionButtonModel> model) @@ -32,9 +77,22 @@ caption_button_container_->UpdateCaptionButtonState(false /*=animate*/); AddChildView(caption_button_container_); - frame_header_ = std::make_unique<DefaultFrameHeader>( - target_widget_, this, caption_button_container_, window_style); + if (window_style == mojom::WindowStyle::DEFAULT) { + frame_header_ = std::make_unique<DefaultFrameHeader>( + target_widget_, this, caption_button_container_); + } else { + DCHECK_EQ(mojom::WindowStyle::BROWSER, window_style); + DCHECK_EQ(Config::MASH, Shell::GetAshConfig()); + appearance_provider_ = std::make_unique<WindowPropertyAppearanceProvider>( + target_widget_->GetNativeWindow()); + auto frame_header = std::make_unique<CustomFrameHeader>(); + // TODO(estade): pass correct value for |incognito|. + frame_header->Init(this, appearance_provider_.get(), false, + caption_button_container_); + frame_header_ = std::move(frame_header); + } + window_observer_.Add(target_widget_->GetNativeWindow()); Shell::Get()->tablet_mode_controller()->AddObserver(this); } @@ -85,7 +143,7 @@ } avatar_icon_->SetImage(avatar); } - frame_header_->set_left_header_view(avatar_icon_); + frame_header_->SetLeftHeaderView(avatar_icon_); Layout(); } @@ -95,36 +153,23 @@ bool has_back_button = caption_button_container_->model()->IsVisible(CAPTION_BUTTON_ICON_BACK); - FrameCaptionButton* back_button = frame_header_->back_button(); + FrameCaptionButton* back_button = frame_header_->GetBackButton(); if (has_back_button) { if (!back_button) { back_button = new FrameBackButton(); AddChildView(back_button); - frame_header_->set_back_button(back_button); + frame_header_->SetBackButton(back_button); } back_button->SetEnabled(caption_button_container_->model()->IsEnabled( CAPTION_BUTTON_ICON_BACK)); } else { delete back_button; - frame_header_->set_back_button(nullptr); + frame_header_->SetBackButton(nullptr); } Layout(); } -void HeaderView::SetFrameColors(SkColor active_frame_color, - SkColor inactive_frame_color) { - frame_header_->SetFrameColors(active_frame_color, inactive_frame_color); -} - -SkColor HeaderView::GetActiveFrameColor() const { - return frame_header_->GetActiveFrameColor(); -} - -SkColor HeaderView::GetInactiveFrameColor() const { - return frame_header_->GetInactiveFrameColor(); -} - void HeaderView::OnShowStateChanged(ui::WindowShowState show_state) { frame_header_->OnShowStateChanged(show_state); } @@ -174,6 +219,28 @@ target_widget_->non_client_view()->Layout(); } +void HeaderView::OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) { + DCHECK_EQ(target_widget_->GetNativeWindow(), window); + if (key == kFrameImageActiveKey) { + SchedulePaint(); + } else if (key == aura::client::kAvatarIconKey) { + gfx::ImageSkia* const avatar_icon = + window->GetProperty(aura::client::kAvatarIconKey); + SetAvatarIcon(avatar_icon ? *avatar_icon : gfx::ImageSkia()); + } else if (key == ash::kFrameActiveColorKey || + key == ash::kFrameInactiveColorKey) { + frame_header_->SetFrameColors( + window->GetProperty(ash::kFrameActiveColorKey), + window->GetProperty(ash::kFrameInactiveColorKey)); + } +} + +void HeaderView::OnWindowDestroying(aura::Window* window) { + window_observer_.Remove(window); +} + views::View* HeaderView::avatar_icon() const { return avatar_icon_; } @@ -188,7 +255,7 @@ } FrameCaptionButton* HeaderView::GetBackButton() { - return frame_header_->back_button(); + return frame_header_->GetBackButton(); } ///////////////////////////////////////////////////////////////////////////////
diff --git a/ash/frame/header_view.h b/ash/frame/header_view.h index 80455e1..e437deb 100644 --- a/ash/frame/header_view.h +++ b/ash/frame/header_view.h
@@ -8,12 +8,15 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/frame/default_frame_header.h" +#include "ash/frame/custom_frame_header.h" +#include "ash/frame/frame_header.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h" #include "ash/public/interfaces/window_style.mojom.h" #include "ash/wm/tablet_mode/tablet_mode_observer.h" #include "base/macros.h" +#include "base/scoped_observer.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/aura/window_observer.h" #include "ui/base/ui_base_types.h" #include "ui/views/view.h" @@ -38,7 +41,8 @@ // and on screen in immersive fullscreen. class ASH_EXPORT HeaderView : public views::View, public ImmersiveFullscreenControllerDelegate, - public TabletModeObserver { + public TabletModeObserver, + public aura::WindowObserver { public: // |target_widget| is the widget that the caption buttons act on. // |target_widget| is not necessarily the same as the widget the header is @@ -75,10 +79,6 @@ void UpdateCaptionButtons(); - void SetFrameColors(SkColor active_frame_color, SkColor inactive_frame_color); - SkColor GetActiveFrameColor() const; - SkColor GetInactiveFrameColor() const; - // Called when the target widget show state changed. void OnShowStateChanged(ui::WindowShowState show_state); @@ -91,6 +91,12 @@ void OnTabletModeStarted() override; void OnTabletModeEnded() override; + // aura::WindowObserver: + void OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) override; + void OnWindowDestroying(aura::Window* window) override; + FrameCaptionButtonContainerView* caption_button_container() { return caption_button_container_; } @@ -100,10 +106,6 @@ bool in_immersive_mode() const { return in_immersive_mode_; } bool is_revealed() const { return fullscreen_visible_fraction_ > 0.0; } - void set_title(const base::string16& title) { - frame_header_->set_title(title); - } - void SetShouldPaintHeader(bool paint); FrameCaptionButton* GetBackButton(); @@ -120,8 +122,14 @@ // The widget that the caption buttons act on. views::Widget* target_widget_; - // Helper for painting the header. - std::unique_ptr<DefaultFrameHeader> frame_header_; + std::unique_ptr<CustomFrameHeader::AppearanceProvider> appearance_provider_; + + // Helper for painting the header. The exact type of FrameHeader will depend + // on the type of window: In Mash, Chrome Browser windows use + // CustomFrameHeader which is aware of theming. In classic Ash, Chrome Browser + // windows won't use HeaderView at all. In either configuration, non Browser + // windows will use DefaultFrameHeader. + std::unique_ptr<FrameHeader> frame_header_; views::ImageView* avatar_icon_; @@ -142,6 +150,9 @@ bool in_immersive_mode_ = false; + // Observes property changes to |target_widget_|'s window. + ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this}; + DISALLOW_COPY_AND_ASSIGN(HeaderView); };
diff --git a/ash/frame/wide_frame_view.cc b/ash/frame/wide_frame_view.cc index e3709b1..95d5138 100644 --- a/ash/frame/wide_frame_view.cc +++ b/ash/frame/wide_frame_view.cc
@@ -105,11 +105,8 @@ aura::Window* target_window = target->GetNativeWindow(); target_window->AddObserver(this); - SkColor active = target_window->GetProperty(kFrameActiveColorKey); - SkColor inactive = target_window->GetProperty(kFrameInactiveColorKey); header_view_ = new HeaderView(target); AddChildView(header_view_); - header_view_->SetFrameColors(active, inactive); GetTargetHeaderView()->SetShouldPaintHeader(false); }
diff --git a/ash/highlighter/highlighter_controller.cc b/ash/highlighter/highlighter_controller.cc index 0d4a2e9..8b7da85c 100644 --- a/ash/highlighter/highlighter_controller.cc +++ b/ash/highlighter/highlighter_controller.cc
@@ -64,6 +64,16 @@ Shell::Get()->RemovePreTargetHandler(this); } +void HighlighterController::AddObserver(Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void HighlighterController::RemoveObserver(Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + void HighlighterController::SetExitCallback(base::OnceClosure exit_callback, bool require_success) { exit_callback_ = std::move(exit_callback); @@ -89,6 +99,9 @@ if (highlighter_view_ && !highlighter_view_->animating()) DestroyPointerView(); } + for (auto& observer : observers_) + observer.OnHighlighterEnabledChanged(enabled); + if (client_) client_->HandleEnabledStateChange(enabled); }
diff --git a/ash/highlighter/highlighter_controller.h b/ash/highlighter/highlighter_controller.h index 7136d0e..87b5b0f 100644 --- a/ash/highlighter/highlighter_controller.h +++ b/ash/highlighter/highlighter_controller.h
@@ -12,6 +12,7 @@ #include "ash/public/interfaces/highlighter_controller.mojom.h" #include "base/callback.h" #include "base/memory/weak_ptr.h" +#include "base/observer_list.h" #include "mojo/public/cpp/bindings/binding.h" namespace base { @@ -30,9 +31,24 @@ : public fast_ink::FastInkPointerController, public mojom::HighlighterController { public: + // Interface for classes that wish to be notified with highlighter status. + class Observer { + public: + // Called when highlighter enabled status changes. + // TODO(warx): add a reason enum to distinguish the case of deselecting the + // tool and done with a stylus selection. + virtual void OnHighlighterEnabledChanged(bool enabled) {} + + protected: + virtual ~Observer() = default; + }; + HighlighterController(); ~HighlighterController() override; + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + // Set the callback to exit the highlighter mode. If |require_success| is // true, the callback will be called only after a successful gesture // recognition. If |require_success| is false, the callback will be called @@ -115,6 +131,8 @@ // Interface to highlighter controller client (chrome). mojom::HighlighterControllerClientPtr client_; + base::ObserverList<Observer> observers_; + base::WeakPtrFactory<HighlighterController> weak_factory_; DISALLOW_COPY_AND_ASSIGN(HighlighterController);
diff --git a/ash/message_center/message_center_controller.h b/ash/message_center/message_center_controller.h index cdacbb5..34fabf5 100644 --- a/ash/message_center/message_center_controller.h +++ b/ash/message_center/message_center_controller.h
@@ -7,9 +7,9 @@ #include "ash/ash_export.h" #include "ash/public/interfaces/ash_message_center_controller.mojom.h" -#include "ash/system/web_notification/fullscreen_notification_blocker.h" -#include "ash/system/web_notification/inactive_user_notification_blocker.h" -#include "ash/system/web_notification/session_state_notification_blocker.h" +#include "ash/system/message_center/fullscreen_notification_blocker.h" +#include "ash/system/message_center/inactive_user_notification_blocker.h" +#include "ash/system/message_center/session_state_notification_blocker.h" #include "base/macros.h" #include "components/arc/common/notifications.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h"
diff --git a/ash/public/cpp/ash_switches.cc b/ash/public/cpp/ash_switches.cc index 8836081..79c94b0 100644 --- a/ash/public/cpp/ash_switches.cc +++ b/ash/public/cpp/ash_switches.cc
@@ -154,10 +154,6 @@ // Hides all Message Center notification popups (toasts). Used for testing. const char kSuppressMessageCenterPopups[] = "suppress-message-center-popups"; -// By default we use classic IME (i.e. InputMethodChromeOS) in kMus. This flag -// enables the IME service (i.e. InputMethodMus) instead. -const char kUseIMEService[] = "use-ime-service"; - bool IsNightLightEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( kAshEnableNightLight);
diff --git a/ash/public/cpp/ash_switches.h b/ash/public/cpp/ash_switches.h index 5807fe2..0b198ed6 100644 --- a/ash/public/cpp/ash_switches.h +++ b/ash/public/cpp/ash_switches.h
@@ -61,7 +61,6 @@ ASH_PUBLIC_EXPORT extern const char kShowWebUiLogin[]; ASH_PUBLIC_EXPORT extern const char kSuppressMessageCenterPopups[]; ASH_PUBLIC_EXPORT extern const char kTouchscreenUsableWhileScreenOff[]; -ASH_PUBLIC_EXPORT extern const char kUseIMEService[]; ASH_PUBLIC_EXPORT bool IsDisplayMoveWindowAccelsEnabled(); ASH_PUBLIC_EXPORT bool IsNightLightEnabled();
diff --git a/ash/public/cpp/config.h b/ash/public/cpp/config.h index 4fb88c6..f375298 100644 --- a/ash/public/cpp/config.h +++ b/ash/public/cpp/config.h
@@ -13,6 +13,8 @@ CLASSIC, // Aura is backed by mus, but chrome and ash are still in the same process. + // TODO(jamescook): Remove this mode. We are switching to window service as a + // library, https://crbug.com/837684 MUS, // Aura is backed by mus and chrome and ash are in separate processes. In this
diff --git a/ash/public/cpp/menu_struct_mojom_traits.h b/ash/public/cpp/menu_struct_mojom_traits.h index a799efd..37aaf56 100644 --- a/ash/public/cpp/menu_struct_mojom_traits.h +++ b/ash/public/cpp/menu_struct_mojom_traits.h
@@ -28,6 +28,8 @@ return ash::mojom::MenuItemType::COMMAND; case ui::MenuModel::TYPE_SUBMENU: return ash::mojom::MenuItemType::SUBMENU; + case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU: + return ash::mojom::MenuItemType::ACTIONABLE_SUBMENU; } NOTREACHED(); return ash::mojom::MenuItemType::COMMAND; @@ -51,6 +53,9 @@ case ash::mojom::MenuItemType::SUBMENU: *out = ui::MenuModel::TYPE_SUBMENU; return true; + case ash::mojom::MenuItemType::ACTIONABLE_SUBMENU: + *out = ui::MenuModel::TYPE_ACTIONABLE_SUBMENU; + return true; } NOTREACHED(); return false;
diff --git a/ash/public/cpp/menu_utils.cc b/ash/public/cpp/menu_utils.cc index 81cd8891..516b9f2 100644 --- a/ash/public/cpp/menu_utils.cc +++ b/ash/public/cpp/menu_utils.cc
@@ -26,8 +26,10 @@ item->checked = model->IsItemCheckedAt(i); item->enabled = model->IsEnabledAt(i); item->radio_group_id = model->GetGroupIdAt(i); - if (item->type == ui::MenuModel::TYPE_SUBMENU) + if (item->type == ui::MenuModel::TYPE_SUBMENU || + item->type == ui::MenuModel::TYPE_ACTIONABLE_SUBMENU) { item->submenu = GetMojoMenuItemsFromModel(model->GetSubmenuModelAt(i)); + } gfx::Image icon; if (model->GetIconAt(i, &icon)) item->image = icon.AsImageSkia(); @@ -59,12 +61,18 @@ NOTREACHED() << "TYPE_BUTTON_ITEM is not yet supported."; break; case ui::MenuModel::TYPE_SUBMENU: + case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU: if (item->submenu.has_value()) { std::unique_ptr<ui::SimpleMenuModel> submenu = std::make_unique<ui::SimpleMenuModel>(delegate); PopulateMenuFromMojoMenuItems(submenu.get(), delegate, item->submenu.value(), submenus); - model->AddSubMenu(item->command_id, item->label, submenu.get()); + if (item->type == ui::MenuModel::TYPE_SUBMENU) { + model->AddSubMenu(item->command_id, item->label, submenu.get()); + } else { + model->AddActionableSubMenu(item->command_id, item->label, + submenu.get()); + } submenus->push_back(std::move(submenu)); } break; @@ -83,7 +91,8 @@ for (const mojom::MenuItemPtr& item : items) { if (item->command_id == command_id) return item; - if (item->type == ui::MenuModel::TYPE_SUBMENU && + if ((item->type == ui::MenuModel::TYPE_SUBMENU || + (item->type == ui::MenuModel::TYPE_ACTIONABLE_SUBMENU)) && item->submenu.has_value()) { const mojom::MenuItemPtr& submenu_item = GetMenuItemByCommandId(item->submenu.value(), command_id);
diff --git a/ash/public/cpp/mus_property_mirror_ash.cc b/ash/public/cpp/mus_property_mirror_ash.cc index 90189f8..01793527 100644 --- a/ash/public/cpp/mus_property_mirror_ash.cc +++ b/ash/public/cpp/mus_property_mirror_ash.cc
@@ -63,6 +63,11 @@ MirrorOwnedProperty(window, root_window, aura::client::kTitleKey); } else if (key == aura::client::kWindowIconKey) { MirrorOwnedProperty(window, root_window, aura::client::kWindowIconKey); + } else if (key == kFrameImageActiveKey) { + MirrorOwnedProperty(window, root_window, kFrameImageActiveKey); + } else if (key == kWindowTitleShownKey) { + root_window->SetProperty(kWindowTitleShownKey, + window->GetProperty(kWindowTitleShownKey)); } }
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc index ae06aa6b..56d79821 100644 --- a/ash/public/cpp/window_properties.cc +++ b/ash/public/cpp/window_properties.cc
@@ -8,6 +8,7 @@ #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/public/interfaces/window_state_type.mojom.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/image/image_skia.h" DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_PUBLIC_EXPORT, ash::mojom::WindowPinType) @@ -22,6 +23,9 @@ kBackdropWindowMode, BackdropWindowMode::kAuto); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kCanConsumeSystemKeysKey, false); +DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, + kFrameImageActiveKey, + nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kHideShelfWhenFullscreenKey, true); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kPanelAttachedKey, true); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Rect, @@ -46,5 +50,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowStateType, kWindowStateTypeKey, mojom::WindowStateType::DEFAULT); +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowTitleShownKey, true); } // namespace ash
diff --git a/ash/public/cpp/window_properties.h b/ash/public/cpp/window_properties.h index 620369e..dafb85f 100644 --- a/ash/public/cpp/window_properties.h +++ b/ash/public/cpp/window_properties.h
@@ -18,6 +18,7 @@ } namespace gfx { +class ImageSkia; class Rect; } @@ -47,6 +48,10 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const kCanConsumeSystemKeysKey; +// The frame's active image. Only set on themed windows. +ASH_PUBLIC_EXPORT extern const aura::WindowProperty<gfx::ImageSkia*>* const + kFrameImageActiveKey; + // Whether the shelf should be hidden when this window is put into fullscreen. // Exposed because some windows want to explicitly opt-out of this. ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const @@ -107,6 +112,11 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty< mojom::WindowStateType>* const kWindowStateTypeKey; +// Determines whether the window title should be drawn. For example, app and +// non-tabbed, trusted source windows (such as Settings) will not show a title. +ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const + kWindowTitleShownKey; + // Alphabetical sort. } // namespace ash
diff --git a/ash/public/interfaces/menu.mojom b/ash/public/interfaces/menu.mojom index 2986328f..971cd9c6 100644 --- a/ash/public/interfaces/menu.mojom +++ b/ash/public/interfaces/menu.mojom
@@ -10,12 +10,13 @@ // The types of menu items shown in shelf context and application list menus. // These values roughly match ui::MenuModel::ItemType (sans TYPE_BUTTON_ITEM). enum MenuItemType { - COMMAND, // An item that performs an action when selected. - CHECK, // An item that can be selected/checked to toggle a boolean state. - RADIO, // An item that can be selected/checked among a group of choices. - SEPARATOR, // An item that shows a horizontal line separator. - SUBMENU, // An item that presents a submenu within another menu. -}; + COMMAND, // Performs an action when selected. + CHECK, // Can be selected/checked to toggle a boolean state. + RADIO, // Can be selected/checked among a group of choices. + SEPARATOR, // Shows a horizontal line separator. + SUBMENU, // Presents a submenu within another menu. + ACTIONABLE_SUBMENU, // A SUBMENU that is also a COMMAND. + }; // MenuItems are used to populate application menus for shelf items. // Note: Some menus only support a subset of these item features (eg. no icons).
diff --git a/ash/public/interfaces/window_properties.mojom b/ash/public/interfaces/window_properties.mojom index 0c54b00..07d02afc1 100644 --- a/ash/public/interfaces/window_properties.mojom +++ b/ash/public/interfaces/window_properties.mojom
@@ -9,6 +9,10 @@ const string kCanConsumeSystemKeys_Property = "ash:can-consume-system-keys"; +// A gfx::ImageSkia used to tell Mash the frame image to use for a custom +// Browser theme. +const string kFrameImageActive_Property = "ash:frame-image-active"; + // True if the shelf should be hidden when this window is put into fullscreen. // Exposed because some windows want to explicitly opt-out of this. const string kHideShelfWhenFullscreen_Property =
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd index 91535e0..1edf3c9 100644 --- a/ash/resources/ash_resources.grd +++ b/ash/resources/ash_resources.grd
@@ -14,11 +14,6 @@ SAME CONDITIONALS. --> <structure type="chrome_scaled_image" name="IDR_AURA_NOTIFICATION_DISPLAY" file="cros/notification/display_notification_icon.png" /> - - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM" file="common/window_header_shade_bottom_inactive.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_LEFT" file="common/window_header_shade_left_inactive.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_RIGHT" file="common/window_header_shade_right_inactive.png" /> - <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_TOP" file="common/window_header_shade_top_inactive.png" /> </structures> </release> </grit>
diff --git a/ash/resources/default_100_percent/common/window_header_shade_bottom_inactive.png b/ash/resources/default_100_percent/common/window_header_shade_bottom_inactive.png deleted file mode 100644 index 69a3e01..0000000 --- a/ash/resources/default_100_percent/common/window_header_shade_bottom_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_header_shade_left_inactive.png b/ash/resources/default_100_percent/common/window_header_shade_left_inactive.png deleted file mode 100644 index 06b9749..0000000 --- a/ash/resources/default_100_percent/common/window_header_shade_left_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_header_shade_right_inactive.png b/ash/resources/default_100_percent/common/window_header_shade_right_inactive.png deleted file mode 100644 index 3dcc983..0000000 --- a/ash/resources/default_100_percent/common/window_header_shade_right_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_header_shade_top_inactive.png b/ash/resources/default_100_percent/common/window_header_shade_top_inactive.png deleted file mode 100644 index 0be57ba..0000000 --- a/ash/resources/default_100_percent/common/window_header_shade_top_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_header_shade_bottom_inactive.png b/ash/resources/default_200_percent/common/window_header_shade_bottom_inactive.png deleted file mode 100644 index 5c6d4ff1..0000000 --- a/ash/resources/default_200_percent/common/window_header_shade_bottom_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_header_shade_left_inactive.png b/ash/resources/default_200_percent/common/window_header_shade_left_inactive.png deleted file mode 100644 index 91f40878..0000000 --- a/ash/resources/default_200_percent/common/window_header_shade_left_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_header_shade_right_inactive.png b/ash/resources/default_200_percent/common/window_header_shade_right_inactive.png deleted file mode 100644 index 2ab6d846..0000000 --- a/ash/resources/default_200_percent/common/window_header_shade_right_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_header_shade_top_inactive.png b/ash/resources/default_200_percent/common/window_header_shade_top_inactive.png deleted file mode 100644 index 576ad9b..0000000 --- a/ash/resources/default_200_percent/common/window_header_shade_top_inactive.png +++ /dev/null Binary files differ
diff --git a/ash/session/session_controller_unittest.cc b/ash/session/session_controller_unittest.cc index 3c65e76..20fb1d34 100644 --- a/ash/session/session_controller_unittest.cc +++ b/ash/session/session_controller_unittest.cc
@@ -15,9 +15,9 @@ #include "ash/session/session_observer.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/screen_security/screen_tray_item.h" #include "ash/system/tray/system_tray.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/window_util.h" @@ -564,12 +564,12 @@ capture_item_ = system_tray->GetScreenCaptureItem(); EXPECT_TRUE(share_item_); EXPECT_TRUE(capture_item_); - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); } void TearDown() override { RunAllPendingInMessageLoop(); - WebNotificationTray::DisableAnimationsForTest(false); + NotificationTray::DisableAnimationsForTest(false); AshTestBase::TearDown(); }
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index 6bca366..7c88b70 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -9,6 +9,7 @@ #include <utility> #include "ash/app_list/app_list_controller_impl.h" +#include "ash/assistant/ash_assistant_controller.h" #include "ash/public/cpp/shelf_types.h" #include "ash/session/session_controller.h" #include "ash/shelf/assistant_overlay.h" @@ -132,12 +133,18 @@ Shell::Get()->app_list_controller()->StartVoiceInteractionSession(); assistant_overlay_->BurstAnimation(); event->SetHandled(); + } else if (chromeos::switches::IsAssistantEnabled()) { + // TODO: Handle overlay animation similarly to above. Also needs to + // factor in Assistant enabled state. + Shell::Get()->ash_assistant_controller()->StartInteraction(); + event->SetHandled(); } else { ImageButton::OnGestureEvent(event); } return; case ui::ET_GESTURE_LONG_TAP: - if (UseVoiceInteractionStyle()) { + if (UseVoiceInteractionStyle() || + chromeos::switches::IsAssistantEnabled()) { // Also consume the long tap event. This happens after the user long // presses and lifts the finger. We already handled the long press // ignore the long tap to avoid bringing up the context menu again.
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index f16392d4..d54b8818 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -213,7 +213,7 @@ class UpdateShelfObserver; friend class PanelLayoutManagerTest; friend class ShelfLayoutManagerTest; - friend class WebNotificationTrayTest; + friend class NotificationTrayTest; struct TargetBounds { TargetBounds();
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 5ea645d..fc619a5 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -34,7 +34,7 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_test_api.h" -#include "ash/system/web_notification/web_notification_tray.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test_shell_delegate.h" @@ -261,7 +261,7 @@ model_ = Shell::Get()->shelf_model(); shelf_view_ = GetPrimaryShelf()->GetShelfViewForTesting(); - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); // The bounds should be big enough for 4 buttons + overflow chevron. shelf_view_->SetBounds(0, 0, 500, kShelfSize); @@ -274,7 +274,7 @@ } void TearDown() override { - WebNotificationTray::DisableAnimationsForTest(false); // Reenable animation + NotificationTray::DisableAnimationsForTest(false); // Reenable animation test_api_.reset(); AshTestBase::TearDown(); }
diff --git a/ash/shell.cc b/ash/shell.cc index fda0577..17736e4 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -399,10 +399,7 @@ // static bool Shell::ShouldUseIMEService() { - return Shell::GetAshConfig() == Config::MASH || - (Shell::GetAshConfig() == Config::MUS && - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kUseIMEService)); + return Shell::GetAshConfig() == Config::MASH; } // static @@ -535,10 +532,10 @@ Shelf::ForWindow(root)->UpdateVisibilityState(); } -WebNotificationTray* Shell::GetWebNotificationTray() { +NotificationTray* Shell::GetNotificationTray() { return GetPrimaryRootWindowController() ->GetStatusAreaWidget() - ->web_notification_tray(); + ->notification_tray(); } bool Shell::HasPrimaryStatusArea() { @@ -1091,10 +1088,6 @@ app_list_controller_ = std::make_unique<AppListControllerImpl>(); shelf_controller_ = std::make_unique<ShelfController>(); - ash_assistant_controller_ = chromeos::switches::IsAssistantEnabled() - ? std::make_unique<AshAssistantController>() - : nullptr; - magnifier_key_scroll_handler_ = MagnifierKeyScroller::CreateHandler(); AddPreTargetHandler(magnifier_key_scroll_handler_.get()); speech_feedback_handler_ = SpokenFeedbackToggler::CreateHandler(); @@ -1181,6 +1174,10 @@ voice_interaction_controller_ = std::make_unique<VoiceInteractionController>(); + ash_assistant_controller_ = chromeos::switches::IsAssistantEnabled() + ? std::make_unique<AshAssistantController>() + : nullptr; + magnification_controller_ = std::make_unique<MagnificationController>(); mru_window_tracker_ = std::make_unique<MruWindowTracker>();
diff --git a/ash/shell.h b/ash/shell.h index 5740bea..75a7f6d 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -182,7 +182,7 @@ class VpnList; class WallpaperController; class WaylandServerController; -class WebNotificationTray; +class NotificationTray; class WindowCycleController; class WindowPositioner; class WindowSelectorController; @@ -556,8 +556,8 @@ // TODO(jamescook): Move to Shelf. void UpdateShelfVisibility(); - // Returns WebNotificationTray on the primary root window. - WebNotificationTray* GetWebNotificationTray(); + // Returns NotificationTray on the primary root window. + NotificationTray* GetNotificationTray(); // Does the primary display have status area? bool HasPrimaryStatusArea();
diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc index e162cb14..9ca7f74 100644 --- a/ash/shell/window_type_launcher.cc +++ b/ash/shell/window_type_launcher.cc
@@ -13,8 +13,8 @@ #include "ash/shell/example_factory.h" #include "ash/shell/panel_window.h" #include "ash/shell/toplevel_window.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/status_area_widget.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/wm/test_child_modal_parent.h" #include "base/strings/utf_string_conversions.h" #include "ui/aura/window.h" @@ -303,7 +303,7 @@ Shell::GetPrimaryRootWindowController() ->GetStatusAreaWidget() - ->web_notification_tray() + ->notification_tray() ->message_center() ->AddNotification(std::move(notification)); } else if (sender == examples_button_) {
diff --git a/ash/sidebar/sidebar_widget.cc b/ash/sidebar/sidebar_widget.cc index a2ab8ce..56ddcb0 100644 --- a/ash/sidebar/sidebar_widget.cc +++ b/ash/sidebar/sidebar_widget.cc
@@ -12,9 +12,9 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/tray_constants.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "base/strings/utf_string_conversions.h" #include "ui/app_list/views/app_list_view.h" #include "ui/aura/window.h"
diff --git a/ash/system/audio/unified_volume_slider_controller.cc b/ash/system/audio/unified_volume_slider_controller.cc index 139df7f..17753d2 100644 --- a/ash/system/audio/unified_volume_slider_controller.cc +++ b/ash/system/audio/unified_volume_slider_controller.cc
@@ -4,7 +4,12 @@ #include "ash/system/audio/unified_volume_slider_controller.h" +#include "ash/metrics/user_metrics_action.h" +#include "ash/metrics/user_metrics_recorder.h" +#include "ash/shell.h" #include "ash/system/audio/unified_volume_view.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" using chromeos::CrasAudioHandler; @@ -21,8 +26,12 @@ void UnifiedVolumeSliderController::ButtonPressed(views::Button* sender, const ui::Event& event) { - CrasAudioHandler::Get()->SetOutputMute( - !CrasAudioHandler::Get()->IsOutputMuted()); + bool mute_on = !CrasAudioHandler::Get()->IsOutputMuted(); + if (mute_on) + base::RecordAction(base::UserMetricsAction("StatusArea_Audio_Muted")); + else + base::RecordAction(base::UserMetricsAction("StatusArea_Audio_Unmuted")); + CrasAudioHandler::Get()->SetOutputMute(mute_on); } void UnifiedVolumeSliderController::SliderValueChanged( @@ -35,6 +44,11 @@ const int level = value * 100; + if (level != CrasAudioHandler::Get()->GetOutputVolumePercent()) { + Shell::Get()->metrics()->RecordUserMetricsAction( + UMA_STATUS_AREA_CHANGED_VOLUME_MENU); + } + CrasAudioHandler::Get()->SetOutputVolumePercent(level); // If the volume is above certain level and it's muted, it should be unmuted.
diff --git a/ash/system/audio/volume_view.cc b/ash/system/audio/volume_view.cc index c524311..8507cb0 100644 --- a/ash/system/audio/volume_view.cc +++ b/ash/system/audio/volume_view.cc
@@ -17,6 +17,8 @@ #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_utils.h" #include "ash/system/tray/tri_view.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" #include "chromeos/audio/cras_audio_handler.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" @@ -256,6 +258,12 @@ if (sender == icon_) { CrasAudioHandler* audio_handler = CrasAudioHandler::Get(); bool mute_on = !audio_handler->IsOutputMuted(); + + if (mute_on) + base::RecordAction(base::UserMetricsAction("StatusArea_Audio_Muted")); + else + base::RecordAction(base::UserMetricsAction("StatusArea_Audio_Unmuted")); + audio_handler->SetOutputMute(mute_on); if (!mute_on) audio_handler->AdjustOutputVolumeToAudibleLevel();
diff --git a/ash/system/caps_lock_notification_controller_unittest.cc b/ash/system/caps_lock_notification_controller_unittest.cc index b873a64..3a1917c 100644 --- a/ash/system/caps_lock_notification_controller_unittest.cc +++ b/ash/system/caps_lock_notification_controller_unittest.cc
@@ -7,7 +7,7 @@ #include "ash/accessibility/accessibility_controller.h" #include "ash/accessibility/test_accessibility_controller_client.h" #include "ash/shell.h" -#include "ash/system/web_notification/web_notification_tray.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/test/ash_test_base.h" namespace ash { @@ -19,11 +19,11 @@ void SetUp() override { AshTestBase::SetUp(); - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); } void TearDown() override { - WebNotificationTray::DisableAnimationsForTest(false); + NotificationTray::DisableAnimationsForTest(false); AshTestBase::TearDown(); }
diff --git a/ash/system/web_notification/ash_popup_alignment_delegate.cc b/ash/system/message_center/ash_popup_alignment_delegate.cc similarity index 98% rename from ash/system/web_notification/ash_popup_alignment_delegate.cc rename to ash/system/message_center/ash_popup_alignment_delegate.cc index 79cef6b..fae8ba0 100644 --- a/ash/system/web_notification/ash_popup_alignment_delegate.cc +++ b/ash/system/message_center/ash_popup_alignment_delegate.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/ash_popup_alignment_delegate.h" +#include "ash/system/message_center/ash_popup_alignment_delegate.h" #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/shell_window_ids.h"
diff --git a/ash/system/web_notification/ash_popup_alignment_delegate.h b/ash/system/message_center/ash_popup_alignment_delegate.h similarity index 91% rename from ash/system/web_notification/ash_popup_alignment_delegate.h rename to ash/system/message_center/ash_popup_alignment_delegate.h index 7f87f770..3eed14b 100644 --- a/ash/system/web_notification/ash_popup_alignment_delegate.h +++ b/ash/system/message_center/ash_popup_alignment_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 ASH_SYSTEM_WEB_NOTIFICATION_ASH_POPUP_ALIGNMENT_DELEGATE_H_ -#define ASH_SYSTEM_WEB_NOTIFICATION_ASH_POPUP_ALIGNMENT_DELEGATE_H_ +#ifndef ASH_SYSTEM_MESSAGE_CENTER_ASH_POPUP_ALIGNMENT_DELEGATE_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_ASH_POPUP_ALIGNMENT_DELEGATE_H_ #include <stdint.h> @@ -24,7 +24,7 @@ class AshPopupAlignmentDelegateTest; class Shelf; -class WebNotificationTrayTest; +class NotificationTrayTest; // The PopupAlignmentDelegate subclass for Ash. It needs to handle alignment of // the shelf and its autohide state. @@ -61,7 +61,7 @@ private: friend class AshPopupAlignmentDelegateTest; - friend class WebNotificationTrayTest; + friend class NotificationTrayTest; // Get the current alignment of the shelf. ShelfAlignment GetAlignment() const; @@ -92,4 +92,4 @@ } // namespace ash -#endif // ASH_SYSTEM_WEB_NOTIFICATION_ASH_POPUP_ALIGNMENT_DELEGATE_H_ +#endif // ASH_SYSTEM_MESSAGE_CENTER_ASH_POPUP_ALIGNMENT_DELEGATE_H_
diff --git a/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc b/ash/system/message_center/ash_popup_alignment_delegate_unittest.cc similarity index 98% rename from ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc rename to ash/system/message_center/ash_popup_alignment_delegate_unittest.cc index b52cfe863..d8f6c67 100644 --- a/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc +++ b/ash/system/message_center/ash_popup_alignment_delegate_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/ash_popup_alignment_delegate.h" +#include "ash/system/message_center/ash_popup_alignment_delegate.h" #include <memory> #include <utility>
diff --git a/ash/system/web_notification/fullscreen_notification_blocker.cc b/ash/system/message_center/fullscreen_notification_blocker.cc similarity index 96% rename from ash/system/web_notification/fullscreen_notification_blocker.cc rename to ash/system/message_center/fullscreen_notification_blocker.cc index 29261df..381044f9 100644 --- a/ash/system/web_notification/fullscreen_notification_blocker.cc +++ b/ash/system/message_center/fullscreen_notification_blocker.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/fullscreen_notification_blocker.h" +#include "ash/system/message_center/fullscreen_notification_blocker.h" #include "ash/root_window_controller.h" #include "ash/shell.h"
diff --git a/ash/system/web_notification/fullscreen_notification_blocker.h b/ash/system/message_center/fullscreen_notification_blocker.h similarity index 82% rename from ash/system/web_notification/fullscreen_notification_blocker.h rename to ash/system/message_center/fullscreen_notification_blocker.h index 19de9cb..36f4c72 100644 --- a/ash/system/web_notification/fullscreen_notification_blocker.h +++ b/ash/system/message_center/fullscreen_notification_blocker.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_WEB_NOTIFICATION_FULLSCREEN_NOTIFICATION_BLOCKER_H_ -#define ASH_SYSTEM_WEB_NOTIFICATION_FULLSCREEN_NOTIFICATION_BLOCKER_H_ +#ifndef ASH_SYSTEM_MESSAGE_CENTER_FULLSCREEN_NOTIFICATION_BLOCKER_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_FULLSCREEN_NOTIFICATION_BLOCKER_H_ #include "ash/shell_observer.h" #include "base/macros.h" @@ -36,4 +36,4 @@ } // namespace ash -#endif // ASH_SYSTEM_WEB_NOTIFICATION_FULLSCREEN_NOTIFICATION_BLOCKER_H_ +#endif // ASH_SYSTEM_MESSAGE_CENTER_FULLSCREEN_NOTIFICATION_BLOCKER_H_
diff --git a/ash/system/web_notification/inactive_user_notification_blocker.cc b/ash/system/message_center/inactive_user_notification_blocker.cc similarity index 95% rename from ash/system/web_notification/inactive_user_notification_blocker.cc rename to ash/system/message_center/inactive_user_notification_blocker.cc index 2ba18ba..9b432926 100644 --- a/ash/system/web_notification/inactive_user_notification_blocker.cc +++ b/ash/system/message_center/inactive_user_notification_blocker.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/inactive_user_notification_blocker.h" +#include "ash/system/message_center/inactive_user_notification_blocker.h" #include "ash/session/session_controller.h" #include "ash/shell.h"
diff --git a/ash/system/web_notification/inactive_user_notification_blocker.h b/ash/system/message_center/inactive_user_notification_blocker.h similarity index 85% rename from ash/system/web_notification/inactive_user_notification_blocker.h rename to ash/system/message_center/inactive_user_notification_blocker.h index f78ff43a..9f1f676 100644 --- a/ash/system/web_notification/inactive_user_notification_blocker.h +++ b/ash/system/message_center/inactive_user_notification_blocker.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_WEB_NOTIFICATION_INACTIVE_USER_NOTIFICATION_BLOCKER_H_ -#define ASH_SYSTEM_WEB_NOTIFICATION_INACTIVE_USER_NOTIFICATION_BLOCKER_H_ +#ifndef ASH_SYSTEM_MESSAGE_CENTER_INACTIVE_USER_NOTIFICATION_BLOCKER_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_INACTIVE_USER_NOTIFICATION_BLOCKER_H_ #include <map> @@ -43,4 +43,4 @@ } // namespace ash -#endif // ASH_SYSTEM_WEB_NOTIFICATION_INACTIVE_USER_NOTIFICATION_BLOCKER_H_ +#endif // ASH_SYSTEM_MESSAGE_CENTER_INACTIVE_USER_NOTIFICATION_BLOCKER_H_
diff --git a/ash/system/web_notification/inactive_user_notification_blocker_unittest.cc b/ash/system/message_center/inactive_user_notification_blocker_unittest.cc similarity index 98% rename from ash/system/web_notification/inactive_user_notification_blocker_unittest.cc rename to ash/system/message_center/inactive_user_notification_blocker_unittest.cc index a1bc249c..8e802051 100644 --- a/ash/system/web_notification/inactive_user_notification_blocker_unittest.cc +++ b/ash/system/message_center/inactive_user_notification_blocker_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/inactive_user_notification_blocker.h" +#include "ash/system/message_center/inactive_user_notification_blocker.h" #include "ash/message_center/message_center_controller.h" #include "ash/session/test_session_controller_client.h"
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/message_center/notification_tray.cc similarity index 81% rename from ash/system/web_notification/web_notification_tray.cc rename to ash/system/message_center/notification_tray.cc index 0961219b..66ee5a3 100644 --- a/ash/system/web_notification/web_notification_tray.cc +++ b/ash/system/message_center/notification_tray.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/web_notification_tray.h" +#include "ash/system/message_center/notification_tray.h" #include <memory> @@ -17,12 +17,12 @@ #include "ash/shelf/shelf_constants.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/system/message_center/ash_popup_alignment_delegate.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/tray_bubble_wrapper.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_container.h" #include "ash/system/tray/tray_utils.h" -#include "ash/system/web_notification/ash_popup_alignment_delegate.h" #include "base/auto_reset.h" #include "base/i18n/number_formatting.h" #include "base/i18n/rtl.h" @@ -57,7 +57,8 @@ constexpr size_t kMaximumNotificationNumber = 99; -constexpr size_t kPaddingFromScreenTop = 8; // in px. See crbug.com/754307. +// in px. See https://crbug.com/754307. +constexpr size_t kPaddingFromScreenTop = 8; constexpr float kBackgroundBlurRadius = 30.f; @@ -68,13 +69,13 @@ // Class to initialize and manage the WebNotificationBubble and // TrayBubbleWrapper instances for a bubble. -class WebNotificationBubbleWrapper { +class NotificationBubbleWrapper { public: // Takes ownership of |bubble| and creates |bubble_wrapper_|. - WebNotificationBubbleWrapper(WebNotificationTray* tray, - TrayBackgroundView* anchor_tray, - MessageCenterBubble* bubble, - bool show_by_click) { + NotificationBubbleWrapper(NotificationTray* tray, + TrayBackgroundView* anchor_tray, + MessageCenterBubble* bubble, + bool show_by_click) { bubble_.reset(bubble); views::TrayBubbleView::InitParams init_params; init_params.delegate = tray; @@ -112,13 +113,13 @@ std::unique_ptr<MessageCenterBubble> bubble_; std::unique_ptr<TrayBubbleWrapper> bubble_wrapper_; - DISALLOW_COPY_AND_ASSIGN(WebNotificationBubbleWrapper); + DISALLOW_COPY_AND_ASSIGN(NotificationBubbleWrapper); }; class WebNotificationItem : public views::View, public gfx::AnimationDelegate { public: WebNotificationItem(gfx::AnimationContainer* container, - WebNotificationTray* tray) + NotificationTray* tray) : tray_(tray) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -127,7 +128,7 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); - animation_.reset(new gfx::SlideAnimation(this)); + animation_ = std::make_unique<gfx::SlideAnimation>(this); animation_->SetContainer(container); animation_->SetSlideDuration(kTrayItemAnimationDurationMS); animation_->SetTweenType(gfx::Tween::LINEAR); @@ -217,16 +218,16 @@ std::unique_ptr<gfx::SlideAnimation> animation_; bool delete_after_animation_ = false; - WebNotificationTray* tray_; + NotificationTray* tray_; DISALLOW_COPY_AND_ASSIGN(WebNotificationItem); }; -class WebNotificationImage : public WebNotificationItem { +class NotificationImage : public WebNotificationItem { public: - WebNotificationImage(const gfx::ImageSkia& image, - gfx::AnimationContainer* container, - WebNotificationTray* tray) + NotificationImage(const gfx::ImageSkia& image, + gfx::AnimationContainer* container, + NotificationTray* tray) : WebNotificationItem(container, tray) { DCHECK(image.size() == gfx::Size(kTrayItemInnerIconSize, kTrayItemInnerIconSize)); @@ -240,13 +241,12 @@ private: views::ImageView* view_; - DISALLOW_COPY_AND_ASSIGN(WebNotificationImage); + DISALLOW_COPY_AND_ASSIGN(NotificationImage); }; -class WebNotificationLabel : public WebNotificationItem { +class NotificationLabel : public WebNotificationItem { public: - WebNotificationLabel(gfx::AnimationContainer* container, - WebNotificationTray* tray) + NotificationLabel(gfx::AnimationContainer* container, NotificationTray* tray) : WebNotificationItem(container, tray) { view_ = new views::Label(); SetupLabelForTray(view_); @@ -273,11 +273,11 @@ private: views::Label* view_; - DISALLOW_COPY_AND_ASSIGN(WebNotificationLabel); + DISALLOW_COPY_AND_ASSIGN(NotificationLabel); }; -WebNotificationTray::WebNotificationTray(Shelf* shelf, - aura::Window* status_area_window) +NotificationTray::NotificationTray(Shelf* shelf, + aura::Window* status_area_window) : TrayBackgroundView(shelf), status_area_window_(status_area_window), show_message_center_on_unlock_(false), @@ -288,25 +288,28 @@ SetInkDropMode(InkDropMode::ON); gfx::ImageSkia bell_image = CreateVectorIcon(kShelfNotificationsIcon, kShelfIconColor); - bell_icon_.reset( - new WebNotificationImage(bell_image, animation_container_.get(), this)); + bell_icon_ = std::make_unique<NotificationImage>( + bell_image, animation_container_.get(), this); tray_container()->AddChildView(bell_icon_.get()); gfx::ImageSkia quiet_mode_image = CreateVectorIcon(kNotificationCenterDoNotDisturbOnIcon, kTrayItemInnerIconSize, kShelfIconColor); - quiet_mode_icon_.reset(new WebNotificationImage( - quiet_mode_image, animation_container_.get(), this)); + quiet_mode_icon_ = std::make_unique<NotificationImage>( + quiet_mode_image, animation_container_.get(), this); tray_container()->AddChildView(quiet_mode_icon_.get()); - counter_.reset(new WebNotificationLabel(animation_container_.get(), this)); + counter_ = + std::make_unique<NotificationLabel>(animation_container_.get(), this); tray_container()->AddChildView(counter_.get()); - message_center_ui_controller_.reset(new message_center::UiController(this)); - popup_alignment_delegate_.reset(new AshPopupAlignmentDelegate(shelf)); - popup_collection_.reset(new message_center::MessagePopupCollection( + message_center_ui_controller_ = + std::make_unique<message_center::UiController>(this); + popup_alignment_delegate_ = + std::make_unique<AshPopupAlignmentDelegate>(shelf); + popup_collection_ = std::make_unique<message_center::MessagePopupCollection>( message_center(), message_center_ui_controller_.get(), - popup_alignment_delegate_.get())); + popup_alignment_delegate_.get()); display::Screen* screen = display::Screen::GetScreen(); popup_alignment_delegate_->StartObserving( screen, screen->GetDisplayNearestWindow(status_area_window_)); @@ -315,7 +318,7 @@ tray_container()->SetMargin(kTrayMainAxisInset, kTrayCrossAxisInset); } -WebNotificationTray::~WebNotificationTray() { +NotificationTray::~NotificationTray() { // Release any child views that might have back pointers before ~View(). message_center_bubble_.reset(); popup_alignment_delegate_.reset(); @@ -323,14 +326,14 @@ } // static -void WebNotificationTray::DisableAnimationsForTest(bool disable) { +void NotificationTray::DisableAnimationsForTest(bool disable) { disable_animations_for_test = disable; } // Public methods. -bool WebNotificationTray::ShowMessageCenterInternal(bool show_settings, - bool show_by_click) { +bool NotificationTray::ShowMessageCenterInternal(bool show_settings, + bool show_by_click) { if (!ShouldShowMessageCenter()) return false; @@ -348,7 +351,7 @@ new MessageCenterBubble(message_center()); // In the horizontal case, message center starts from the top of the shelf. - // In the vertical case, it starts from the bottom of WebNotificationTray. + // In the vertical case, it starts from the bottom of NotificationTray. const int max_height = (shelf()->IsHorizontalAlignment() ? shelf()->GetUserWorkAreaBounds().height() : GetBoundsInScreen().bottom() - @@ -360,14 +363,14 @@ if (show_settings) message_center_bubble->SetSettingsVisible(); - // For vertical shelf alignments, anchor to the WebNotificationTray, but for + // For vertical shelf alignments, anchor to the NotificationTray, but for // horizontal (i.e. bottom) shelves, anchor to the system tray. TrayBackgroundView* anchor_tray = this; if (shelf()->IsHorizontalAlignment()) anchor_tray = shelf()->GetSystemTrayAnchor(); - message_center_bubble_.reset(new WebNotificationBubbleWrapper( - this, anchor_tray, message_center_bubble, show_by_click)); + message_center_bubble_ = std::make_unique<NotificationBubbleWrapper>( + this, anchor_tray, message_center_bubble, show_by_click); } shelf()->UpdateAutoHideState(); @@ -375,11 +378,11 @@ return true; } -bool WebNotificationTray::ShowMessageCenter(bool show_by_click) { +bool NotificationTray::ShowMessageCenter(bool show_by_click) { return ShowMessageCenterInternal(false /* show_settings */, show_by_click); } -void WebNotificationTray::HideMessageCenter() { +void NotificationTray::HideMessageCenter() { if ((switches::IsSidebarEnabled() && !IsMessageCenterVisible()) || (!switches::IsSidebarEnabled() && !message_center_bubble())) return; @@ -398,15 +401,15 @@ shelf()->UpdateAutoHideState(); } -void WebNotificationTray::SetTrayBubbleHeight(int height) { +void NotificationTray::SetTrayBubbleHeight(int height) { popup_alignment_delegate_->SetTrayBubbleHeight(height); } -int WebNotificationTray::tray_bubble_height_for_test() const { +int NotificationTray::tray_bubble_height_for_test() const { return popup_alignment_delegate_->tray_bubble_height_for_test(); } -bool WebNotificationTray::ShowPopups() { +bool NotificationTray::ShowPopups() { if (IsMessageCenterVisible()) return false; @@ -414,19 +417,19 @@ return true; } -void WebNotificationTray::HidePopups() { +void NotificationTray::HidePopups() { DCHECK(popup_collection_.get()); popup_collection_->MarkAllPopupsShown(); } // Private methods. -bool WebNotificationTray::ShouldShowMessageCenter() const { +bool NotificationTray::ShouldShowMessageCenter() const { // Hidden at login screen, during supervised user creation, etc. return Shell::Get()->session_controller()->ShouldShowNotificationTray(); } -bool WebNotificationTray::IsMessageCenterVisible() const { +bool NotificationTray::IsMessageCenterVisible() const { if (switches::IsSidebarEnabled()) { Sidebar* sidebar = RootWindowController::ForWindow(GetWidget()->GetNativeView()) @@ -438,7 +441,7 @@ } } -void WebNotificationTray::UpdateAfterShelfAlignmentChange() { +void NotificationTray::UpdateAfterShelfAlignmentChange() { TrayBackgroundView::UpdateAfterShelfAlignmentChange(); // Destroy existing message center bubble so that it won't be reused. message_center_ui_controller_->HideMessageCenterBubble(); @@ -448,7 +451,7 @@ message_center_ui_controller_->ShowPopupBubble(); } -void WebNotificationTray::UpdateAfterRootWindowBoundsChange( +void NotificationTray::UpdateAfterRootWindowBoundsChange( const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) { TrayBackgroundView::UpdateAfterRootWindowBoundsChange(old_bounds, new_bounds); @@ -458,7 +461,7 @@ message_center_ui_controller_->HideMessageCenterBubble(); } -void WebNotificationTray::AnchorUpdated() { +void NotificationTray::AnchorUpdated() { if (message_center_bubble()) { UpdateClippingWindowBounds(); shelf()->GetSystemTrayAnchor()->UpdateClippingWindowBounds(); @@ -473,14 +476,14 @@ } } -base::string16 WebNotificationTray::GetAccessibleNameForTray() { +base::string16 NotificationTray::GetAccessibleNameForTray() { return l10n_util::GetStringFUTF16Int( IDS_MESSAGE_CENTER_ACCESSIBLE_NAME, static_cast<int>(message_center_ui_controller_->message_center() ->NotificationCount())); } -void WebNotificationTray::HideBubbleWithView( +void NotificationTray::HideBubbleWithView( const views::TrayBubbleView* bubble_view) { if (message_center_bubble() && bubble_view == message_center_bubble()->bubble_view()) { @@ -490,28 +493,28 @@ } } -void WebNotificationTray::BubbleViewDestroyed() { +void NotificationTray::BubbleViewDestroyed() { if (message_center_bubble()) message_center_bubble()->bubble()->BubbleViewDestroyed(); } -void WebNotificationTray::OnMouseEnteredView() {} +void NotificationTray::OnMouseEnteredView() {} -void WebNotificationTray::OnMouseExitedView() {} +void NotificationTray::OnMouseExitedView() {} -base::string16 WebNotificationTray::GetAccessibleNameForBubble() { +base::string16 NotificationTray::GetAccessibleNameForBubble() { return GetAccessibleNameForTray(); } -bool WebNotificationTray::ShouldEnableExtraKeyboardAccessibility() { +bool NotificationTray::ShouldEnableExtraKeyboardAccessibility() { return Shell::Get()->accessibility_controller()->IsSpokenFeedbackEnabled(); } -void WebNotificationTray::HideBubble(const views::TrayBubbleView* bubble_view) { +void NotificationTray::HideBubble(const views::TrayBubbleView* bubble_view) { HideBubbleWithView(bubble_view); } -bool WebNotificationTray::ShowNotifierSettings() { +bool NotificationTray::ShowNotifierSettings() { if (IsMessageCenterVisible()) { if (switches::IsSidebarEnabled()) { Sidebar* sidebar = @@ -529,17 +532,17 @@ false /* show_by_click */); } -void WebNotificationTray::OnMessageCenterContentsChanged() { +void NotificationTray::OnMessageCenterContentsChanged() { // Do not update the tray contents directly. Multiple change events can happen // consecutively, and calling Update in the middle of those events will show // intermediate unread counts for a moment. should_update_tray_content_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&WebNotificationTray::UpdateTrayContent, AsWeakPtr())); + base::BindOnce(&NotificationTray::UpdateTrayContent, AsWeakPtr())); } -void WebNotificationTray::UpdateTrayContent() { +void NotificationTray::UpdateTrayContent() { if (!should_update_tray_content_) return; should_update_tray_content_ = false; @@ -566,7 +569,7 @@ if (visible_small_icons_.count(notification->id()) != 0) continue; - auto item = std::make_unique<WebNotificationImage>( + auto item = std::make_unique<NotificationImage>( image.AsImageSkia(), animation_container_.get(), this); tray_container()->AddChildViewAt(item.get(), 0); item->SetVisible(true); @@ -576,7 +579,7 @@ // Remove unnecessary icons. for (const std::string& id : notification_ids) { - WebNotificationImage* item = visible_small_icons_[id].release(); + NotificationImage* item = visible_small_icons_[id].release(); visible_small_icons_.erase(id); item->HideAndDelete(); } @@ -606,7 +609,7 @@ SchedulePaint(); } -void WebNotificationTray::ClickedOutsideBubble() { +void NotificationTray::ClickedOutsideBubble() { // Only hide the message center if (!IsMessageCenterVisible()) return; @@ -614,7 +617,7 @@ message_center_ui_controller_->HideMessageCenterBubble(); } -bool WebNotificationTray::PerformAction(const ui::Event& event) { +bool NotificationTray::PerformAction(const ui::Event& event) { UserMetricsRecorder::RecordUserClickOnTray( LoginMetricsRecorder::TrayClickTarget::kNotificationTray); if (IsMessageCenterVisible()) @@ -624,31 +627,31 @@ return true; } -void WebNotificationTray::CloseBubble() { +void NotificationTray::CloseBubble() { message_center_ui_controller_->HideMessageCenterBubble(); } -void WebNotificationTray::ShowBubble(bool show_by_click) { +void NotificationTray::ShowBubble(bool show_by_click) { if (!IsMessageCenterVisible()) message_center_ui_controller_->ShowMessageCenterBubble(show_by_click); } -views::TrayBubbleView* WebNotificationTray::GetBubbleView() { +views::TrayBubbleView* NotificationTray::GetBubbleView() { return message_center_bubble_ ? message_center_bubble_->bubble_view() : nullptr; } -message_center::MessageCenter* WebNotificationTray::message_center() const { +message_center::MessageCenter* NotificationTray::message_center() const { return message_center_ui_controller_->message_center(); } // Methods for testing -bool WebNotificationTray::IsPopupVisible() const { +bool NotificationTray::IsPopupVisible() const { return message_center_ui_controller_->popups_visible(); } -MessageCenterBubble* WebNotificationTray::GetMessageCenterBubbleForTest() { +MessageCenterBubble* NotificationTray::GetMessageCenterBubbleForTest() { if (!message_center_bubble()) return nullptr; return static_cast<MessageCenterBubble*>(message_center_bubble()->bubble());
diff --git a/ash/system/web_notification/web_notification_tray.h b/ash/system/message_center/notification_tray.h similarity index 67% rename from ash/system/web_notification/web_notification_tray.h rename to ash/system/message_center/notification_tray.h index e2c18f6..1ed0312 100644 --- a/ash/system/web_notification/web_notification_tray.h +++ b/ash/system/message_center/notification_tray.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_WEB_NOTIFICATION_WEB_NOTIFICATION_TRAY_H_ -#define ASH_SYSTEM_WEB_NOTIFICATION_WEB_NOTIFICATION_TRAY_H_ +#ifndef ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_TRAY_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_TRAY_H_ #include <memory> @@ -25,29 +25,25 @@ class MessageCenter; class MessagePopupCollection; class UiController; -} +} // namespace message_center namespace ash { class AshPopupAlignmentDelegate; class MessageCenterBubble; -class WebNotificationBubbleWrapper; -class WebNotificationImage; -class WebNotificationLabel; +class NotificationBubbleWrapper; +class NotificationImage; +class NotificationLabel; -// Status area tray for showing browser and app notifications. This hosts -// a MessageCenter class which manages the notification list. This class -// contains the Ash specific tray implementation. -// -// Note: These are not related to system notifications (i.e NotificationView -// generated by SystemTrayItem). Visibility of one notification type or other -// is controlled by StatusAreaWidget. -class ASH_EXPORT WebNotificationTray +// Status area tray for showing System, Chrome App, Web and ARC++ app +// notifications. This hosts a MessageCenter class which manages the +// notification list. This class contains the Ash specific tray implementation. +class ASH_EXPORT NotificationTray : public TrayBackgroundView, public message_center::UiDelegate, - public base::SupportsWeakPtr<WebNotificationTray> { + public base::SupportsWeakPtr<NotificationTray> { public: - WebNotificationTray(Shelf* shelf, aura::Window* status_area_window); - ~WebNotificationTray() override; + NotificationTray(Shelf* shelf, aura::Window* status_area_window); + ~NotificationTray() override; static void DisableAnimationsForTest(bool disable); @@ -94,19 +90,19 @@ message_center::MessageCenter* message_center() const; private: - friend class WebNotificationTrayTest; + friend class NotificationTrayTest; - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, WebNotifications); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, WebNotificationPopupBubble); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, Notifications); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, NotificationPopupBubble); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, ManyMessageCenterNotifications); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, ManyPopupNotifications); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, PopupShownOnBothDisplays); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, PopupAndSystemTray); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, PopupAndAutoHideShelf); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, VisibleSmallIcon); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, QuietModeIcon); - FRIEND_TEST_ALL_PREFIXES(WebNotificationTrayTest, CloseOnActivation); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, ManyPopupNotifications); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, PopupShownOnBothDisplays); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, PopupAndSystemTray); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, PopupAndAutoHideShelf); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, VisibleSmallIcon); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, QuietModeIcon); + FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, CloseOnActivation); void UpdateTrayContent(); @@ -120,7 +116,7 @@ // the message center. bool ShouldShowMessageCenter() const; - WebNotificationBubbleWrapper* message_center_bubble() const { + NotificationBubbleWrapper* message_center_bubble() const { return message_center_bubble_.get(); } @@ -130,16 +126,16 @@ aura::Window* status_area_window_; std::unique_ptr<message_center::UiController> message_center_ui_controller_; - std::unique_ptr<WebNotificationBubbleWrapper> message_center_bubble_; + std::unique_ptr<NotificationBubbleWrapper> message_center_bubble_; std::unique_ptr<message_center::MessagePopupCollection> popup_collection_; std::unique_ptr<views::View> bell_icon_; std::unique_ptr<views::View> quiet_mode_icon_; - std::unique_ptr<WebNotificationLabel> counter_; + std::unique_ptr<NotificationLabel> counter_; scoped_refptr<gfx::AnimationContainer> animation_container_ = new gfx::AnimationContainer(); - std::unordered_map<std::string, std::unique_ptr<WebNotificationImage>> + std::unordered_map<std::string, std::unique_ptr<NotificationImage>> visible_small_icons_; bool show_message_center_on_unlock_; @@ -148,9 +144,9 @@ std::unique_ptr<AshPopupAlignmentDelegate> popup_alignment_delegate_; - DISALLOW_COPY_AND_ASSIGN(WebNotificationTray); + DISALLOW_COPY_AND_ASSIGN(NotificationTray); }; } // namespace ash -#endif // ASH_SYSTEM_WEB_NOTIFICATION_WEB_NOTIFICATION_TRAY_H_ +#endif // ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_TRAY_H_
diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/message_center/notification_tray_unittest.cc similarity index 90% rename from ash/system/web_notification/web_notification_tray_unittest.cc rename to ash/system/message_center/notification_tray_unittest.cc index f013a4e..cebfad4 100644 --- a/ash/system/web_notification/web_notification_tray_unittest.cc +++ b/ash/system/message_center/notification_tray_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/web_notification_tray.h" +#include "ash/system/message_center/notification_tray.h" #include <memory> #include <utility> @@ -15,16 +15,17 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" +#include "ash/system/message_center/ash_popup_alignment_delegate.h" #include "ash/system/screen_layout_observer.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_container.h" -#include "ash/system/web_notification/ash_popup_alignment_delegate.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" +#include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "ui/display/display.h" @@ -50,16 +51,15 @@ namespace { -WebNotificationTray* GetTray() { - return StatusAreaWidgetTestHelper::GetStatusAreaWidget() - ->web_notification_tray(); +NotificationTray* GetTray() { + return StatusAreaWidgetTestHelper::GetStatusAreaWidget()->notification_tray(); } -WebNotificationTray* GetSecondaryTray() { +NotificationTray* GetSecondaryTray() { StatusAreaWidget* status_area_widget = StatusAreaWidgetTestHelper::GetSecondaryStatusAreaWidget(); if (status_area_widget) - return status_area_widget->web_notification_tray(); + return status_area_widget->notification_tray(); return NULL; } @@ -89,10 +89,10 @@ } // namespace -class WebNotificationTrayTest : public AshTestBase { +class NotificationTrayTest : public AshTestBase { public: - WebNotificationTrayTest() = default; - ~WebNotificationTrayTest() override = default; + NotificationTrayTest() = default; + ~NotificationTrayTest() override = default; protected: void AddNotification(const std::string& id) { @@ -130,7 +130,7 @@ return GetPopupWorkAreaBottomForTray(GetTray()); } - int GetPopupWorkAreaBottomForTray(WebNotificationTray* tray) { + int GetPopupWorkAreaBottomForTray(NotificationTray* tray) { return tray->popup_alignment_delegate_->GetWorkArea().bottom(); } @@ -146,10 +146,10 @@ } private: - DISALLOW_COPY_AND_ASSIGN(WebNotificationTrayTest); + DISALLOW_COPY_AND_ASSIGN(NotificationTrayTest); }; -TEST_F(WebNotificationTrayTest, WebNotifications) { +TEST_F(NotificationTrayTest, Notifications) { // TODO(mukai): move this test case to ui/message_center. ASSERT_TRUE(GetWidget()); @@ -179,7 +179,7 @@ EXPECT_FALSE(GetMessageCenter()->FindVisibleNotificationById("test_id3")); } -TEST_F(WebNotificationTrayTest, WebNotificationPopupBubble) { +TEST_F(NotificationTrayTest, NotificationPopupBubble) { // TODO(mukai): move this test case to ui/message_center. ASSERT_TRUE(GetWidget()); @@ -214,7 +214,7 @@ using message_center::NotificationList; -TEST_F(WebNotificationTrayTest, ManyMessageCenterNotifications) { +TEST_F(NotificationTrayTest, ManyMessageCenterNotifications) { // Add the max visible notifications +1, ensure the correct visible number. size_t notifications_to_add = MessageCenterView::kMaxVisibleNotifications + 1; for (size_t i = 0; i < notifications_to_add; ++i) { @@ -225,7 +225,7 @@ GetTray()->message_center_ui_controller_->ShowMessageCenterBubble( false /* show_by_click */); EXPECT_TRUE(shown); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(GetTray()->message_center_bubble() != NULL); EXPECT_EQ(notifications_to_add, GetMessageCenter()->NotificationCount()); EXPECT_EQ( @@ -233,7 +233,7 @@ GetTray()->GetMessageCenterBubbleForTest()->NumMessageViewsForTest()); } -TEST_F(WebNotificationTrayTest, ManyPopupNotifications) { +TEST_F(NotificationTrayTest, ManyPopupNotifications) { // Add the max visible popup notifications +1, ensure the correct num visible. size_t notifications_to_add = message_center::kMaxVisiblePopupNotifications + 1; @@ -250,7 +250,7 @@ } // Verifies if the notification appears on both displays when extended mode. -TEST_F(WebNotificationTrayTest, PopupShownOnBothDisplays) { +TEST_F(NotificationTrayTest, PopupShownOnBothDisplays) { Shell::Get()->screen_layout_observer()->set_show_notifications_for_testing( true); @@ -269,7 +269,7 @@ // OnNativeDisplaysChanged() creates the display notifications, so popup is // visible. EXPECT_TRUE(GetTray()->IsPopupVisible()); - WebNotificationTray* secondary_tray = GetSecondaryTray(); + NotificationTray* secondary_tray = GetSecondaryTray(); ASSERT_TRUE(secondary_tray); EXPECT_TRUE(secondary_tray->IsPopupVisible()); @@ -306,7 +306,7 @@ // PopupAndSystemTray may fail in platforms other than ChromeOS because the // RootWindow's bound can be bigger than display::Display's work area so that // openingsystem tray doesn't affect at all the work area of popups. -TEST_F(WebNotificationTrayTest, PopupAndSystemTray) { +TEST_F(NotificationTrayTest, PopupAndSystemTray) { GetSystemTray()->AddTrayItem(std::make_unique<TestItem>()); AddNotification("test_id"); @@ -322,7 +322,7 @@ EXPECT_GT(bottom, bottom_with_tray); } -TEST_F(WebNotificationTrayTest, PopupAndAutoHideShelf) { +TEST_F(NotificationTrayTest, PopupAndAutoHideShelf) { AddNotification("test_id"); EXPECT_TRUE(GetTray()->IsPopupVisible()); int bottom = GetPopupWorkAreaBottom(); @@ -355,7 +355,7 @@ EXPECT_GT(bottom_auto_shown, bottom_with_tray); } -TEST_F(WebNotificationTrayTest, PopupAndFullscreen) { +TEST_F(NotificationTrayTest, PopupAndFullscreen) { AddNotification("test_id"); EXPECT_TRUE(IsPopupVisible()); int bottom = GetPopupWorkAreaBottom(); @@ -374,7 +374,7 @@ wm::GetWindowState(widget->GetNativeWindow()) ->SetHideShelfWhenFullscreen(false); widget->SetFullscreen(true); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // The work area for auto-hidden status of fullscreen is a bit larger // since it doesn't even have the 3-pixel width. @@ -399,7 +399,7 @@ EXPECT_EQ(bottom_auto_hidden, GetPopupWorkAreaBottom()); } -TEST_F(WebNotificationTrayTest, PopupAndSystemTrayMultiDisplay) { +TEST_F(NotificationTrayTest, PopupAndSystemTrayMultiDisplay) { UpdateDisplay("800x600,600x400"); AddNotification("test_id"); @@ -414,7 +414,7 @@ EXPECT_EQ(bottom_second, GetPopupWorkAreaBottomForTray(GetSecondaryTray())); } -TEST_F(WebNotificationTrayTest, VisibleSmallIcon) { +TEST_F(NotificationTrayTest, VisibleSmallIcon) { EXPECT_EQ(0u, GetTray()->visible_small_icons_.size()); EXPECT_EQ(3, GetTray()->tray_container()->child_count()); std::unique_ptr<message_center::Notification> notification = @@ -429,23 +429,23 @@ message_center::RichNotificationData(), nullptr /* delegate */); notification->set_small_image(gfx::test::CreateImage(18, 18)); GetMessageCenter()->AddNotification(std::move(notification)); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, GetTray()->visible_small_icons_.size()); EXPECT_EQ(4, GetTray()->tray_container()->child_count()); } -TEST_F(WebNotificationTrayTest, QuietModeIcon) { - WebNotificationTray::DisableAnimationsForTest(true); +TEST_F(NotificationTrayTest, QuietModeIcon) { + NotificationTray::DisableAnimationsForTest(true); AddNotification("test"); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // There is a notification, so no bell & quiet mode icons are shown. EXPECT_FALSE(GetTray()->bell_icon_->visible()); EXPECT_FALSE(GetTray()->quiet_mode_icon_->visible()); GetMessageCenter()->SetQuietMode(true); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // If there is a notification, setting quiet mode shouldn't change tray icons. EXPECT_FALSE(GetTray()->bell_icon_->visible()); @@ -454,27 +454,27 @@ GetMessageCenter()->SetQuietMode(false); GetMessageCenter()->RemoveAllNotifications( false /* by_user */, message_center::MessageCenter::RemoveType::ALL); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // If there is no notification, bell icon should be shown. EXPECT_TRUE(GetTray()->bell_icon_->visible()); EXPECT_FALSE(GetTray()->quiet_mode_icon_->visible()); GetMessageCenter()->SetQuietMode(true); - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // If there is no notification and quiet mode is set, it should show quiet // mode icon. EXPECT_FALSE(GetTray()->bell_icon_->visible()); EXPECT_TRUE(GetTray()->quiet_mode_icon_->visible()); - WebNotificationTray::DisableAnimationsForTest(false); + NotificationTray::DisableAnimationsForTest(false); } // Makes sure that the system tray bubble closes when another window is // activated, and does not crash regardless of the initial activation state. -TEST_F(WebNotificationTrayTest, CloseOnActivation) { - WebNotificationTray* tray = GetTray(); +TEST_F(NotificationTrayTest, CloseOnActivation) { + NotificationTray* tray = GetTray(); // Show the web notification bubble. tray->ShowBubble(false /* show_by_click */); @@ -489,7 +489,7 @@ EXPECT_FALSE(tray->message_center_bubble()); // Wait for bubble to actually close. - RunAllPendingInMessageLoop(); + base::RunLoop().RunUntilIdle(); // Show a second widget. std::unique_ptr<views::Widget> second_widget(CreateTestWidget());
diff --git a/ash/system/web_notification/session_state_notification_blocker.cc b/ash/system/message_center/session_state_notification_blocker.cc similarity index 97% rename from ash/system/web_notification/session_state_notification_blocker.cc rename to ash/system/message_center/session_state_notification_blocker.cc index e01c4b3..4f3bd1a 100644 --- a/ash/system/web_notification/session_state_notification_blocker.cc +++ b/ash/system/message_center/session_state_notification_blocker.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/session_state_notification_blocker.h" +#include "ash/system/message_center/session_state_notification_blocker.h" #include "ash/public/cpp/ash_features.h" #include "ash/session/session_controller.h"
diff --git a/ash/system/web_notification/session_state_notification_blocker.h b/ash/system/message_center/session_state_notification_blocker.h similarity index 88% rename from ash/system/web_notification/session_state_notification_blocker.h rename to ash/system/message_center/session_state_notification_blocker.h index 0a51375..495a757 100644 --- a/ash/system/web_notification/session_state_notification_blocker.h +++ b/ash/system/message_center/session_state_notification_blocker.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_WEB_NOTIFICATION_SESSION_STATE_NOTIFICATION_BLOCKER_H_ -#define ASH_SYSTEM_WEB_NOTIFICATION_SESSION_STATE_NOTIFICATION_BLOCKER_H_ +#ifndef ASH_SYSTEM_MESSAGE_CENTER_SESSION_STATE_NOTIFICATION_BLOCKER_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_SESSION_STATE_NOTIFICATION_BLOCKER_H_ #include "ash/ash_export.h" #include "ash/session/session_observer.h" @@ -47,4 +47,4 @@ } // namespace ash -#endif // ASH_SYSTEM_WEB_NOTIFICATION_SESSION_STATE_NOTIFICATION_BLOCKER_H_ +#endif // ASH_SYSTEM_MESSAGE_CENTER_SESSION_STATE_NOTIFICATION_BLOCKER_H_
diff --git a/ash/system/web_notification/session_state_notification_blocker_unittest.cc b/ash/system/message_center/session_state_notification_blocker_unittest.cc similarity index 98% rename from ash/system/web_notification/session_state_notification_blocker_unittest.cc rename to ash/system/message_center/session_state_notification_blocker_unittest.cc index f87f064..96f1a6b5 100644 --- a/ash/system/web_notification/session_state_notification_blocker_unittest.cc +++ b/ash/system/message_center/session_state_notification_blocker_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/web_notification/session_state_notification_blocker.h" +#include "ash/system/message_center/session_state_notification_blocker.h" #include <memory>
diff --git a/ash/system/screen_layout_observer_unittest.cc b/ash/system/screen_layout_observer_unittest.cc index 126a4f0..51e37c3f8 100644 --- a/ash/system/screen_layout_observer_unittest.cc +++ b/ash/system/screen_layout_observer_unittest.cc
@@ -6,8 +6,8 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/tray/system_tray.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" @@ -39,11 +39,11 @@ protected: void SetUp() override { AshTestBase::SetUp(); - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); } void TearDown() override { - WebNotificationTray::DisableAnimationsForTest(false); + NotificationTray::DisableAnimationsForTest(false); AshTestBase::TearDown(); }
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc index 40084fe..5d1e8036 100644 --- a/ash/system/status_area_widget.cc +++ b/ash/system/status_area_widget.cc
@@ -13,6 +13,7 @@ #include "ash/system/dictation/dictation_button_tray.h" #include "ash/system/flag_warning/flag_warning_tray.h" #include "ash/system/ime_menu/ime_menu_tray.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/overview/overview_button_tray.h" #include "ash/system/palette/palette_tray.h" #include "ash/system/session/logout_button_tray.h" @@ -20,7 +21,6 @@ #include "ash/system/tray/system_tray.h" #include "ash/system/unified/unified_system_tray.h" #include "ash/system/virtual_keyboard/virtual_keyboard_tray.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "base/command_line.h" #include "base/i18n/time_formatting.h" #include "ui/display/display.h" @@ -60,9 +60,9 @@ // Must happen after the widget is initialized so the native window exists. if (!features::IsSystemTrayUnifiedEnabled()) { - web_notification_tray_ = - std::make_unique<WebNotificationTray>(shelf_, GetNativeWindow()); - status_area_widget_delegate_->AddChildView(web_notification_tray_.get()); + notification_tray_ = + std::make_unique<NotificationTray>(shelf_, GetNativeWindow()); + status_area_widget_delegate_->AddChildView(notification_tray_.get()); } palette_tray_ = std::make_unique<PaletteTray>(shelf_); @@ -103,9 +103,9 @@ status_area_widget_delegate_->UpdateLayout(); // Initialize after all trays have been created. - if (web_notification_tray_) { - system_tray_->InitializeTrayItems(web_notification_tray_.get()); - web_notification_tray_->Initialize(); + if (notification_tray_) { + system_tray_->InitializeTrayItems(notification_tray_.get()); + notification_tray_->Initialize(); } else { system_tray_->InitializeTrayItems(nullptr); } @@ -128,8 +128,8 @@ StatusAreaWidget::~StatusAreaWidget() { system_tray_->Shutdown(); - web_notification_tray_.reset(); - // Must be destroyed after |web_notification_tray_|. + notification_tray_.reset(); + // Must be destroyed after |notification_tray_|. system_tray_.reset(); unified_system_tray_.reset(); ime_menu_tray_.reset(); @@ -147,8 +147,8 @@ void StatusAreaWidget::UpdateAfterShelfAlignmentChange() { system_tray_->UpdateAfterShelfAlignmentChange(); - if (web_notification_tray_) - web_notification_tray_->UpdateAfterShelfAlignmentChange(); + if (notification_tray_) + notification_tray_->UpdateAfterShelfAlignmentChange(); logout_button_tray_->UpdateAfterShelfAlignmentChange(); virtual_keyboard_tray_->UpdateAfterShelfAlignmentChange(); ime_menu_tray_->UpdateAfterShelfAlignmentChange(); @@ -206,14 +206,13 @@ bool StatusAreaWidget::IsMessageBubbleShown() const { return system_tray_->IsSystemBubbleVisible() || - (web_notification_tray_ && - web_notification_tray_->IsMessageCenterVisible()); + (notification_tray_ && notification_tray_->IsMessageCenterVisible()); } void StatusAreaWidget::SchedulePaint() { status_area_widget_delegate_->SchedulePaint(); - if (web_notification_tray_) - web_notification_tray_->SchedulePaint(); + if (notification_tray_) + notification_tray_->SchedulePaint(); system_tray_->SchedulePaint(); virtual_keyboard_tray_->SchedulePaint(); logout_button_tray_->SchedulePaint(); @@ -241,8 +240,8 @@ } void StatusAreaWidget::UpdateShelfItemBackground(SkColor color) { - if (web_notification_tray_) - web_notification_tray_->UpdateShelfItemBackground(color); + if (notification_tray_) + notification_tray_->UpdateShelfItemBackground(color); system_tray_->UpdateShelfItemBackground(color); virtual_keyboard_tray_->UpdateShelfItemBackground(color); ime_menu_tray_->UpdateShelfItemBackground(color);
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h index 8e78818..8db1bbf 100644 --- a/ash/system/status_area_widget.h +++ b/ash/system/status_area_widget.h
@@ -30,7 +30,7 @@ class UnifiedSystemTray; class TrayBackgroundView; class VirtualKeyboardTray; -class WebNotificationTray; +class NotificationTray; // Widget showing the system tray, notification tray, and other tray views in // the bottom-right of the screen. Exists separately from ShelfView/ShelfWidget @@ -71,9 +71,7 @@ UnifiedSystemTray* unified_system_tray() { return unified_system_tray_.get(); } - WebNotificationTray* web_notification_tray() { - return web_notification_tray_.get(); - } + NotificationTray* notification_tray() { return notification_tray_.get(); } DictationButtonTray* dictation_button_tray() { return dictation_button_tray_.get(); } @@ -129,7 +127,7 @@ std::unique_ptr<DictationButtonTray> dictation_button_tray_; std::unique_ptr<SystemTray> system_tray_; std::unique_ptr<UnifiedSystemTray> unified_system_tray_; - std::unique_ptr<WebNotificationTray> web_notification_tray_; + std::unique_ptr<NotificationTray> notification_tray_; std::unique_ptr<LogoutButtonTray> logout_button_tray_; std::unique_ptr<PaletteTray> palette_tray_; std::unique_ptr<VirtualKeyboardTray> virtual_keyboard_tray_;
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc index 0825928..cbefd86 100644 --- a/ash/system/status_area_widget_unittest.cc +++ b/ash/system/status_area_widget_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" #include "ash/system/ime_menu/ime_menu_tray.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/overview/overview_button_tray.h" #include "ash/system/palette/palette_tray.h" #include "ash/system/session/logout_button_tray.h" @@ -19,7 +20,6 @@ #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/virtual_keyboard/virtual_keyboard_tray.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/test/ash_test_base.h" #include "base/command_line.h" #include "base/test/scoped_feature_list.h" @@ -47,20 +47,20 @@ // Default trays are constructed. EXPECT_TRUE(status->overview_button_tray()); EXPECT_TRUE(status->system_tray()); - EXPECT_TRUE(status->web_notification_tray()); + EXPECT_TRUE(status->notification_tray()); EXPECT_TRUE(status->logout_button_tray_for_testing()); EXPECT_TRUE(status->ime_menu_tray()); EXPECT_TRUE(status->virtual_keyboard_tray_for_testing()); EXPECT_TRUE(status->palette_tray()); - // Needed because WebNotificationTray updates its initial visibility + // Needed because NotificationTray updates its initial visibility // asynchronously. RunAllPendingInMessageLoop(); // Default trays are visible. EXPECT_FALSE(status->overview_button_tray()->visible()); EXPECT_TRUE(status->system_tray()->visible()); - EXPECT_TRUE(status->web_notification_tray()->visible()); + EXPECT_TRUE(status->notification_tray()->visible()); EXPECT_FALSE(status->logout_button_tray_for_testing()->visible()); EXPECT_FALSE(status->ime_menu_tray()->visible()); EXPECT_FALSE(status->virtual_keyboard_tray_for_testing()->visible()); @@ -138,19 +138,19 @@ // Default trays are constructed. ASSERT_TRUE(status->overview_button_tray()); ASSERT_TRUE(status->system_tray()); - ASSERT_TRUE(status->web_notification_tray()); + ASSERT_TRUE(status->notification_tray()); ASSERT_TRUE(status->logout_button_tray_for_testing()); ASSERT_TRUE(status->ime_menu_tray()); ASSERT_TRUE(status->virtual_keyboard_tray_for_testing()); - // Needed because WebNotificationTray updates its initial visibility + // Needed because NotificationTray updates its initial visibility // asynchronously. RunAllPendingInMessageLoop(); // Default trays are visible. ASSERT_FALSE(status->overview_button_tray()->visible()); ASSERT_TRUE(status->system_tray()->visible()); - ASSERT_TRUE(status->web_notification_tray()->visible()); + ASSERT_TRUE(status->notification_tray()->visible()); ASSERT_FALSE(status->logout_button_tray_for_testing()->visible()); ASSERT_FALSE(status->ime_menu_tray()->visible()); ASSERT_FALSE(status->virtual_keyboard_tray_for_testing()->visible()); @@ -162,7 +162,7 @@ // A tab key event will move focus to web notification tray. GenerateTabEvent(false); - EXPECT_EQ(status->web_notification_tray(), focus_manager->GetFocusedView()); + EXPECT_EQ(status->notification_tray(), focus_manager->GetFocusedView()); EXPECT_EQ(0, test_observer_->focus_out_count()); EXPECT_EQ(0, test_observer_->reverse_focus_out_count()); @@ -176,7 +176,7 @@ // A reverse tab key event will send reverse FocusOut event, since we are not // handling this event, focus will still be moved to web notification tray. GenerateTabEvent(true); - EXPECT_EQ(status->web_notification_tray(), focus_manager->GetFocusedView()); + EXPECT_EQ(status->notification_tray(), focus_manager->GetFocusedView()); EXPECT_EQ(1, test_observer_->focus_out_count()); EXPECT_EQ(1, test_observer_->reverse_focus_out_count()); }
diff --git a/ash/system/tray/interacted_by_tap_recorder.cc b/ash/system/tray/interacted_by_tap_recorder.cc new file mode 100644 index 0000000..30e77a8f --- /dev/null +++ b/ash/system/tray/interacted_by_tap_recorder.cc
@@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/tray/interacted_by_tap_recorder.h" + +#include "base/metrics/histogram_macros.h" +#include "ui/events/event.h" +#include "ui/views/view.h" + +namespace ash { + +InteractedByTapRecorder::InteractedByTapRecorder(views::View* target_view) { + target_view->AddPreTargetHandler(this); +} + +void InteractedByTapRecorder::OnEvent(ui::Event* event) { + if (event->type() == ui::ET_GESTURE_TAP) { + UMA_HISTOGRAM_ENUMERATION("ChromeOS.SystemTray.Interaction", + INTERACTION_TYPE_TAP, INTERACTION_TYPE_COUNT); + } else if (event->type() == ui::ET_MOUSE_PRESSED) { + UMA_HISTOGRAM_ENUMERATION("ChromeOS.SystemTray.Interaction", + INTERACTION_TYPE_CLICK, INTERACTION_TYPE_COUNT); + } +} + +} // namespace ash
diff --git a/ash/system/tray/interacted_by_tap_recorder.h b/ash/system/tray/interacted_by_tap_recorder.h new file mode 100644 index 0000000..1fb4ec2 --- /dev/null +++ b/ash/system/tray/interacted_by_tap_recorder.h
@@ -0,0 +1,40 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_TRAY_INTERACTED_BY_TAP_RECORDER_H_ +#define ASH_SYSTEM_TRAY_INTERACTED_BY_TAP_RECORDER_H_ + +#include "ui/events/event_handler.h" + +namespace views { +class View; +} // namespace views + +namespace ash { + +// An event handler that will be installed as system tray view PreTargetHandler +// to record Interaction metrics. +class InteractedByTapRecorder : public ui::EventHandler { + public: + InteractedByTapRecorder(views::View* target_view); + ~InteractedByTapRecorder() override = default; + + // Type of interaction. This enum is used to back an UMA histogram and should + // be treated as append-only. + enum InteractionType { + INTERACTION_TYPE_TAP = 0, + INTERACTION_TYPE_CLICK, + INTERACTION_TYPE_COUNT + }; + + private: + // ui::EventHandler: + void OnEvent(ui::Event* event) override; + + DISALLOW_COPY_AND_ASSIGN(InteractedByTapRecorder); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_TRAY_INTERACTED_BY_TAP_RECORDER_H_
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index ad1a282..139ff5e 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc
@@ -32,6 +32,7 @@ #include "ash/system/ime/tray_ime_chromeos.h" #include "ash/system/keyboard_brightness/tray_keyboard_brightness.h" #include "ash/system/media_security/multi_profile_media_tray_item.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/model/clock_model.h" #include "ash/system/model/system_tray_model.h" #include "ash/system/network/tray_network.h" @@ -58,7 +59,6 @@ #include "ash/system/unified/unified_system_tray.h" #include "ash/system/update/tray_update.h" #include "ash/system/user/tray_user.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/wm/container_finder.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/widget_finder.h" @@ -236,17 +236,16 @@ item->OnTrayViewDestroyed(); } -void SystemTray::InitializeTrayItems( - WebNotificationTray* web_notification_tray) { - DCHECK(web_notification_tray || features::IsSystemTrayUnifiedEnabled()); - web_notification_tray_ = web_notification_tray; +void SystemTray::InitializeTrayItems(NotificationTray* notification_tray) { + DCHECK(notification_tray || features::IsSystemTrayUnifiedEnabled()); + notification_tray_ = notification_tray; TrayBackgroundView::Initialize(); CreateItems(); } void SystemTray::Shutdown() { - DCHECK(web_notification_tray_ || features::IsSystemTrayUnifiedEnabled()); - web_notification_tray_ = nullptr; + DCHECK(notification_tray_ || features::IsSystemTrayUnifiedEnabled()); + notification_tray_ = nullptr; } void SystemTray::CreateItems() { @@ -564,8 +563,8 @@ height = std::max(0, work_area.bottom() - bubble_view->GetBoundsInScreen().y()); } - if (web_notification_tray_) - web_notification_tray_->SetTrayBubbleHeight(height); + if (notification_tray_) + notification_tray_->SetTrayBubbleHeight(height); } base::string16 SystemTray::GetAccessibleTimeString(
diff --git a/ash/system/tray/system_tray.h b/ash/system/tray/system_tray.h index 8d0db51..d545436e 100644 --- a/ash/system/tray/system_tray.h +++ b/ash/system/tray/system_tray.h
@@ -22,6 +22,7 @@ namespace ash { enum class LoginStatus; +class NotificationTray; class ScreenTrayItem; class SystemBubbleWrapper; class SystemTrayItem; @@ -42,7 +43,6 @@ class TrayTracing; class TrayUpdate; class TrayVPN; -class WebNotificationTray; // There are different methods for creating bubble views. enum BubbleCreationType { @@ -66,7 +66,7 @@ // Calls TrayBackgroundView::Initialize(), creates the tray items, and // adds them to SystemTrayNotifier. - void InitializeTrayItems(WebNotificationTray* web_notification_tray); + void InitializeTrayItems(NotificationTray* notification_tray); // Resets internal pointers. This has to be called before deletion. void Shutdown(); @@ -210,7 +210,7 @@ void RecordSystemMenuMetrics(); // The web notification tray view that appears adjacent to this view. - WebNotificationTray* web_notification_tray_ = nullptr; + NotificationTray* notification_tray_ = nullptr; // Items. std::vector<std::unique_ptr<SystemTrayItem>> items_;
diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc index a3154eec..1ffb2be6 100644 --- a/ash/system/tray/system_tray_unittest.cc +++ b/ash/system/tray/system_tray_unittest.cc
@@ -18,6 +18,7 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" #include "ash/system/tray/system_tray_bubble.h" @@ -25,7 +26,6 @@ #include "ash/system/tray/test_system_tray_item.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray_drag_controller.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test/ash_test_views_delegate.h" @@ -969,9 +969,8 @@ TEST_F(SystemTrayTest, SystemTrayHeightWithBubble) { SystemTray* tray = GetPrimarySystemTray(); - WebNotificationTray* notification_tray = - StatusAreaWidgetTestHelper::GetStatusAreaWidget() - ->web_notification_tray(); + NotificationTray* notification_tray = + StatusAreaWidgetTestHelper::GetStatusAreaWidget()->notification_tray(); // Ensure the initial tray bubble height is zero. EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test());
diff --git a/ash/system/tray/system_tray_view.cc b/ash/system/tray/system_tray_view.cc index b9b34c0..2cc50fe 100644 --- a/ash/system/tray/system_tray_view.cc +++ b/ash/system/tray/system_tray_view.cc
@@ -5,6 +5,7 @@ #include "ash/system/tray/system_tray_view.h" #include "ash/shell.h" +#include "ash/system/tray/interacted_by_tap_recorder.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_item.h" #include "base/metrics/histogram_macros.h" @@ -52,6 +53,8 @@ const std::vector<ash::SystemTrayItem*>& items) : time_to_click_recorder_( std::make_unique<TimeToClickRecorder>(system_tray, this)), + interacted_by_tap_recorder_( + std::make_unique<InteractedByTapRecorder>(this)), items_(items), system_tray_type_(system_tray_type) { SetLayoutManager(std::make_unique<BottomAlignedBoxLayout>());
diff --git a/ash/system/tray/system_tray_view.h b/ash/system/tray/system_tray_view.h index bc5691d..d02b2e3b 100644 --- a/ash/system/tray/system_tray_view.h +++ b/ash/system/tray/system_tray_view.h
@@ -43,6 +43,7 @@ std::map<SystemTrayItem::UmaType, views::View*> tray_item_view_map_; std::unique_ptr<ui::EventHandler> time_to_click_recorder_; + std::unique_ptr<ui::EventHandler> interacted_by_tap_recorder_; std::vector<ash::SystemTrayItem*> items_;
diff --git a/ash/system/tray_caps_lock_unittest.cc b/ash/system/tray_caps_lock_unittest.cc index 6a04ccd..ad06b86b 100644 --- a/ash/system/tray_caps_lock_unittest.cc +++ b/ash/system/tray_caps_lock_unittest.cc
@@ -4,9 +4,9 @@ #include "ash/system/tray_caps_lock.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_test_api.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/test/ash_test_base.h" namespace ash { @@ -18,11 +18,11 @@ void SetUp() override { AshTestBase::SetUp(); - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); } void TearDown() override { - WebNotificationTray::DisableAnimationsForTest(false); + NotificationTray::DisableAnimationsForTest(false); AshTestBase::TearDown(); }
diff --git a/ash/system/tray_drag_controller.h b/ash/system/tray_drag_controller.h index 6fd32ab..d96d88f8 100644 --- a/ash/system/tray_drag_controller.h +++ b/ash/system/tray_drag_controller.h
@@ -15,7 +15,7 @@ // The TrayDragController helps to process the swiping events that happened on // TrayBackgroundView or TrayBubbleView. Not all the TrayBackgroundView can be // dragged currently. Only ImeMenuTray, SystemTray, PaletteTray, -// WebNotificationTray and their associated tray bubbles can be dragged. +// NotificationTray and their associated tray bubbles can be dragged. class ASH_EXPORT TrayDragController { public: // The threshold of the velocity of the fling event.
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index e4e70df..9ce5cb1 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -6,13 +6,13 @@ #include "ash/shell.h" #include "ash/system/date/date_view.h" +#include "ash/system/message_center/ash_popup_alignment_delegate.h" #include "ash/system/model/system_tray_model.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/tray_container.h" #include "ash/system/unified/unified_system_tray_bubble.h" #include "ash/system/unified/unified_system_tray_model.h" -#include "ash/system/web_notification/ash_popup_alignment_delegate.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/message_center/message_center.h"
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc index 1072f32..0448390 100644 --- a/ash/system/unified/unified_system_tray_view.cc +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -5,6 +5,7 @@ #include "ash/system/unified/unified_system_tray_view.h" #include "ash/public/cpp/app_list/app_list_features.h" +#include "ash/system/tray/interacted_by_tap_recorder.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/feature_pod_button.h" #include "ash/system/unified/feature_pods_container_view.h" @@ -106,7 +107,9 @@ sliders_container_(new UnifiedSlidersContainerView(initially_expanded)), system_info_view_(new UnifiedSystemInfoView()), system_tray_container_(new views::View()), - detailed_view_container_(new DetailedViewContainer()) { + detailed_view_container_(new DetailedViewContainer()), + interacted_by_tap_recorder_( + std::make_unique<InteractedByTapRecorder>(this)) { DCHECK(controller_); auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h index e6a4a1e..c91462c5 100644 --- a/ash/system/unified/unified_system_tray_view.h +++ b/ash/system/unified/unified_system_tray_view.h
@@ -81,6 +81,8 @@ views::View* system_tray_container_; views::View* detailed_view_container_; + const std::unique_ptr<ui::EventHandler> interacted_by_tap_recorder_; + DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTrayView); };
diff --git a/ash/test/ash_test_suite.cc b/ash/test/ash_test_suite.cc index 4c17af8..9e97c1a6 100644 --- a/ash/test/ash_test_suite.cc +++ b/ash/test/ash_test_suite.cc
@@ -60,14 +60,12 @@ ash_test_resources_200, ui::SCALE_FACTOR_200P); } - const bool is_mus = features::IsMusEnabled(); const bool is_mash = base::FeatureList::IsEnabled(features::kMash); - AshTestHelper::config_ = - is_mash ? Config::MASH : is_mus ? Config::MUS : Config::CLASSIC; + AshTestHelper::config_ = is_mash ? Config::MASH : Config::CLASSIC; base::DiscardableMemoryAllocator::SetInstance(&discardable_memory_allocator_); - env_ = aura::Env::CreateInstance(is_mus ? aura::Env::Mode::MUS - : aura::Env::Mode::LOCAL); + env_ = aura::Env::CreateInstance(is_mash ? aura::Env::Mode::MUS + : aura::Env::Mode::LOCAL); if (is_mash) { context_factory_ = std::make_unique<aura::test::AuraTestContextFactory>();
diff --git a/ash/window_manager.cc b/ash/window_manager.cc index 4d03d5b..debfda7 100644 --- a/ash/window_manager.cc +++ b/ash/window_manager.cc
@@ -95,6 +95,8 @@ aura::client::kDrawAttentionKey, ui::mojom::WindowManager::kDrawAttention_Property, aura::PropertyConverter::CreateAcceptAnyValueCallback()); + property_converter_->RegisterImageSkiaProperty( + kFrameImageActiveKey, ash::mojom::kFrameImageActive_Property); property_converter_->RegisterPrimitiveProperty( kPanelAttachedKey, ui::mojom::WindowManager::kPanelAttached_Property, aura::PropertyConverter::CreateAcceptAnyValueCallback()); @@ -128,6 +130,10 @@ kRestoreWindowStateTypeOverrideKey, ash::mojom::kRestoreWindowStateTypeOverride_Property, base::BindRepeating(&ash::IsValidWindowStateType)); + property_converter_->RegisterPrimitiveProperty( + kWindowTitleShownKey, + ui::mojom::WindowManager::kWindowTitleShown_Property, + aura::PropertyConverter::CreateAcceptAnyValueCallback()); } WindowManager::~WindowManager() {
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc index 308e183..604faa1a3 100644 --- a/ash/wm/non_client_frame_controller.cc +++ b/ash/wm/non_client_frame_controller.cc
@@ -15,6 +15,7 @@ #include "ash/frame/detached_title_area_renderer.h" #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h" +#include "ash/public/cpp/window_properties.h" #include "ash/window_manager.h" #include "ash/wm/move_event_handler.h" #include "ash/wm/panels/panel_frame_view.h" @@ -401,9 +402,7 @@ } bool NonClientFrameController::ShouldShowWindowTitle() const { - // Only draw the title if the client hasn't declared any additional client - // areas which might conflict with it. - return window_ && additional_client_areas_.empty(); + return window_ && window_->GetProperty(kWindowTitleShownKey); } views::ClientView* NonClientFrameController::CreateClientView(
diff --git a/ash/wm/panels/panel_frame_view.cc b/ash/wm/panels/panel_frame_view.cc index 018d222..fa11e4a60 100644 --- a/ash/wm/panels/panel_frame_view.cc +++ b/ash/wm/panels/panel_frame_view.cc
@@ -40,7 +40,7 @@ SkColor inactive_frame_color) { frame_header_->SetFrameColors(active_frame_color, inactive_frame_color); GetWidgetWindow()->SetProperty(aura::client::kTopViewColor, - frame_header_->GetInactiveFrameColor()); + inactive_frame_color); } const char* PanelFrameView::GetClassName() const { @@ -54,12 +54,12 @@ frame_header_ = std::make_unique<DefaultFrameHeader>( frame_, this, caption_button_container_); GetWidgetWindow()->SetProperty(aura::client::kTopViewColor, - frame_header_->GetInactiveFrameColor()); + DefaultFrameHeader::GetDefaultFrameColor()); if (frame_->widget_delegate()->ShouldShowWindowIcon()) { window_icon_ = new views::ImageView(); AddChildView(window_icon_); - frame_header_->set_left_header_view(window_icon_); + frame_header_->SetLeftHeaderView(window_icon_); } }
diff --git a/ash/wm/panels/panel_layout_manager_unittest.cc b/ash/wm/panels/panel_layout_manager_unittest.cc index 769cf68..8bca5ed 100644 --- a/ash/wm/panels/panel_layout_manager_unittest.cc +++ b/ash/wm/panels/panel_layout_manager_unittest.cc
@@ -17,7 +17,7 @@ #include "ash/shelf/shelf_view_test_api.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/web_notification/web_notification_tray.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/window_state.h" @@ -71,13 +71,13 @@ new ShelfViewTestAPI(GetPrimaryShelf()->GetShelfViewForTesting())); shelf_view_test_->SetAnimationDuration(1); - WebNotificationTray::DisableAnimationsForTest(true); + NotificationTray::DisableAnimationsForTest(true); } void TearDown() override { AshTestBase::TearDown(); - WebNotificationTray::DisableAnimationsForTest(false); // Reenable animation + NotificationTray::DisableAnimationsForTest(false); // Reenable animation } aura::Window* CreateNormalWindow(const gfx::Rect& bounds) {
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc index 21026e3..1207495b 100644 --- a/ash/wm/splitview/split_view_drag_indicators.cc +++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -12,12 +12,12 @@ #include "ash/wm/root_window_finder.h" #include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_controller.h" +#include "ash/wm/splitview/split_view_highlight_view.h" #include "ash/wm/splitview/split_view_utils.h" #include "base/i18n/rtl.h" #include "base/strings/utf_string_conversions.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/display/display_observer.h" #include "ui/views/controls/label.h" @@ -30,14 +30,14 @@ namespace { -// The amount of round applied to the corners of the highlight views. -constexpr int kHighlightScreenRoundRectRadiusDp = 4; - // When animating, this is the location of the split view label as a ratio of // the width or height. constexpr double kSplitviewLabelExpandTranslationPrimaryAxisRatio = 0.20; constexpr double kSplitviewLabelShrinkTranslationPrimaryAxisRatio = 0.05; +// When a preview is shown, the opposite highlight will shrink to this length. +constexpr int kOtherHighlightLengthDp = 20; + // Creates the widget responsible for displaying the indicators. std::unique_ptr<views::Widget> CreateWidget() { auto widget = std::make_unique<views::Widget>(); @@ -185,14 +185,13 @@ // window has entered a snap region to display the bounds of the window, if it // were to get snapped. class SplitViewDragIndicators::SplitViewDragIndicatorsView - : public views::View, - public ui::ImplicitAnimationObserver { + : public views::View { public: SplitViewDragIndicatorsView() { left_highlight_view_ = - new RoundedRectView(kHighlightScreenRoundRectRadiusDp, SK_ColorWHITE); + new SplitViewHighlightView(/*is_right_or_bottom=*/false); right_highlight_view_ = - new RoundedRectView(kHighlightScreenRoundRectRadiusDp, SK_ColorWHITE); + new SplitViewHighlightView(/*is_right_or_bottom=*/true); left_highlight_view_->SetPaintToLayer(); right_highlight_view_->SetPaintToLayer(); @@ -258,16 +257,16 @@ DoSplitviewOpacityAnimation(view->layer(), animation_type); } - for (RoundedRectView* view : GetHighlightViews()) { - view->SetBackgroundColor( - indicator_state == IndicatorState::kCannotSnap ? SK_ColorBLACK - : SK_ColorWHITE); + for (SplitViewHighlightView* view : GetHighlightViews()) { + view->SetColor(indicator_state == IndicatorState::kCannotSnap + ? SK_ColorBLACK + : SK_ColorWHITE); DoSplitviewOpacityAnimation( view->layer(), show ? SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN : SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_OUT); } - Layout(); + Layout(previous_indicator_state_ != IndicatorState::kNone); return; } case IndicatorState::kPreviewAreaLeft: @@ -290,7 +289,7 @@ DoSplitviewOpacityAnimation(right_highlight_view_->layer(), SPLITVIEW_ANIMATION_PREVIEW_AREA_FADE_IN); } - Layout(); + Layout(/*animate=*/true); return; } } @@ -315,7 +314,13 @@ } // views::View: - void Layout() override { + void Layout() override { Layout(/*animate=*/false); } + + private: + // Layout the bounds of the highlight views and helper labels. One should + // animate when changing states, but not when bounds or orientation is + // changed. + void Layout(bool animate) { const bool landscape = Shell::Get() ->split_view_controller() ->IsCurrentScreenOrientationLandscape(); @@ -337,17 +342,17 @@ ? kHighlightScreenEdgePaddingDp : height() - highlight_height - kHighlightScreenEdgePaddingDp); - // Apply a transform to the left and right highlights if one is to expand to - // show a preview area. The expanding window will be transformed by - // |main_transform|. The other highlight, which will shrink and fade out, - // will be transformed by |other_transform|. - gfx::Transform main_transform, other_transform; + gfx::Rect left_highlight_bounds, right_highlight_bounds; + left_highlight_bounds = + gfx::Rect(kHighlightScreenEdgePaddingDp, kHighlightScreenEdgePaddingDp, + highlight_width, highlight_height); + right_highlight_bounds = + gfx::Rect(right_bottom_origin.x(), right_bottom_origin.y(), + highlight_width, highlight_height); + const bool preview_left = - IsPreviewAreaOnLeftTopOfScreen(indicator_state_) || - IsPreviewAreaOnLeftTopOfScreen(previous_indicator_state_); - if (IsPreviewAreaState(indicator_state_) || - (indicator_state_ == IndicatorState::kDragArea && - IsPreviewAreaState(previous_indicator_state_))) { + (indicator_state_ == IndicatorState::kPreviewAreaLeft); + if (IsPreviewAreaState(indicator_state_)) { // Get the preview area bounds from the split view controller. gfx::Rect preview_area_bounds = Shell::Get()->split_view_controller()->GetSnappedWindowBoundsInScreen( @@ -357,91 +362,41 @@ preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp, kHighlightScreenEdgePaddingDp); - // Compute both |main_transform| and |other_transform|. In landscape mode - // use x and width values. In portrait mode use y and height values. + // Calculate the bounds of the other highlight, which is the one that + // shrinks and fades away, while the other one, the preview area, expands + // and takes up half the screen. + gfx::Rect other_bounds; if (landscape) { - if (!preview_left) { - // |main_transform| corresponds to the right window, which changes x - // position as well as scale, so apply a translation. - main_transform.Translate(gfx::Vector2dF( - -(right_bottom_origin.x() - width() + - kHighlightScreenEdgePaddingDp + preview_area_bounds.width()), - 0.f)); - } - // Apply a scale to scale the width to the width of - // |preview_area_bounds|. - main_transform.Scale(static_cast<double>(preview_area_bounds.width()) / - static_cast<double>(highlight_width), - 1.0); - - if (preview_left) { - // |other_transform| corresponds to the right window, which changes x - // position as well as scale, so apply a translation. - other_transform.Translate(gfx::Vector2dF(highlight_width, 0.f)); - } - // Scale the other window so that it becomes hidden. - other_transform.Scale(1.0 / static_cast<double>(highlight_width), 1.0); + other_bounds.set_size( + gfx::Size(kOtherHighlightLengthDp, + height() - 2 * kHighlightScreenEdgePaddingDp)); + other_bounds.set_origin(gfx::Point( + width() - kOtherHighlightLengthDp - kHighlightScreenEdgePaddingDp, + kHighlightScreenEdgePaddingDp)); } else { - if (!preview_left) { - // |main_transform| corresponds to the bottom window, which changes y - // position as well as scale, so apply a translation. - main_transform.Translate(gfx::Vector2dF( - 0.f, - -(right_bottom_origin.y() - height() + - kHighlightScreenEdgePaddingDp + preview_area_bounds.height()))); - } - // Apply a scale to scale the height to the height of - // |preview_area_bounds|. - main_transform.Scale(1.0, - static_cast<double>(preview_area_bounds.height()) / - static_cast<double>(highlight_height)); - - if (preview_left) { - // |other_transform| corresponds to the bottom window, which changes y - // position as well as scale, so apply a translation. - other_transform.Translate(gfx::Vector2dF(0.f, highlight_height)); - } - // Scale the other window so that it becomes hidden. - other_transform.Scale(1.0, 1.0 / static_cast<double>(highlight_height)); + other_bounds.set_size( + gfx::Size(width() - 2 * kHighlightScreenEdgePaddingDp, + kOtherHighlightLengthDp)); + other_bounds.set_origin(gfx::Point(kHighlightScreenEdgePaddingDp, + height() - kOtherHighlightLengthDp - + kHighlightScreenEdgePaddingDp)); } - if (IsPreviewAreaState(previous_indicator_state_)) { - // If the previous state was a preview state, first apply a transform, - // otherwise no animation will happen if we try to transform from - // identity to identity. (OnImplicitAnimationsCompleted sets the bounds - // and all transforms to identity to preserve rounded edges). - left_highlight_view_->layer()->SetTransform( - preview_left ? main_transform : other_transform); - right_highlight_view_->layer()->SetTransform( - preview_left ? other_transform : main_transform); - main_transform.MakeIdentity(); - other_transform.MakeIdentity(); + if (IsPreviewAreaOnLeftTopOfScreen(indicator_state_)) { + left_highlight_bounds = preview_area_bounds; + right_highlight_bounds = other_bounds; + } else { + other_bounds.set_origin(gfx::Point(kHighlightScreenEdgePaddingDp, + kHighlightScreenEdgePaddingDp)); + left_highlight_bounds = other_bounds; + right_highlight_bounds = preview_area_bounds; } } - left_highlight_bounds_ = - gfx::Rect(kHighlightScreenEdgePaddingDp, kHighlightScreenEdgePaddingDp, - highlight_width, highlight_height); - right_highlight_bounds_ = - gfx::Rect(right_bottom_origin.x(), right_bottom_origin.y(), - highlight_width, highlight_height); - if (base::i18n::IsRTL() && landscape) { - gfx::Rect temp = left_highlight_bounds_; - left_highlight_bounds_ = right_highlight_bounds_; - right_highlight_bounds_ = temp; - } - - DoSplitviewTransformAnimation( - left_highlight_view_->layer(), - SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT, - preview_left ? main_transform : other_transform, this); - left_highlight_view_->SetBoundsRect(left_highlight_bounds_); - - DoSplitviewTransformAnimation( - right_highlight_view_->layer(), - SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT, - preview_left ? other_transform : main_transform, nullptr); - right_highlight_view_->SetBoundsRect(right_highlight_bounds_); + left_highlight_view_->SetBounds(GetMirroredRect(left_highlight_bounds), + landscape, animate); + right_highlight_view_->SetBounds(GetMirroredRect(right_highlight_bounds), + landscape, animate); // Calculate the bounds of the views which contain the guidance text and // icon. Rotate the two views in landscape mode. @@ -493,57 +448,18 @@ nullptr); } - // ui::ImplicitAnimationObserver: - void OnImplicitAnimationsCompleted() override { - // Set the final bounds and the layer transforms to identity, so that the - // proper rounding on the rounded rect corners show up. - const bool flip = - base::i18n::IsRTL() && Shell::Get() - ->split_view_controller() - ->IsCurrentScreenOrientationLandscape(); - const bool left = - (indicator_state_ == IndicatorState::kPreviewAreaLeft && !flip) || - (indicator_state_ == IndicatorState::kPreviewAreaRight && flip); - gfx::Rect preview_area_bounds = - Shell::Get()->split_view_controller()->GetSnappedWindowBoundsInScreen( - GetWidget()->GetNativeWindow(), - left ? SplitViewController::LEFT : SplitViewController::RIGHT); - preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp, - kHighlightScreenEdgePaddingDp); - - constexpr gfx::Rect kEmptyRect; - left_highlight_view_->layer()->SetTransform(gfx::Transform()); - right_highlight_view_->layer()->SetTransform(gfx::Transform()); - if (IsPreviewAreaOnLeftTopOfScreen(indicator_state_)) { - left_highlight_view_->SetBoundsRect(preview_area_bounds); - right_highlight_view_->SetBoundsRect(kEmptyRect); - } else if (IsPreviewAreaState(indicator_state_)) { - left_highlight_view_->SetBoundsRect(kEmptyRect); - right_highlight_view_->SetBoundsRect(preview_area_bounds); - } else { - left_highlight_view_->SetBoundsRect(left_highlight_bounds_); - right_highlight_view_->SetBoundsRect(right_highlight_bounds_); - } - } - - private: - std::vector<RoundedRectView*> GetHighlightViews() { + std::vector<SplitViewHighlightView*> GetHighlightViews() { return {left_highlight_view_, right_highlight_view_}; } std::vector<RotatedImageLabelView*> GetTextViews() { return {left_rotated_view_, right_rotated_view_}; } - RoundedRectView* left_highlight_view_ = nullptr; - RoundedRectView* right_highlight_view_ = nullptr; + SplitViewHighlightView* left_highlight_view_ = nullptr; + SplitViewHighlightView* right_highlight_view_ = nullptr; RotatedImageLabelView* left_rotated_view_ = nullptr; RotatedImageLabelView* right_rotated_view_ = nullptr; - // Cache the bounds calculated in Layout(), so that they do not have to be - // recalculated when animation is finished. - gfx::Rect left_highlight_bounds_; - gfx::Rect right_highlight_bounds_; - IndicatorState indicator_state_ = IndicatorState::kNone; IndicatorState previous_indicator_state_ = IndicatorState::kNone;
diff --git a/ash/wm/splitview/split_view_highlight_view.cc b/ash/wm/splitview/split_view_highlight_view.cc new file mode 100644 index 0000000..f5cb8ca --- /dev/null +++ b/ash/wm/splitview/split_view_highlight_view.cc
@@ -0,0 +1,174 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/splitview/split_view_highlight_view.h" + +#include "ash/wm/overview/rounded_rect_view.h" +#include "ash/wm/splitview/split_view_utils.h" +#include "ui/gfx/canvas.h" +#include "ui/views/view.h" + +namespace ash { + +namespace { + +// The amount of round applied to the corners of the highlight views. +constexpr int kHighlightScreenRoundRectRadiusDp = 4; + +constexpr int kRoundRectPaddingDp = 10; + +gfx::Transform CalculateTransformFromRects(const gfx::Rect& src, + const gfx::Rect& dst, + bool landscape) { + // In portrait, rtl will have no effect on this view. + const bool is_rtl = base::i18n::IsRTL() && landscape; + const bool should_scale = + src.width() != dst.width() || src.height() != dst.height(); + + // Add a translatation. In rtl, translate in the opposite direction to account + // for the flip. + gfx::Transform transform; + transform.Translate(is_rtl && !should_scale ? src.origin() - dst.origin() + : dst.origin() - src.origin()); + if (should_scale) { + // In rtl a extra translation needs to be added to account for the flipped + // scaling. + if (is_rtl) { + int x_translation = 0; + if ((src.x() > dst.x() && src.width() < dst.width()) || + (src.x() == dst.x() && src.width() > dst.width())) { + x_translation = std::abs(dst.width() - src.width()); + } else { + x_translation = -std::abs(dst.width() - src.width()); + } + transform.Translate(gfx::Vector2d(x_translation, 0)); + } + transform.Scale( + static_cast<float>(dst.width()) / static_cast<float>(src.width()), + static_cast<float>(dst.height()) / static_cast<float>(src.height())); + } + return transform; +} + +} // namespace + +SplitViewHighlightView::SplitViewHighlightView(bool is_right_or_bottom) + : is_right_or_bottom_(is_right_or_bottom) { + left_top_ = + new RoundedRectView(kHighlightScreenRoundRectRadiusDp, SK_ColorWHITE); + right_bottom_ = + new RoundedRectView(kHighlightScreenRoundRectRadiusDp, SK_ColorWHITE); + + left_top_->SetPaintToLayer(); + left_top_->layer()->SetFillsBoundsOpaquely(false); + right_bottom_->SetPaintToLayer(); + right_bottom_->layer()->SetFillsBoundsOpaquely(false); + + middle_ = new views::View(); + middle_->SetPaintToLayer(ui::LAYER_SOLID_COLOR); + middle_->layer()->SetColor(SK_ColorWHITE); + + AddChildView(left_top_); + AddChildView(right_bottom_); + AddChildView(middle_); +} + +SplitViewHighlightView::~SplitViewHighlightView() = default; + +void SplitViewHighlightView::SetBounds(const gfx::Rect& bounds, + bool landscape, + bool animate) { + if (bounds == this->bounds() && landscape == landscape_) + return; + + landscape_ = landscape; + + const gfx::Rect old_bounds = this->bounds(); + const gfx::Vector2d offset = old_bounds.origin() - bounds.origin(); + SetBoundsRect(bounds); + // Shift the bounds of the right bottom view if needed before applying the + // transform. + const bool slides_from_right = base::i18n::IsRTL() && landscape + ? !is_right_or_bottom_ + : is_right_or_bottom_; + if (slides_from_right && animate && !offset.IsZero()) { + gfx::Rect old_left_top_bounds = left_top_->bounds(); + gfx::Rect old_right_middle_bounds = right_bottom_->bounds(); + gfx::Rect old_middle_bounds = middle_->bounds(); + + old_left_top_bounds.Offset(offset); + old_right_middle_bounds.Offset(offset); + old_middle_bounds.Offset(offset); + + left_top_->SetBoundsRect(old_left_top_bounds); + right_bottom_->SetBoundsRect(old_right_middle_bounds); + middle_->SetBoundsRect(old_middle_bounds); + } + + // Calculate the new bounds. The middle should take as much space as possible, + // and the other two should take just enough space so they can display rounded + // corners. + gfx::Rect left_top_bounds, right_bottom_bounds; + gfx::Rect middle_bounds = bounds; + + // The thickness of the two outer views should be the amount of rounding, plus + // a little padding. There will be some overlap to simply the code (we use a + // rectangle that is rounded on all sides, but cover half the sides instead of + // creating a new class that is only rounded on half the sides). + const int thickness = kHighlightScreenRoundRectRadiusDp + kRoundRectPaddingDp; + if (landscape) { + left_top_bounds = gfx::Rect(0, 0, thickness, bounds.height()); + right_bottom_bounds = left_top_bounds; + right_bottom_bounds.Offset(bounds.width() - thickness, 0); + middle_bounds.Offset(-bounds.x(), -bounds.y()); + middle_bounds.Inset(kHighlightScreenRoundRectRadiusDp, 0); + } else { + left_top_bounds = gfx::Rect(0, 0, bounds.width(), thickness); + right_bottom_bounds = left_top_bounds; + right_bottom_bounds.Offset(0, bounds.height() - thickness); + middle_bounds.Offset(-bounds.x(), -bounds.y()); + middle_bounds.Inset(0, kHighlightScreenRoundRectRadiusDp); + } + + left_top_bounds = GetMirroredRect(left_top_bounds); + right_bottom_bounds = GetMirroredRect(right_bottom_bounds); + middle_bounds = GetMirroredRect(middle_bounds); + + // If |animate|, calculate the needed transform from old bounds to new bounds + // and apply it. Otherwise set the new bounds and reset the transforms on all + // items. + if (animate) { + DoSplitviewTransformAnimation( + middle_->layer(), SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT, + CalculateTransformFromRects(middle_->bounds(), middle_bounds, + landscape), + nullptr); + DoSplitviewTransformAnimation( + left_top_->layer(), SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT, + CalculateTransformFromRects(left_top_->bounds(), left_top_bounds, + landscape), + nullptr); + DoSplitviewTransformAnimation( + right_bottom_->layer(), SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT, + CalculateTransformFromRects(right_bottom_->bounds(), + right_bottom_bounds, landscape), + nullptr); + } else { + left_top_->layer()->SetTransform(gfx::Transform()); + right_bottom_->layer()->SetTransform(gfx::Transform()); + middle_->layer()->SetTransform(gfx::Transform()); + + left_top_->SetBoundsRect(left_top_bounds); + right_bottom_->SetBoundsRect(right_bottom_bounds); + middle_->SetBoundsRect(middle_bounds); + } +} + +void SplitViewHighlightView::SetColor(SkColor color) { + left_top_->SetBackgroundColor(color); + right_bottom_->SetBackgroundColor(color); + middle_->layer()->SetColor(color); +} + +} // namespace ash \ No newline at end of file
diff --git a/ash/wm/splitview/split_view_highlight_view.h b/ash/wm/splitview/split_view_highlight_view.h new file mode 100644 index 0000000..ea2dd55 --- /dev/null +++ b/ash/wm/splitview/split_view_highlight_view.h
@@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_SPLITVIEW_SPLIT_VIEW_HIGHLIGHT_VIEW_H_ +#define ASH_WM_SPLITVIEW_SPLIT_VIEW_HIGHLIGHT_VIEW_H_ + +#include "ash/ash_export.h" +#include "ui/views/view.h" + +namespace ash { + +class RoundedRectView; +class SplitViewHighlightViewTestApi; + +// View that is used for displaying and animating the highlights which tell +// users where to drag windows to enter splitview, and previews the space which +// a snapped window will occupy. It is a view consisting of a rectangle with +// rounded corners on the left or top, a rectangle in the middle and a rectangle +// with rounded corners on the right or bottom. It is done this way to ensure +// rounded corners remain the same during the duration of an animation. +// (Transforming a rounded rect will stretch the corners, and having to repaint +// every animation tick is expensive.) +class ASH_EXPORT SplitViewHighlightView : public views::View { + public: + explicit SplitViewHighlightView(bool is_right_or_bottom); + ~SplitViewHighlightView() override; + + void SetBounds(const gfx::Rect& bounds, bool landscape, bool animate); + + void SetColor(SkColor color); + + private: + friend class SplitViewHighlightViewTestApi; + + // The three components of this view. + RoundedRectView* left_top_ = nullptr; + RoundedRectView* right_bottom_ = nullptr; + views::View* middle_ = nullptr; + + bool landscape_ = true; + // Determines whether this particular highlight view is located at the right + // or bottom of the screen. These highlights animate in the opposite direction + // as left or top highlights, so when we use SetBounds extra calucations have + // to be done to ensure the animation is correct. + const bool is_right_or_bottom_; + + DISALLOW_COPY_AND_ASSIGN(SplitViewHighlightView); +}; + +} // namespace ash + +#endif // ASH_WM_SPLITVIEW_SPLIT_VIEW_HIGHLIGHT_VIEW_H_ \ No newline at end of file
diff --git a/ash/wm/splitview/split_view_highlight_view_test_api.cc b/ash/wm/splitview/split_view_highlight_view_test_api.cc new file mode 100644 index 0000000..e3cc60e0 --- /dev/null +++ b/ash/wm/splitview/split_view_highlight_view_test_api.cc
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/splitview/split_view_highlight_view_test_api.h" + +#include "ash/wm/overview/rounded_rect_view.h" +#include "ui/views/view.h" + +namespace ash { + +SplitViewHighlightViewTestApi::SplitViewHighlightViewTestApi( + SplitViewHighlightView* highlight_view) + : highlight_view_(highlight_view) {} + +SplitViewHighlightViewTestApi::~SplitViewHighlightViewTestApi() = default; + +views::View* SplitViewHighlightViewTestApi::GetLeftTopView() { + return static_cast<views::View*>(highlight_view_->left_top_); +} + +views::View* SplitViewHighlightViewTestApi::GetRightBottomView() { + return static_cast<views::View*>(highlight_view_->right_bottom_); +} + +views::View* SplitViewHighlightViewTestApi::GetMiddleView() { + return highlight_view_->middle_; +} + +} // namespace ash
diff --git a/ash/wm/splitview/split_view_highlight_view_test_api.h b/ash/wm/splitview/split_view_highlight_view_test_api.h new file mode 100644 index 0000000..2c3e09c --- /dev/null +++ b/ash/wm/splitview/split_view_highlight_view_test_api.h
@@ -0,0 +1,36 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_SPLITVIEW_SPLIT_VIEW_HIGHLIGHT_VIEW_TEST_API_H_ +#define ASH_WM_SPLITVIEW_SPLIT_VIEW_HIGHLIGHT_VIEW_TEST_API_H_ + +#include "ash/wm/splitview/split_view_highlight_view.h" +#include "base/macros.h" + +namespace views { +class View; +} // namespace views + +namespace ash { + +// Use the api in this class to test SplitViewHighlightView. +class SplitViewHighlightViewTestApi { + public: + explicit SplitViewHighlightViewTestApi( + SplitViewHighlightView* highlight_view); + ~SplitViewHighlightViewTestApi(); + + views::View* GetLeftTopView(); + views::View* GetRightBottomView(); + views::View* GetMiddleView(); + + private: + SplitViewHighlightView* highlight_view_; + + DISALLOW_COPY_AND_ASSIGN(SplitViewHighlightViewTestApi); +}; + +} // namespace ash + +#endif // ASH_WM_SPLITVIEW_SPLIT_VIEW_HIGHLIGHT_VIEW_TEST_API_H_ \ No newline at end of file
diff --git a/ash/wm/splitview/split_view_highlight_view_unittest.cc b/ash/wm/splitview/split_view_highlight_view_unittest.cc new file mode 100644 index 0000000..6a44b17 --- /dev/null +++ b/ash/wm/splitview/split_view_highlight_view_unittest.cc
@@ -0,0 +1,199 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/splitview/split_view_highlight_view.h" + +#include "ash/test/ash_test_base.h" +#include "ash/wm/splitview/split_view_highlight_view_test_api.h" +#include "base/test/icu_test_util.h" +#include "ui/gfx/transform.h" + +namespace ash { + +namespace { + +gfx::Transform GetTransform(views::View* view) { + DCHECK(view && view->layer()); + return view->layer()->transform(); +} + +} // namespace + +class SplitViewHighlightViewTest : public AshTestBase { + public: + SplitViewHighlightViewTest() = default; + ~SplitViewHighlightViewTest() override = default; + + SplitViewHighlightView* left_highlight() { return left_highlight_.get(); } + SplitViewHighlightView* right_highlight() { return right_highlight_.get(); } + + // test::AshTestBase: + void SetUp() override { + AshTestBase::SetUp(); + + left_highlight_ = std::make_unique<SplitViewHighlightView>(false); + right_highlight_ = std::make_unique<SplitViewHighlightView>(true); + } + + private: + std::unique_ptr<SplitViewHighlightView> left_highlight_; + std::unique_ptr<SplitViewHighlightView> right_highlight_; + + DISALLOW_COPY_AND_ASSIGN(SplitViewHighlightViewTest); +}; + +// Tests setting and animating bounds for the split view highlight view in +// landscape mode. +TEST_F(SplitViewHighlightViewTest, LandscapeBounds) { + const gfx::Rect bounds(0, 0, 100, 100); + left_highlight()->SetBounds(bounds, /*landscape=*/true, /*animate=*/false); + + // Tests that setting bounds without animations in landscape mode will set the + // bounds of the components correctly, without any transforms. + SplitViewHighlightViewTestApi test_api(left_highlight()); + EXPECT_EQ(gfx::Rect(0, 0, 14, 100), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(4, 0, 92, 100), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(86, 0, 14, 100), test_api.GetRightBottomView()->bounds()); + EXPECT_TRUE(GetTransform(test_api.GetLeftTopView()).IsIdentity()); + EXPECT_TRUE(GetTransform(test_api.GetMiddleView()).IsIdentity()); + EXPECT_TRUE(GetTransform(test_api.GetRightBottomView()).IsIdentity()); + + // Tests that after animating to new bounds, the components have the same + // bounds, but have transforms. + const gfx::Rect new_bounds(0, 0, 200, 100); + left_highlight()->SetBounds(new_bounds, /*landscape=*/true, /*animate=*/true); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(gfx::Rect(0, 0, 14, 100), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(4, 0, 92, 100), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(86, 0, 14, 100), test_api.GetRightBottomView()->bounds()); + EXPECT_TRUE(GetTransform(test_api.GetLeftTopView()).IsIdentity()); + gfx::Transform expected_middle_transform; + expected_middle_transform.Scale(2.16, 1); + EXPECT_TRUE(GetTransform(test_api.GetMiddleView()) + .ApproximatelyEqual(expected_middle_transform)); + gfx::Transform expected_end_transform; + expected_end_transform.Translate(100, 0); + EXPECT_TRUE(GetTransform(test_api.GetRightBottomView()) + .ApproximatelyEqual(expected_end_transform)); +} + +// Tests setting and animating bounds for the split view highlight view in +// landscape mode for rtl languages. +TEST_F(SplitViewHighlightViewTest, LandscapeBoundsInRtl) { + base::test::ScopedRestoreICUDefaultLocale scoped_locale("he"); + + const gfx::Rect bounds(0, 0, 100, 100); + left_highlight()->SetBounds(bounds, /*landscape=*/true, /*animate=*/false); + + // Tests that setting bounds without animations in landscape mode will set the + // bounds of the components correctly, without any transforms. In rtl, the + // bounds of the outer components are swapped. + SplitViewHighlightViewTestApi test_api(left_highlight()); + EXPECT_EQ(gfx::Rect(86, 0, 14, 100), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(4, 0, 92, 100), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(0, 0, 14, 100), test_api.GetRightBottomView()->bounds()); + EXPECT_TRUE(GetTransform(test_api.GetLeftTopView()).IsIdentity()); + EXPECT_TRUE(GetTransform(test_api.GetMiddleView()).IsIdentity()); + EXPECT_TRUE(GetTransform(test_api.GetRightBottomView()).IsIdentity()); + + // Tests that after animating to new bounds, the components have the same + // bounds, but have transforms. In rtl the beginning element is the one that + // is translated instead. The middle element has a extra translation in its + // transform to account for the flipped scaling. + const gfx::Rect new_bounds(0, 0, 200, 100); + left_highlight()->SetBounds(new_bounds, /*landscape=*/true, /*animate=*/true); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(gfx::Rect(86, 0, 14, 100), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(4, 0, 92, 100), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(0, 0, 14, 100), test_api.GetRightBottomView()->bounds()); + gfx::Transform expected_begin_transform; + expected_begin_transform.Translate(-100, 0); + EXPECT_TRUE(GetTransform(test_api.GetLeftTopView()) + .ApproximatelyEqual(expected_begin_transform)); + gfx::Transform expected_middle_transform; + expected_middle_transform.Translate(-100, 0); + expected_middle_transform.Scale(2.16, 1); + EXPECT_TRUE(GetTransform(test_api.GetMiddleView()) + .ApproximatelyEqual(expected_middle_transform)); + EXPECT_TRUE(GetTransform(test_api.GetRightBottomView()).IsIdentity()); +} + +class SplitViewHighlightViewPortraitTest + : public SplitViewHighlightViewTest, + public testing::WithParamInterface<bool> { + public: + SplitViewHighlightViewPortraitTest() + : scoped_locale_(GetParam() ? "he" : "") {} + ~SplitViewHighlightViewPortraitTest() override = default; + + private: + // Restores locale to the default when destructor is called. + base::test::ScopedRestoreICUDefaultLocale scoped_locale_; + + DISALLOW_COPY_AND_ASSIGN(SplitViewHighlightViewPortraitTest); +}; + +// Tests setting and animating bounds for the split view highlight view in +// portrait mode. The bounds should remain the same in ltr or rtl. +TEST_P(SplitViewHighlightViewPortraitTest, Bounds) { + const gfx::Rect bounds(0, 0, 100, 100); + left_highlight()->SetBounds(bounds, /*landscape=*/false, /*animate=*/false); + + SplitViewHighlightViewTestApi test_api(left_highlight()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 14), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(0, 4, 100, 92), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(0, 86, 100, 14), test_api.GetRightBottomView()->bounds()); + + const gfx::Rect new_bounds(0, 0, 100, 200); + left_highlight()->SetBounds(new_bounds, /*landscape=*/false, + /*animate=*/true); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(gfx::Rect(0, 0, 100, 14), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(0, 4, 100, 92), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(0, 86, 100, 14), test_api.GetRightBottomView()->bounds()); + EXPECT_TRUE(GetTransform(test_api.GetLeftTopView()).IsIdentity()); + gfx::Transform expected_middle_transform; + expected_middle_transform.Scale(1, 2.16); + EXPECT_TRUE(GetTransform(test_api.GetMiddleView()) + .ApproximatelyEqual(expected_middle_transform)); + gfx::Transform expected_end_transform; + expected_end_transform.Translate(0, 100); + EXPECT_TRUE(GetTransform(test_api.GetRightBottomView()) + .ApproximatelyEqual(expected_end_transform)); +} + +INSTANTIATE_TEST_CASE_P(Bounds, + SplitViewHighlightViewPortraitTest, + testing::Bool()); + +TEST_F(SplitViewHighlightViewTest, RightBounds) { + const gfx::Rect bounds(100, 0, 100, 100); + right_highlight()->SetBounds(bounds, /*landscape=*/true, /*animate=*/false); + + SplitViewHighlightViewTestApi test_api(right_highlight()); + EXPECT_EQ(gfx::Rect(0, 0, 14, 100), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(4, 0, 92, 100), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(86, 0, 14, 100), test_api.GetRightBottomView()->bounds()); + + const gfx::Rect new_bounds(0, 0, 200, 100); + right_highlight()->SetBounds(new_bounds, /*landscape=*/true, + /*animate=*/true); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(gfx::Rect(100, 0, 14, 100), test_api.GetLeftTopView()->bounds()); + EXPECT_EQ(gfx::Rect(104, 0, 92, 100), test_api.GetMiddleView()->bounds()); + EXPECT_EQ(gfx::Rect(186, 0, 14, 100), + test_api.GetRightBottomView()->bounds()); + gfx::Transform expected_begin_transform; + expected_begin_transform.Translate(-100, 0); + EXPECT_TRUE(GetTransform(test_api.GetLeftTopView()) + .ApproximatelyEqual(expected_begin_transform)); + gfx::Transform expected_middle_transform; + expected_middle_transform.Translate(-100, 0); + expected_middle_transform.Scale(2.16, 1); + EXPECT_TRUE(GetTransform(test_api.GetMiddleView()) + .ApproximatelyEqual(expected_middle_transform)); + EXPECT_TRUE(GetTransform(test_api.GetRightBottomView()).IsIdentity()); +} + +} // namespace ash \ No newline at end of file
diff --git a/base/BUILD.gn b/base/BUILD.gn index 5f04e581..ee3ed563 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2120,6 +2120,7 @@ sources = [ "fuchsia/test.fidl", ] + namespace = "base" } }
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc index 93e51df7..8554673 100644 --- a/base/allocator/partition_allocator/partition_alloc.cc +++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -257,38 +257,46 @@ return true; } -void* PartitionRootGeneric::Realloc(void* ptr, - size_t new_size, - const char* type_name) { +void* PartitionReallocGenericFlags(PartitionRootGeneric* root, + int flags, + void* ptr, + size_t new_size, + const char* type_name) { #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) - return realloc(ptr, new_size); + void* result = realloc(ptr, new_size); + CHECK(result || flags & PartitionAllocReturnNull); + return result; #else if (UNLIKELY(!ptr)) - return this->Alloc(new_size, type_name); + return PartitionAllocGenericFlags(root, flags, new_size, type_name); if (UNLIKELY(!new_size)) { - this->Free(ptr); + root->Free(ptr); return nullptr; } - if (new_size > kGenericMaxDirectMapped) - internal::PartitionExcessiveAllocationSize(); + if (new_size > kGenericMaxDirectMapped) { + if (flags & PartitionAllocReturnNull) + return nullptr; + else + internal::PartitionExcessiveAllocationSize(); + } internal::PartitionPage* page = internal::PartitionPage::FromPointer( internal::PartitionCookieFreePointerAdjust(ptr)); // TODO(palmer): See if we can afford to make this a CHECK. - DCHECK(IsValidPage(page)); + DCHECK(root->IsValidPage(page)); if (UNLIKELY(page->bucket->is_direct_mapped())) { // We may be able to perform the realloc in place by changing the // accessibility of memory pages and, if reducing the size, decommitting // them. - if (PartitionReallocDirectMappedInPlace(this, page, new_size)) { + if (PartitionReallocDirectMappedInPlace(root, page, new_size)) { PartitionAllocHooks::ReallocHookIfEnabled(ptr, ptr, new_size, type_name); return ptr; } } - size_t actual_new_size = this->ActualSize(new_size); + size_t actual_new_size = root->ActualSize(new_size); size_t actual_old_size = PartitionAllocGetSize(ptr); // TODO: note that tcmalloc will "ignore" a downsizing realloc() unless the @@ -309,17 +317,30 @@ } // This realloc cannot be resized in-place. Sadness. - void* ret = this->Alloc(new_size, type_name); + void* ret = PartitionAllocGenericFlags(root, flags, new_size, type_name); + if (!ret) { + if (flags & PartitionAllocReturnNull) + return nullptr; + else + internal::PartitionExcessiveAllocationSize(); + } + size_t copy_size = actual_old_size; if (new_size < copy_size) copy_size = new_size; memcpy(ret, ptr, copy_size); - this->Free(ptr); + root->Free(ptr); return ret; #endif } +void* PartitionRootGeneric::Realloc(void* ptr, + size_t new_size, + const char* type_name) { + return PartitionReallocGenericFlags(this, 0, ptr, new_size, type_name); +} + static size_t PartitionPurgePage(internal::PartitionPage* page, bool discard) { const internal::PartitionBucket* bucket = page->bucket; size_t slot_size = bucket->slot_size;
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h index 59b1c2d..79d09053 100644 --- a/base/allocator/partition_allocator/partition_alloc.h +++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -359,6 +359,12 @@ #endif } +BASE_EXPORT void* PartitionReallocGenericFlags(PartitionRootGeneric* root, + int flags, + void* ptr, + size_t new_size, + const char* type_name); + ALWAYS_INLINE size_t PartitionRootGeneric::ActualSize(size_t size) { #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) return size;
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index f8081fc4..4bf6b26d 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -182,7 +182,7 @@ } } - void DoReturnNullTest(size_t allocSize) { + void DoReturnNullTest(size_t allocSize, bool use_realloc) { // TODO(crbug.com/678782): Where necessary and possible, disable the // platform's OOM-killing behavior. OOM-killing makes this test flaky on // low-memory devices. @@ -202,9 +202,17 @@ int i; for (i = 0; i < numAllocations; ++i) { - ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(), - PartitionAllocReturnNull, allocSize, - type_name); + if (use_realloc) { + ptrs[i] = PartitionAllocGenericFlags( + generic_allocator.root(), PartitionAllocReturnNull, 1, type_name); + ptrs[i] = PartitionReallocGenericFlags(generic_allocator.root(), + PartitionAllocReturnNull, + ptrs[i], allocSize, type_name); + } else { + ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(), + PartitionAllocReturnNull, + allocSize, type_name); + } if (!i) EXPECT_TRUE(ptrs[0]); if (!ptrs[i]) { @@ -1302,14 +1310,26 @@ // sufficient unreserved virtual memory around for the later one(s). TEST_F(PartitionAllocReturnNullTest, RepeatedReturnNullDirect) { // A direct-mapped allocation size. - DoReturnNullTest(32 * 1024 * 1024); + DoReturnNullTest(32 * 1024 * 1024, false); } // Test "return null" with a 512 kB block size. TEST_F(PartitionAllocReturnNullTest, RepeatedReturnNull) { // A single-slot but non-direct-mapped allocation size. - DoReturnNullTest(512 * 1024); + DoReturnNullTest(512 * 1024, false); } + +// Repeating the above tests using Realloc instead of Alloc. +class PartitionReallocReturnNullTest : public PartitionAllocTest {}; + +TEST_F(PartitionReallocReturnNullTest, RepeatedReturnNullDirect) { + DoReturnNullTest(32 * 1024 * 1024, true); +} + +TEST_F(PartitionReallocReturnNullTest, RepeatedReturnNull) { + DoReturnNullTest(512 * 1024, true); +} + #endif // !defined(ARCH_CPU_64_BITS) || (defined(OS_POSIX) && // !(defined(OS_FUCHSIA) || defined(OS_MACOSX) || defined(OS_ANDROID)))
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc index 6b268cdb..794584c 100644 --- a/base/files/file_util_win.cc +++ b/base/files/file_util_win.cc
@@ -23,10 +23,11 @@ #include "base/guid.h" #include "base/logging.h" #include "base/macros.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_functions.h" #include "base/process/process_handle.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" @@ -41,35 +42,104 @@ const DWORD kFileShareAll = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; +// Records a sample in a histogram named +// "Windows.PostOperationState.|operation|" indicating the state of |path| +// following the named operation. If |operation_succeeded| is true, the +// "operation succeeded" sample is recorded. Otherwise, the state of |path| is +// queried and the most meaningful sample is recorded. +void RecordPostOperationState(const FilePath& path, + StringPiece operation, + bool operation_succeeded) { + // The state of a filesystem item after an operation. + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class PostOperationState { + kOperationSucceeded = 0, + kFileNotFoundAfterFailure = 1, + kPathNotFoundAfterFailure = 2, + kAccessDeniedAfterFailure = 3, + kNoAttributesAfterFailure = 4, + kEmptyDirectoryAfterFailure = 5, + kNonEmptyDirectoryAfterFailure = 6, + kNotDirectoryAfterFailure = 7, + kCount + } metric = PostOperationState::kOperationSucceeded; + + if (!operation_succeeded) { + const DWORD attributes = ::GetFileAttributes(path.value().c_str()); + if (attributes == INVALID_FILE_ATTRIBUTES) { + // On failure to delete, one might expect the file/directory to still be + // in place. Slice a failure to get its attributes into a few common error + // buckets. + const DWORD error_code = ::GetLastError(); + if (error_code == ERROR_FILE_NOT_FOUND) + metric = PostOperationState::kFileNotFoundAfterFailure; + else if (error_code == ERROR_PATH_NOT_FOUND) + metric = PostOperationState::kPathNotFoundAfterFailure; + else if (error_code == ERROR_ACCESS_DENIED) + metric = PostOperationState::kAccessDeniedAfterFailure; + else + metric = PostOperationState::kNoAttributesAfterFailure; + } else if (attributes & FILE_ATTRIBUTE_DIRECTORY) { + if (IsDirectoryEmpty(path)) + metric = PostOperationState::kEmptyDirectoryAfterFailure; + else + metric = PostOperationState::kNonEmptyDirectoryAfterFailure; + } else { + metric = PostOperationState::kNotDirectoryAfterFailure; + } + } + + std::string histogram_name = "Windows.PostOperationState."; + operation.AppendToString(&histogram_name); + UmaHistogramEnumeration(histogram_name, metric, PostOperationState::kCount); +} + +// Records the sample |error| in a histogram named +// "Windows.FilesystemError.|operation|". +void RecordFilesystemError(StringPiece operation, DWORD error) { + std::string histogram_name = "Windows.FilesystemError."; + operation.AppendToString(&histogram_name); + UmaHistogramSparse(histogram_name, error); +} + // Deletes all files and directories in a path. -// Returns false on the first failure it encounters. -bool DeleteFileRecursive(const FilePath& path, - const FilePath::StringType& pattern, - bool recursive) { +// Returns ERROR_SUCCESS on success or the Windows error code corresponding to +// the first error encountered. +DWORD DeleteFileRecursive(const FilePath& path, + const FilePath::StringType& pattern, + bool recursive) { FileEnumerator traversal(path, false, FileEnumerator::FILES | FileEnumerator::DIRECTORIES, pattern); - bool success = true; + DWORD result = ERROR_SUCCESS; for (FilePath current = traversal.Next(); !current.empty(); current = traversal.Next()) { // Try to clear the read-only bit if we find it. FileEnumerator::FileInfo info = traversal.GetInfo(); if ((info.find_data().dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (recursive || !info.IsDirectory())) { - SetFileAttributes( + ::SetFileAttributes( current.value().c_str(), info.find_data().dwFileAttributes & ~FILE_ATTRIBUTE_READONLY); } + DWORD this_result = ERROR_SUCCESS; if (info.IsDirectory()) { - if (recursive && (!DeleteFileRecursive(current, pattern, true) || - !RemoveDirectory(current.value().c_str()))) - success = false; + if (recursive) { + this_result = DeleteFileRecursive(current, pattern, true); + if (this_result == ERROR_SUCCESS && + !::RemoveDirectory(current.value().c_str())) { + this_result = ::GetLastError(); + } + } } else if (!::DeleteFile(current.value().c_str())) { - success = false; + this_result = ::GetLastError(); } + if (result == ERROR_SUCCESS) + result = this_result; } - return success; + return result; } // Appends |mode_char| to |mode| before the optional character set encoding; see @@ -203,6 +273,55 @@ return success; } +// Returns ERROR_SUCCESS on success, or a Windows error code on failure. +DWORD DoDeleteFile(const FilePath& path, bool recursive) { + AssertBlockingAllowed(); + + if (path.empty()) + return ERROR_SUCCESS; + + if (path.value().length() >= MAX_PATH) + return ERROR_BAD_PATHNAME; + + // Handle any path with wildcards. + if (path.BaseName().value().find_first_of(L"*?") != + FilePath::StringType::npos) { + return DeleteFileRecursive(path.DirName(), path.BaseName().value(), + recursive); + } + + // Report success if the file or path does not exist. + const DWORD attr = ::GetFileAttributes(path.value().c_str()); + if (attr == INVALID_FILE_ATTRIBUTES) { + const DWORD error_code = ::GetLastError(); + return (error_code == ERROR_FILE_NOT_FOUND || + error_code == ERROR_PATH_NOT_FOUND) + ? ERROR_SUCCESS + : error_code; + } + + // Clear the read-only bit if it is set. + if ((attr & FILE_ATTRIBUTE_READONLY) && + !::SetFileAttributes(path.value().c_str(), + attr & ~FILE_ATTRIBUTE_READONLY)) { + return ::GetLastError(); + } + + // Perform a simple delete on anything that isn't a directory. + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { + return ::DeleteFile(path.value().c_str()) ? ERROR_SUCCESS + : ::GetLastError(); + } + + if (recursive) { + const DWORD error_code = DeleteFileRecursive(path, L"*", true); + if (error_code != ERROR_SUCCESS) + return error_code; + } + return ::RemoveDirectory(path.value().c_str()) ? ERROR_SUCCESS + : ::GetLastError(); +} + } // namespace FilePath MakeAbsoluteFilePath(const FilePath& input) { @@ -214,37 +333,22 @@ } bool DeleteFile(const FilePath& path, bool recursive) { + static constexpr char kRecursive[] = "DeleteFile.Recursive"; + static constexpr char kNonRecursive[] = "DeleteFile.NonRecursive"; + const StringPiece operation(recursive ? kRecursive : kNonRecursive); + AssertBlockingAllowed(); - if (path.empty()) + // Metrics for delete failures tracked in https://crbug.com/599084. Delete may + // fail for a number of reasons. Log some metrics relating to failures in the + // current code so that any improvements or regressions resulting from + // subsequent code changes can be detected. + const DWORD error = DoDeleteFile(path, recursive); + RecordPostOperationState(path, operation, error == ERROR_SUCCESS); + if (error == ERROR_SUCCESS) return true; - if (path.value().length() >= MAX_PATH) - return false; - - // Handle any path with wildcards. - if (path.BaseName().value().find_first_of(L"*?") != - FilePath::StringType::npos) { - return DeleteFileRecursive(path.DirName(), path.BaseName().value(), - recursive); - } - DWORD attr = GetFileAttributes(path.value().c_str()); - // We're done if we can't find the path. - if (attr == INVALID_FILE_ATTRIBUTES) - return true; - // We may need to clear the read-only bit. - if ((attr & FILE_ATTRIBUTE_READONLY) && - !SetFileAttributes(path.value().c_str(), - attr & ~FILE_ATTRIBUTE_READONLY)) { - return false; - } - // Directories are handled differently if they're recursive. - if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) - return !!::DeleteFile(path.value().c_str()); - // Handle a simple, single file delete. - if (!recursive || DeleteFileRecursive(path, L"*", true)) - return !!RemoveDirectory(path.value().c_str()); - + RecordFilesystemError(operation, error); return false; } @@ -394,7 +498,7 @@ // perform poorly when creating a large number of files with the same prefix. // In such cases, it is recommended that you construct unique file names based // on GUIDs." - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364991(v=vs.85).aspx + // https://msdn.microsoft.com/library/windows/desktop/aa364991.aspx FilePath temp_name; bool create_file_success = false;
diff --git a/base/i18n/number_formatting_unittest.cc b/base/i18n/number_formatting_unittest.cc index 0bdd603..045bc0e 100644 --- a/base/i18n/number_formatting_unittest.cc +++ b/base/i18n/number_formatting_unittest.cc
@@ -63,20 +63,20 @@ {1024.2, 0, "1,024", "1.024"}, {-1024.223, 2, "-1,024.22", "-1.024,22"}, {std::numeric_limits<double>::max(), 6, - "179,769,313,486,232,000,000,000,000,000,000,000,000,000,000,000,000," - "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," - "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," - "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," - "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," - "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," - "000.000000", - "179.769.313.486.232.000.000.000.000.000.000.000.000.000.000.000.000." - "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." - "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." - "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." - "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." - "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." - "000,000000"}, + "179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000," + "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," + "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," + "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," + "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," + "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000," + "000.000000", + "179.769.313.486.231.570.000.000.000.000.000.000.000.000.000.000.000." + "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." + "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." + "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." + "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." + "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000." + "000,000000"}, {std::numeric_limits<double>::min(), 2, "0.00", "0,00"}, {-42.7, 3, "-42.700", "-42,700"}, }; @@ -108,12 +108,10 @@ const wchar_t* expected_persian; const wchar_t* expected_arabic; } cases[] = { - {0, "0%", L"0\xa0%", L"\x6f0\x66a", L"\x660\xa0\x66a\x61c"}, - {42, "42%", L"42\xa0%", L"\x6f4\x6f2\x66a", - L"\x664\x662\xa0\x66a\x61c"}, - {1024, "1,024%", L"1.024\xa0%", - L"\x6f1\x66c\x6f0\x6f2\x6f4\x66a", - L"\x661\x66c\x660\x662\x664\xa0\x66a\x61c"}, + {0, "0%", L"0\xa0%", L"\x6f0\x66a", L"\x660\x66a\x61c"}, + {42, "42%", L"42\xa0%", L"\x6f4\x6f2\x66a", L"\x664\x662\x66a\x61c"}, + {1024, "1,024%", L"1.024\xa0%", L"\x6f1\x66c\x6f0\x6f2\x6f4\x66a", + L"\x661\x66c\x660\x662\x664\x66a\x61c"}, }; test::ScopedRestoreICUDefaultLocale restore_locale;
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc index a7048568..f3b55f2 100644 --- a/base/process/process_util_unittest.cc +++ b/base/process/process_util_unittest.cc
@@ -86,7 +86,7 @@ const char kSignalFileTerm[] = "TerminatedChildProcess.die"; #if defined(OS_FUCHSIA) -const char kSignalFileClone[] = "/tmp/ClonedTmpDir.die"; +const char kSignalFileClone[] = "ClonedTmpDir.die"; #endif #endif // defined(OS_POSIX) @@ -158,13 +158,13 @@ }; std::string ProcessUtilTest::GetSignalFilePath(const char* filename) { -#if !defined(OS_ANDROID) - return filename; -#else +#if defined(OS_ANDROID) || defined(OS_FUCHSIA) FilePath tmp_dir; - PathService::Get(DIR_CACHE, &tmp_dir); + PathService::Get(DIR_TEMP, &tmp_dir); tmp_dir = tmp_dir.Append(filename); return tmp_dir.value(); +#else + return filename; #endif } @@ -932,30 +932,6 @@ EXPECT_EQ(0, exit_code); } -MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyNamespace) { - CHECK(PathExists(FilePath("/data"))); - CHECK(!PathExists(FilePath("/svc"))); - return 0; -} - -TEST_F(ProcessUtilTest, LaunchNamespaceMap) { - LaunchOptions options; - options.clone_flags &= ~LP_CLONE_FDIO_NAMESPACE; - options.paths_to_map.push_back("/data"); - - // gtest uses /tmp to pass flags to the launched process, so it needs to be - // mapped as well. - options.paths_to_map.push_back("/tmp"); - - Process process = - SpawnChildWithOptions("ProcessUtilsVerifyNamespace", options); - ASSERT_TRUE(process.IsValid()); - - int exit_code; - ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_timeout(), - &exit_code)); - EXPECT_EQ(0, exit_code); -} #endif // defined(OS_FUCHSIA) namespace {
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc index ce30000b..8a889c5 100644 --- a/base/test/test_mock_time_task_runner.cc +++ b/base/test/test_mock_time_task_runner.cc
@@ -251,27 +251,45 @@ while (!tasks_.empty()) { // It's safe to remove const and consume |task| here, since |task| is not // used for ordering the item. - tasks.push_back( - std::move(const_cast<TestOrderedPendingTask&>(tasks_.top()))); + if (!tasks_.top().task.IsCancelled()) { + tasks.push_back( + std::move(const_cast<TestOrderedPendingTask&>(tasks_.top()))); + } tasks_.pop(); } return tasks; } -bool TestMockTimeTaskRunner::HasPendingTask() const { +bool TestMockTimeTaskRunner::HasPendingTask() { DCHECK(thread_checker_.CalledOnValidThread()); + AutoLock scoped_lock(tasks_lock_); + while (!tasks_.empty() && tasks_.top().task.IsCancelled()) + tasks_.pop(); return !tasks_.empty(); } -size_t TestMockTimeTaskRunner::GetPendingTaskCount() const { +size_t TestMockTimeTaskRunner::GetPendingTaskCount() { DCHECK(thread_checker_.CalledOnValidThread()); + AutoLock scoped_lock(tasks_lock_); + TaskPriorityQueue preserved_tasks; + while (!tasks_.empty()) { + if (!tasks_.top().task.IsCancelled()) { + preserved_tasks.push( + std::move(const_cast<TestOrderedPendingTask&>(tasks_.top()))); + } + tasks_.pop(); + } + tasks_.swap(preserved_tasks); return tasks_.size(); } -TimeDelta TestMockTimeTaskRunner::NextPendingTaskDelay() const { +TimeDelta TestMockTimeTaskRunner::NextPendingTaskDelay() { DCHECK(thread_checker_.CalledOnValidThread()); + AutoLock scoped_lock(tasks_lock_); + while (!tasks_.empty() && tasks_.top().task.IsCancelled()) + tasks_.pop(); return tasks_.empty() ? TimeDelta::Max() - : tasks_.top().GetTimeToRun() - NowTicks(); + : tasks_.top().GetTimeToRun() - now_ticks_; } // TODO(gab): Combine |thread_checker_| with a SequenceToken to differentiate @@ -329,6 +347,8 @@ TestPendingTask task_info; if (!DequeueNextTask(original_now_ticks, max_delta, &task_info)) break; + if (task_info.task.IsCancelled()) + continue; // If tasks were posted with a negative delay, task_info.GetTimeToRun() will // be less than |now_ticks_|. ForwardClocksUntilTickTime() takes care of not // moving the clock backwards in this case.
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h index fd2c2eeb..a7654318 100644 --- a/base/test/test_mock_time_task_runner.h +++ b/base/test/test_mock_time_task_runner.h
@@ -171,10 +171,11 @@ std::unique_ptr<TickClock> DeprecatedGetMockTickClock() const; const TickClock* GetMockTickClock() const; + // Cancelled pending tasks get pruned automatically. base::circular_deque<TestPendingTask> TakePendingTasks(); - bool HasPendingTask() const; - size_t GetPendingTaskCount() const; - TimeDelta NextPendingTaskDelay() const; + bool HasPendingTask(); + size_t GetPendingTaskCount(); + TimeDelta NextPendingTaskDelay(); // SingleThreadTaskRunner: bool RunsTasksInCurrentSequence() const override;
diff --git a/base/test/test_mock_time_task_runner_unittest.cc b/base/test/test_mock_time_task_runner_unittest.cc index 06530ca..e149f65 100644 --- a/base/test/test_mock_time_task_runner_unittest.cc +++ b/base/test/test_mock_time_task_runner_unittest.cc
@@ -4,6 +4,7 @@ #include "base/test/test_mock_time_task_runner.h" +#include "base/cancelable_callback.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/test/gtest_util.h" @@ -196,4 +197,54 @@ run_loop.Run(); } +TEST(TestMockTimeTaskRunnerTest, TakePendingTasks) { + auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>(); + task_runner->PostTask(FROM_HERE, Bind([]() {})); + EXPECT_TRUE(task_runner->HasPendingTask()); + EXPECT_EQ(1u, task_runner->TakePendingTasks().size()); + EXPECT_FALSE(task_runner->HasPendingTask()); +} + +TEST(TestMockTimeTaskRunnerTest, CancelPendingTask) { + auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>(); + CancelableClosure task1(Bind([]() {})); + task_runner->PostDelayedTask(FROM_HERE, task1.callback(), + TimeDelta::FromSeconds(1)); + EXPECT_TRUE(task_runner->HasPendingTask()); + EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); + EXPECT_EQ(TimeDelta::FromSeconds(1), task_runner->NextPendingTaskDelay()); + task1.Cancel(); + EXPECT_FALSE(task_runner->HasPendingTask()); + + CancelableClosure task2(Bind([]() {})); + task_runner->PostDelayedTask(FROM_HERE, task2.callback(), + TimeDelta::FromSeconds(1)); + task2.Cancel(); + EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); + + CancelableClosure task3(Bind([]() {})); + task_runner->PostDelayedTask(FROM_HERE, task3.callback(), + TimeDelta::FromSeconds(1)); + task3.Cancel(); + EXPECT_EQ(TimeDelta::Max(), task_runner->NextPendingTaskDelay()); + + CancelableClosure task4(Bind([]() {})); + task_runner->PostDelayedTask(FROM_HERE, task4.callback(), + TimeDelta::FromSeconds(1)); + task4.Cancel(); + EXPECT_TRUE(task_runner->TakePendingTasks().empty()); +} + +TEST(TestMockTimeTaskRunnerTest, NoFastForwardToCancelledTask) { + auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>(); + TimeTicks start_time = task_runner->NowTicks(); + CancelableClosure task(Bind([]() {})); + task_runner->PostDelayedTask(FROM_HERE, task.callback(), + TimeDelta::FromSeconds(1)); + EXPECT_EQ(TimeDelta::FromSeconds(1), task_runner->NextPendingTaskDelay()); + task.Cancel(); + task_runner->FastForwardUntilNoTasksRemain(); + EXPECT_EQ(start_time, task_runner->NowTicks()); +} + } // namespace base
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py index 3061a4b..cb05d60 100755 --- a/build/android/gradle/generate_gradle.py +++ b/build/android/gradle/generate_gradle.py
@@ -854,16 +854,15 @@ project_entries = [] # When only one entry will be generated we want it to have a valid # build.gradle file with its own AndroidManifest. - add_all_module = not args.split_projects and len(entries) > 1 for entry in entries: data = _GenerateGradleFile( entry, generator, build_vars, source_properties, jinja_processor) - if data and add_all_module: + if data and not args.all: project_entries.append((entry.ProjectName(), entry.GradleSubdir())) _WriteFile( os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE), data) - if add_all_module: + if args.all: project_entries.append((_MODULE_ALL, _MODULE_ALL)) _GenerateModuleAll( _gradle_output_dir, generator, build_vars, source_properties,
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index 906647b2..75aafc7 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -70,6 +70,10 @@ parser.add_argument('--native-lib-placeholders', help='GYP-list of native library placeholders to add.', default='[]') + parser.add_argument('--secondary-native-lib-placeholders', + help='GYP-list of native library placeholders to add ' + 'for the secondary ABI', + default='[]') parser.add_argument('--uncompress-shared-libraries', action='store_true', help='Uncompress shared libraries') @@ -79,6 +83,8 @@ options.uncompressed_assets) options.native_lib_placeholders = build_utils.ParseGnList( options.native_lib_placeholders) + options.secondary_native_lib_placeholders = build_utils.ParseGnList( + options.secondary_native_lib_placeholders) options.java_resources = build_utils.ParseGnList(options.java_resources) all_libs = [] for gyp_list in options.native_libs: @@ -93,7 +99,8 @@ if not options.android_abi and (options.native_libs or options.native_lib_placeholders): raise Exception('Must specify --android-abi with --native-libs') - if not options.secondary_android_abi and options.secondary_native_libs: + if not options.secondary_android_abi and (options.secondary_native_libs or + options.secondary_native_lib_placeholders): raise Exception('Must specify --secondary-android-abi with' ' --secondary-native-libs') return options @@ -225,6 +232,7 @@ input_strings = [options.android_abi, options.native_lib_placeholders, + options.secondary_native_lib_placeholders, options.uncompress_shared_libraries] if options.secondary_android_abi: @@ -304,6 +312,13 @@ apk_path = 'lib/%s/%s' % (options.android_abi, name) build_utils.AddToZipHermetic(out_apk, apk_path, data='') + for name in sorted(options.secondary_native_lib_placeholders): + # Note: Empty libs files are ignored by md5check (can cause issues + # with stale builds when the only change is adding/removing + # placeholders). + apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name) + build_utils.AddToZipHermetic(out_apk, apk_path, data='') + # 5. Resources for info in resource_infos[1:]: copy_resource(info)
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index e02e1fd..6068bfa 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2024,6 +2024,8 @@ # output_apk_path: Output path for the generated .apk. # native_lib_placeholders: List of placeholder filenames to add to the apk # (optional). + # secondary_native_lib_placeholders: List of placeholder filenames to add to + # the apk for the secondary ABI (optional). # native_libs: List of native libraries. # native_libs_filearg: @FileArg() of additionally native libraries. # write_asset_list: Adds an extra file to the assets, which contains a list of @@ -2040,6 +2042,11 @@ if (defined(invoker.native_lib_placeholders)) { _native_lib_placeholders = invoker.native_lib_placeholders } + _secondary_native_lib_placeholders = [] + if (defined(invoker.secondary_native_lib_placeholders)) { + _secondary_native_lib_placeholders = + invoker.secondary_native_lib_placeholders + } script = "//build/android/gyp/apkbuilder.py" depfile = "$target_gen_dir/$target_name.d" @@ -2106,6 +2113,13 @@ _native_lib_placeholders != []) { args += [ "--android-abi=$android_app_abi" ] } + if (defined(invoker.secondary_abi_native_libs_filearg) || + (defined(invoker.secondary_native_libs) && + invoker.secondary_native_libs != []) || + _secondary_native_lib_placeholders != []) { + assert(defined(android_app_secondary_abi)) + args += [ "--secondary-android-abi=$android_app_secondary_abi" ] + } if (invoker.native_libs != []) { _rebased_native_libs = rebase_path(invoker.native_libs, root_build_dir) args += [ "--native-libs=$_rebased_native_libs" ] @@ -2116,23 +2130,18 @@ if (_native_lib_placeholders != []) { args += [ "--native-lib-placeholders=$_native_lib_placeholders" ] } + if (_secondary_native_lib_placeholders != []) { + args += [ "--secondary-native-lib-placeholders=$_secondary_native_lib_placeholders" ] + } # TODO (michaelbai): Remove the secondary_native_libs variable. if (defined(invoker.secondary_abi_native_libs_filearg)) { - assert(defined(android_app_secondary_abi)) - args += [ - "--secondary-native-libs=${invoker.secondary_abi_native_libs_filearg}", - "--secondary-android-abi=$android_app_secondary_abi", - ] + args += [ "--secondary-native-libs=${invoker.secondary_abi_native_libs_filearg}" ] } else if (defined(invoker.secondary_native_libs) && invoker.secondary_native_libs != []) { - assert(defined(android_app_secondary_abi)) inputs += invoker.secondary_native_libs _secondary_native_libs = rebase_path(invoker.secondary_native_libs) - args += [ - "--secondary-native-libs=$_secondary_native_libs", - "--secondary-android-abi=$android_app_secondary_abi", - ] + args += [ "--secondary-native-libs=$_secondary_native_libs" ] } if (defined(invoker.uncompress_shared_libraries) && @@ -2299,6 +2308,7 @@ "native_lib_placeholders", "native_libs_filearg", "packaged_resources_path", + "secondary_native_lib_placeholders", "secondary_abi_native_libs_filearg", "secondary_native_libs", "uncompress_shared_libraries",
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 49d5960..97ad5f9b 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1780,6 +1780,8 @@ # dependencies will also be included in the apk (e.g. for is_component_build). # native_lib_placeholders: List of placeholder filenames to add to the apk # (optional). + # secondary_native_lib_placeholders: List of placeholder filenames to add to + # the apk for the secondary ABI (optional). # apk_under_test: For an instrumentation test apk, this is the target of the # tested apk. # write_asset_list: Adds an extra file to the assets, which contains a list of @@ -2520,7 +2522,11 @@ # Placeholders necessary for some older devices. # http://crbug.com/395038 - forward_variables_from(invoker, [ "native_lib_placeholders" ]) + forward_variables_from(invoker, + [ + "native_lib_placeholders", + "secondary_native_lib_placeholders", + ]) } _write_installer_json_rule_name = "${_template_name}__incremental_json"
diff --git a/build/config/fuchsia/build_manifest.py b/build/config/fuchsia/build_manifest.py index e5256fb..0fc8b74 100644 --- a/build/config/fuchsia/build_manifest.py +++ b/build/config/fuchsia/build_manifest.py
@@ -24,11 +24,11 @@ import tempfile -def ReadDynamicLibDeps(path): +def ReadDynamicLibDeps(paths): """Returns a list of NEEDED libraries read from a binary's ELF header.""" LIBRARY_RE = re.compile(r'.*\(NEEDED\)\s+Shared library: \[(?P<lib>.*)\]') - elfinfo = subprocess.check_output(['readelf', '-d', path], + elfinfo = subprocess.check_output(['readelf', '-d'] + paths, stderr=open(os.devnull, 'w')) libs = [] for line in elfinfo.split('\n'): @@ -56,16 +56,15 @@ # The computed set of visited transitive dependencies. deps = set() - while len(to_visit) > 0: - cur_path = to_visit.pop() - deps.add(cur_path) + while to_visit: + deps = deps.union(to_visit) # Resolve the full paths for all of |cur_path|'s NEEDED libraries. dep_paths = {available_libs[dep] - for dep in ReadDynamicLibDeps(cur_path)} + for dep in ReadDynamicLibDeps(list(to_visit))} # Add newly discovered dependencies to the pending traversal stack. - to_visit += dep_paths.difference(deps) + to_visit = dep_paths.difference(deps) return deps @@ -222,7 +221,6 @@ "%s: %s" % (os.path.relpath(output_path, out_dir), " ".join([os.path.relpath(f, out_dir) for f in expanded_files]))) - return 0
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 52f49a8..049a1f1 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -61,7 +61,8 @@ # Enable checks for indirect function calls via a function pointer. # TODO(pcc): remove this when we're ready to add these checks by default. # https://crbug.com/701919 - use_cfi_icall = false + use_cfi_icall = target_os == "linux" && !is_chromeos && target_cpu == "x64" && + is_official_build # Print detailed diagnostics when Control Flow Integrity detects a violation. use_cfi_diag = false
diff --git a/cc/blink/BUILD.gn b/cc/blink/BUILD.gn index 95d4b32..b5b3741 100644 --- a/cc/blink/BUILD.gn +++ b/cc/blink/BUILD.gn
@@ -15,8 +15,6 @@ "web_compositor_support_impl.h", "web_content_layer_impl.cc", "web_content_layer_impl.h", - "web_external_texture_layer_impl.cc", - "web_external_texture_layer_impl.h", "web_image_layer_impl.cc", "web_image_layer_impl.h", "web_layer_impl.cc",
diff --git a/cc/blink/web_compositor_support_impl.cc b/cc/blink/web_compositor_support_impl.cc index e70b25a..aca0e695 100644 --- a/cc/blink/web_compositor_support_impl.cc +++ b/cc/blink/web_compositor_support_impl.cc
@@ -7,14 +7,12 @@ #include <utility> #include "cc/blink/web_content_layer_impl.h" -#include "cc/blink/web_external_texture_layer_impl.h" #include "cc/blink/web_image_layer_impl.h" #include "cc/blink/web_layer_impl.h" #include "cc/blink/web_scrollbar_layer_impl.h" #include "cc/layers/layer.h" using blink::WebContentLayer; -using blink::WebExternalTextureLayer; using blink::WebImageLayer; using blink::WebLayer; using blink::WebScrollbar; @@ -42,12 +40,6 @@ return std::make_unique<WebContentLayerImpl>(client); } -std::unique_ptr<WebExternalTextureLayer> -WebCompositorSupportImpl::CreateExternalTextureLayer( - cc::TextureLayerClient* client) { - return std::make_unique<WebExternalTextureLayerImpl>(client); -} - std::unique_ptr<blink::WebImageLayer> WebCompositorSupportImpl::CreateImageLayer() { return std::make_unique<WebImageLayerImpl>();
diff --git a/cc/blink/web_compositor_support_impl.h b/cc/blink/web_compositor_support_impl.h index c243bfef..518b4ea 100644 --- a/cc/blink/web_compositor_support_impl.h +++ b/cc/blink/web_compositor_support_impl.h
@@ -27,8 +27,6 @@ std::unique_ptr<blink::WebLayer> CreateLayerFromCCLayer(cc::Layer*) override; std::unique_ptr<blink::WebContentLayer> CreateContentLayer( cc::ContentLayerClient* client) override; - std::unique_ptr<blink::WebExternalTextureLayer> CreateExternalTextureLayer( - cc::TextureLayerClient* client) override; std::unique_ptr<blink::WebImageLayer> CreateImageLayer() override; std::unique_ptr<blink::WebScrollbarLayer> CreateScrollbarLayer( std::unique_ptr<blink::WebScrollbar> scrollbar,
diff --git a/cc/blink/web_external_texture_layer_impl.cc b/cc/blink/web_external_texture_layer_impl.cc deleted file mode 100644 index 64fbf26..0000000 --- a/cc/blink/web_external_texture_layer_impl.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/blink/web_external_texture_layer_impl.h" - -#include "cc/blink/web_layer_impl.h" -#include "cc/layers/texture_layer.h" - -using cc::TextureLayer; - -namespace cc_blink { - -WebExternalTextureLayerImpl::WebExternalTextureLayerImpl( - cc::TextureLayerClient* client) { - scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(client); - layer->SetIsDrawable(true); - layer_.reset(new WebLayerImpl(layer)); -} - -WebExternalTextureLayerImpl::~WebExternalTextureLayerImpl() { - static_cast<TextureLayer*>(layer_->layer())->ClearClient(); -} - -blink::WebLayer* WebExternalTextureLayerImpl::Layer() { - return layer_.get(); -} - -void WebExternalTextureLayerImpl::ClearTexture() { - TextureLayer* layer = static_cast<TextureLayer*>(layer_->layer()); - layer->ClearTexture(); -} - -void WebExternalTextureLayerImpl::SetOpaque(bool opaque) { - static_cast<TextureLayer*>(layer_->layer())->SetContentsOpaque(opaque); -} - -void WebExternalTextureLayerImpl::SetFlipped(bool flipped) { - static_cast<TextureLayer*>(layer_->layer())->SetFlipped(flipped); -} - -void WebExternalTextureLayerImpl::SetPremultipliedAlpha( - bool premultiplied_alpha) { - static_cast<TextureLayer*>(layer_->layer()) - ->SetPremultipliedAlpha(premultiplied_alpha); -} - -void WebExternalTextureLayerImpl::SetBlendBackgroundColor(bool blend) { - static_cast<TextureLayer*>(layer_->layer())->SetBlendBackgroundColor(blend); -} - -void WebExternalTextureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { - static_cast<TextureLayer*>(layer_->layer()) - ->SetNearestNeighbor(nearest_neighbor); -} - -void WebExternalTextureLayerImpl::SetUV( - const blink::WebFloatPoint left_top, - const blink::WebFloatPoint right_bottom) { - static_cast<TextureLayer*>(layer_->layer()) - ->SetUV(gfx::PointF(left_top.x, left_top.y), - gfx::PointF(right_bottom.x, right_bottom.y)); -} - -} // namespace cc_blink
diff --git a/cc/blink/web_external_texture_layer_impl.h b/cc/blink/web_external_texture_layer_impl.h deleted file mode 100644 index 11ca63c..0000000 --- a/cc/blink/web_external_texture_layer_impl.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_BLINK_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_ -#define CC_BLINK_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_ - -#include <memory> - -#include "base/macros.h" -#include "cc/blink/cc_blink_export.h" -#include "third_party/blink/public/platform/web_external_texture_layer.h" - -namespace cc { -class TextureLayerClient; -} - -namespace cc_blink { -class WebLayerImpl; - -class WebExternalTextureLayerImpl : public blink::WebExternalTextureLayer { - public: - CC_BLINK_EXPORT explicit WebExternalTextureLayerImpl(cc::TextureLayerClient*); - ~WebExternalTextureLayerImpl() override; - - // blink::WebExternalTextureLayer implementation. - blink::WebLayer* Layer() override; - void ClearTexture() override; - void SetOpaque(bool opaque) override; - void SetFlipped(bool flipped) override; - void SetPremultipliedAlpha(bool premultiplied) override; - void SetBlendBackgroundColor(bool blend) override; - void SetNearestNeighbor(bool nearest_neighbor) override; - void SetUV(const blink::WebFloatPoint left_top, - const blink::WebFloatPoint right_bottom) override; - - private: - std::unique_ptr<WebLayerImpl> layer_; - - DISALLOW_COPY_AND_ASSIGN(WebExternalTextureLayerImpl); -}; - -} // namespace cc_blink - -#endif // CC_BLINK_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index 94935c0..131182a 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -1351,7 +1351,7 @@ layer_tree_host_->SetViewportSizeAndScale( layer_tree_host_->device_viewport_size(), test_scale, - layer_tree_host_->local_surface_id()); + layer_tree_host_->local_surface_id_from_parent()); scrollbar_layer->Update(); @@ -1417,7 +1417,7 @@ layer_tree_host_->SetViewportSizeAndScale( layer_tree_host_->device_viewport_size(), test_scale, - layer_tree_host_->local_surface_id()); + layer_tree_host_->local_surface_id_from_parent()); scrollbar_layer->Update();
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index bea6daa..92306d62 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -77,6 +77,8 @@ "render_surface_filters.h", "scoped_raster_flags.cc", "scoped_raster_flags.h", + "shader_transfer_cache_entry.cc", + "shader_transfer_cache_entry.h", "skia_paint_canvas.cc", "skia_paint_canvas.h", "skia_paint_image_generator.cc",
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc index 414e598..805520f 100644 --- a/cc/paint/paint_image.cc +++ b/cc/paint/paint_image.cc
@@ -15,8 +15,8 @@ namespace cc { namespace { -base::AtomicSequenceNumber g_next_id_; -base::AtomicSequenceNumber g_next_content_id_; +base::AtomicSequenceNumber g_next_image_id; +base::AtomicSequenceNumber g_next_image_content_id; } // namespace const PaintImage::Id PaintImage::kNonLazyStableId = -1; @@ -74,12 +74,12 @@ // static PaintImage::Id PaintImage::GetNextId() { - return g_next_id_.GetNext(); + return g_next_image_id.GetNext(); } // static PaintImage::ContentId PaintImage::GetNextContentId() { - return g_next_content_id_.GetNext(); + return g_next_image_content_id.GetNext(); } const sk_sp<SkImage>& PaintImage::GetSkImage() const {
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index bb32eab..db168437 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -2282,10 +2282,10 @@ if (op->IsPaintOpWithFlags()) { const auto* flags_op = static_cast<const PaintOpWithFlags*>(op); - const bool create_skia_shaders = true; + const bool is_rasterizing = true; const ScopedRasterFlags scoped_flags( &flags_op->flags, new_params.image_provider, canvas->getTotalMatrix(), - iter.alpha(), create_skia_shaders); + iter.alpha(), is_rasterizing); if (const auto* raster_flags = scoped_flags.flags()) flags_op->RasterWithFlags(canvas, raster_flags, new_params); } else {
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index 42cd33d..050efd6 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -28,6 +28,7 @@ #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkTextBlob.h" +#include "ui/gfx/color_space.h" class SkColorSpace; class SkStrikeClient; @@ -168,6 +169,7 @@ DeserializeOptions(TransferCacheDeserializeHelper* transfer_cache, SkStrikeClient* strike_client); TransferCacheDeserializeHelper* transfer_cache = nullptr; + uint32_t raster_color_space_id = gfx::ColorSpace::kInvalidId; SkStrikeClient* strike_client = nullptr; };
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc index e34eaaa..9b1453e7 100644 --- a/cc/paint/paint_op_buffer_serializer.cc +++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -272,11 +272,11 @@ uint8_t alpha) { // We don't need the skia backing for decoded shaders during serialization, // since those are created on the service side where the record is rasterized. - const bool create_skia_shaders = false; + const bool is_rasterizing = false; const ScopedRasterFlags scoped_flags( &flags_op->flags, options->image_provider, - options->canvas->getTotalMatrix(), alpha, create_skia_shaders); + options->canvas->getTotalMatrix(), alpha, is_rasterizing); const PaintFlags* flags_to_serialize = scoped_flags.flags(); if (!flags_to_serialize) return true;
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 4e8da84..c63a1cd 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -12,6 +12,7 @@ #include "cc/paint/paint_op_buffer_serializer.h" #include "cc/paint/paint_op_reader.h" #include "cc/paint/paint_op_writer.h" +#include "cc/paint/shader_transfer_cache_entry.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/paint_op_helper.h" #include "cc/test/skia_common.h" @@ -3089,6 +3090,176 @@ EXPECT_EQ(scale.height(), 0.8f); } +TEST(PaintOpBufferTest, RecordShadersCached) { + auto record_buffer = sk_make_sp<PaintOpBuffer>(); + record_buffer->push<DrawImageOp>( + CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f, nullptr); + auto shader = PaintShader::MakePaintRecord( + record_buffer, SkRect::MakeWH(10.f, 10.f), + SkShader::TileMode::kRepeat_TileMode, + SkShader::TileMode::kRepeat_TileMode, nullptr); + shader->set_has_animated_images(false); + auto shader_id = shader->paint_record_shader_id(); + TestOptionsProvider options_provider; + auto* transfer_cache = options_provider.transfer_cache_helper(); + + // Generate serialized |memory|. + std::unique_ptr<char, base::AlignedFreeDeleter> memory( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + size_t memory_written = 0; + { + auto buffer = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setShader(shader); + buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags); + + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), transfer_cache, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(buffer.get()); + memory_written = serializer.written(); + } + + // Generate serialized |memory_scaled|, which is the same pob, but with + // a scale factor. + std::unique_ptr<char, base::AlignedFreeDeleter> memory_scaled( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + size_t memory_scaled_written = 0; + { + auto buffer = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setShader(shader); + // This buffer has an additional scale op. + buffer->push<ScaleOp>(2.0f, 3.7f); + buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags); + + SimpleBufferSerializer serializer( + memory_scaled.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), transfer_cache, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(buffer.get()); + memory_scaled_written = serializer.written(); + } + + // Hold onto records so PaintShader pointer comparisons are valid. + sk_sp<PaintRecord> records[5]; + const SkShader* last_shader = nullptr; + PaintOp::DeserializeOptions deserialize_options( + transfer_cache, options_provider.strike_client()); + + // Several deserialization test cases: + // (0) deserialize once, verify cached is the same as deserialized version + // (1) deserialize again, verify shader gets reused + // (2) change color space, verify shader is new + // (3) change scale, verify shader is new + // (4) sanity check, same new scale + same new colorspace, shader is reused. + for (size_t i = 0; i < 5; ++i) { + if (i < 2) { + // arbitrary color space ids + deserialize_options.raster_color_space_id = 23; + } else { + deserialize_options.raster_color_space_id = 34; + } + + if (i < 3) { + records[i] = PaintOpBuffer::MakeFromMemory(memory.get(), memory_written, + deserialize_options); + } else { + records[i] = PaintOpBuffer::MakeFromMemory( + memory_scaled.get(), memory_scaled_written, deserialize_options); + } + + auto* entry = + transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(shader_id); + ASSERT_TRUE(entry); + EXPECT_EQ(entry->raster_color_space_id(), + deserialize_options.raster_color_space_id); + if (i < 3) + EXPECT_EQ(records[i]->size(), 1u); + else + EXPECT_EQ(records[i]->size(), 2u); + + for (auto* base_op : PaintOpBuffer::Iterator(records[i].get())) { + if (base_op->GetType() != PaintOpType::DrawRect) + continue; + auto* op = static_cast<const DrawRectOp*>(base_op); + + // In every case, the shader in the op should get cached for future + // use. + auto* op_skshader = op->flags.getShader()->GetSkShader().get(); + EXPECT_EQ(op_skshader, entry->shader()->GetSkShader().get()); + switch (i) { + case 0: + // Nothing to check. + break; + case 1: + EXPECT_EQ(op_skshader, last_shader); + break; + case 2: + EXPECT_NE(op_skshader, last_shader); + break; + case 3: + EXPECT_NE(op_skshader, last_shader); + break; + case 4: + EXPECT_EQ(op_skshader, last_shader); + break; + } + last_shader = op_skshader; + } + } +} + +TEST(PaintOpBufferTest, RecordShadersCachedSize) { + auto record_buffer = sk_make_sp<PaintOpBuffer>(); + size_t estimated_image_size = 30 * 30 * 4; + auto image = CreateBitmapImage(gfx::Size(30, 30)); + record_buffer->push<DrawImageOp>(image, 0.f, 0.f, nullptr); + auto shader = PaintShader::MakePaintRecord( + record_buffer, SkRect::MakeWH(10.f, 10.f), + SkShader::TileMode::kRepeat_TileMode, + SkShader::TileMode::kRepeat_TileMode, nullptr); + shader->set_has_animated_images(false); + auto shader_id = shader->paint_record_shader_id(); + TestOptionsProvider options_provider; + auto* transfer_cache = options_provider.transfer_cache_helper(); + + // Generate serialized |memory|. + std::unique_ptr<char, base::AlignedFreeDeleter> memory( + static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, + PaintOpBuffer::PaintOpAlign))); + auto buffer = sk_make_sp<PaintOpBuffer>(); + PaintFlags flags; + flags.setShader(shader); + buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags); + + SimpleBufferSerializer serializer( + memory.get(), PaintOpBuffer::kInitialBufferSize, + options_provider.image_provider(), transfer_cache, + options_provider.strike_server(), options_provider.color_space(), + options_provider.can_use_lcd_text()); + serializer.Serialize(buffer.get()); + + PaintOp::DeserializeOptions deserialize_options( + transfer_cache, options_provider.strike_client()); + auto record = PaintOpBuffer::MakeFromMemory( + memory.get(), serializer.written(), deserialize_options); + auto* shader_entry = + transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>(shader_id); + ASSERT_TRUE(shader_entry); + + // The size of the shader in the cache should be bigger than both the record + // and the image. Exact numbers not used here to not overfit this test. + size_t shader_size = shader_entry->CachedSize(); + EXPECT_GT(estimated_image_size, serializer.written()); + EXPECT_GT(shader_size, estimated_image_size); +} + TEST(PaintOpBufferTest, TotalOpCount) { auto record_buffer = sk_make_sp<PaintOpBuffer>(); auto sub_record_buffer = sk_make_sp<PaintOpBuffer>();
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc index 3431afc3..915bb86 100644 --- a/cc/paint/paint_op_reader.cc +++ b/cc/paint/paint_op_reader.cc
@@ -15,6 +15,7 @@ #include "cc/paint/paint_shader.h" #include "cc/paint/paint_typeface_transfer_cache_entry.h" #include "cc/paint/path_transfer_cache_entry.h" +#include "cc/paint/shader_transfer_cache_entry.h" #include "cc/paint/transfer_cache_deserialize_helper.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRRect.h" @@ -449,8 +450,18 @@ Read(&ref.image_); bool has_record = false; ReadSimple(&has_record); - if (has_record) - Read(&ref.record_); + uint32_t shader_id = PaintShader::kInvalidRecordShaderId; + size_t shader_size = 0; + if (has_record) { + Read(&shader_id); + + // Track dependent transfer cache entries to make cached shader size + // more realistic. + size_t pre_size = options_.transfer_cache->GetTotalEntrySizes(); + size_t record_size = Read(&ref.record_); + size_t post_size = options_.transfer_cache->GetTotalEntrySizes(); + shader_size = post_size - pre_size + record_size; + } decltype(ref.colors_)::size_type colors_size = 0; ReadSimple(&colors_size); @@ -488,9 +499,40 @@ SetInvalid(); return; } - // TODO(vmpstr): We should have a PaintShader id and cache these shaders - // instead of creating every time we deserialize. - (*shader)->CreateSkShader(); + + if (shader_id == PaintShader::kInvalidRecordShaderId) { + // Paint record shaders must have ids. + if (shader_type == PaintShader::Type::kPaintRecord) { + SetInvalid(); + return; + } + (*shader)->CreateSkShader(); + return; + } + + // Record shaders have shader ids. Attempt to use cached versions of + // these so that Skia can cache based on SkPictureShader::fUniqueId. + // These shaders are always serialized (and assumed to not be large + // records). Handling this edge case in this roundabout way prevents + // transfer cache entries from needing to depend on other transfer cache + // entries. + auto* entry = + options_.transfer_cache->GetEntryAs<ServiceShaderTransferCacheEntry>( + shader_id); + // Only consider entries that use the same scale and color space. + // This limits the service side transfer cache to only having one entry + // per shader but this will hit the common case of enabling Skia reuse. + if (entry && entry->shader()->tile_ == ref.tile_ && + entry->raster_color_space_id() == options_.raster_color_space_id) { + DCHECK(!ref.cached_shader_); + ref.cached_shader_ = entry->shader()->GetSkShader(); + } else { + ref.CreateSkShader(); + std::unique_ptr<ServiceShaderTransferCacheEntry> entry( + new ServiceShaderTransferCacheEntry( + *shader, options_.raster_color_space_id, shader_size)); + options_.transfer_cache->CreateLocalEntry(shader_id, std::move(entry)); + } } void PaintOpReader::Read(SkMatrix* matrix) { @@ -1149,7 +1191,7 @@ base::OptionalOrNullptr(crop_rect))); } -void PaintOpReader::Read(sk_sp<PaintRecord>* record) { +size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) { size_t size_bytes = 0; ReadSimple(&size_bytes); AlignMemory(PaintOpBuffer::PaintOpAlign); @@ -1159,16 +1201,16 @@ // enabled. if (size_bytes != 0) { SetInvalid(); - return; + return 0; } *record = sk_make_sp<PaintOpBuffer>(); - return; + return 0; } if (size_bytes > remaining_bytes_) SetInvalid(); if (!valid_) - return; + return 0; PaintOp::DeserializeOptions options; options.transfer_cache = options_.transfer_cache; @@ -1176,10 +1218,11 @@ *record = PaintOpBuffer::MakeFromMemory(memory_, size_bytes, options); if (!*record) { SetInvalid(); - return; + return 0; } memory_ += size_bytes; remaining_bytes_ -= size_bytes; + return size_bytes; } void PaintOpReader::Read(SkRegion* region) {
diff --git a/cc/paint/paint_op_reader.h b/cc/paint/paint_op_reader.h index bfed664..6a0c0e7 100644 --- a/cc/paint/paint_op_reader.h +++ b/cc/paint/paint_op_reader.h
@@ -183,7 +183,9 @@ sk_sp<PaintFilter>* filter, const base::Optional<PaintFilter::CropRect>& crop_rect); - void Read(sk_sp<PaintRecord>* record); + // Returns the size of the read record, 0 if error. + size_t Read(sk_sp<PaintRecord>* record); + void Read(SkRegion* region); const volatile char* memory_ = nullptr;
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc index d51b845..68ac8c31 100644 --- a/cc/paint/paint_op_writer.cc +++ b/cc/paint/paint_op_writer.cc
@@ -327,6 +327,8 @@ Write(shader->image_); if (shader->record_) { Write(true); + DCHECK_NE(shader->id_, PaintShader::kInvalidRecordShaderId); + Write(shader->id_); base::Optional<gfx::Rect> playback_rect; base::Optional<gfx::SizeF> post_scale; if (shader->tile_scale()) { @@ -337,6 +339,7 @@ Write(shader->record_.get(), std::move(playback_rect), std::move(post_scale)); } else { + DCHECK_EQ(shader->id_, PaintShader::kInvalidRecordShaderId); Write(false); } WriteSimple(shader->colors_.size());
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc index 6baee9f..45f067d4f 100644 --- a/cc/paint/paint_shader.cc +++ b/cc/paint/paint_shader.cc
@@ -4,6 +4,7 @@ #include "cc/paint/paint_shader.h" +#include "base/atomic_sequence_num.h" #include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -11,6 +12,7 @@ namespace cc { namespace { +base::AtomicSequenceNumber g_next_shader_id; sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record, const SkRect& bounds, @@ -26,6 +28,8 @@ } // namespace +const PaintShader::RecordShaderId PaintShader::kInvalidRecordShaderId = -1; + sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) { sk_sp<PaintShader> shader(new PaintShader(Type::kColor)); @@ -151,6 +155,7 @@ sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); shader->record_ = std::move(record); + shader->id_ = g_next_shader_id.GetNext(); shader->tile_ = tile; shader->scaling_behavior_ = scaling_behavior; shader->SetMatrixAndTiling(local_matrix, tx, ty); @@ -175,6 +180,7 @@ sizeof(shader->end_degrees_) + PaintOpWriter::GetImageSize(shader->image_) + PaintOpWriter::GetImageSize(shader->image_) + bool_size + + sizeof(shader->id_) + PaintOpWriter::GetRecordSize(shader->record_.get()) + sizeof(shader->colors_.size()) + shader->colors_.size() * sizeof(SkColor) + @@ -258,6 +264,7 @@ sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); shader->record_ = record_; + shader->id_ = id_; shader->tile_ = tile_rect; // Use a fixed scale since we have already scaled the tile rect and fixed the // raster scale.
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h index 6c197b7..d231174 100644 --- a/cc/paint/paint_shader.h +++ b/cc/paint/paint_shader.h
@@ -16,6 +16,7 @@ #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkShader.h" +#include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size_f.h" namespace cc { @@ -36,6 +37,9 @@ kShaderCount }; + using RecordShaderId = uint32_t; + static const RecordShaderId kInvalidRecordShaderId; + // Scaling behavior dictates how a PaintRecord shader will behave. Use // RasterAtScale to create a picture shader. Use FixedScale to create an image // shader that is backed by the paint record. @@ -148,6 +152,11 @@ bool operator==(const PaintShader& other) const; bool operator!=(const PaintShader& other) const { return !(*this == other); } + RecordShaderId paint_record_shader_id() const { + DCHECK(id_ == kInvalidRecordShaderId || shader_type_ == Type::kPaintRecord); + return id_; + } + private: friend class PaintFlags; friend class PaintOpReader; @@ -156,6 +165,7 @@ friend class ScopedRasterFlags; FRIEND_TEST_ALL_PREFIXES(PaintShaderTest, DecodePaintRecord); FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, PaintRecordShaderSerialization); + FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, RecordShadersCached); explicit PaintShader(Type type); @@ -196,6 +206,7 @@ PaintImage image_; sk_sp<PaintRecord> record_; + RecordShaderId id_ = kInvalidRecordShaderId; // For decoded PaintRecord shaders, specifies the scale at which the record // will be rasterized.
diff --git a/cc/paint/scoped_raster_flags.cc b/cc/paint/scoped_raster_flags.cc index b54f137..e4a6298 100644 --- a/cc/paint/scoped_raster_flags.cc +++ b/cc/paint/scoped_raster_flags.cc
@@ -13,7 +13,7 @@ ImageProvider* image_provider, const SkMatrix& ctm, uint8_t alpha, - bool create_skia_shader) + bool is_rasterizing) : original_flags_(flags) { if (flags->HasDiscardableImages() && image_provider) { // TODO(khushalsagar): The decoding of images in PaintFlags here is a bit of @@ -25,7 +25,7 @@ DecodeImageShader(ctm); if (decode_failed_) return; - DecodeRecordShader(ctm, create_skia_shader); + DecodeRecordShader(ctm, is_rasterizing); if (decode_failed_) return; DecodeFilter(); @@ -101,16 +101,20 @@ } void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm, - bool create_skia_shader) { + bool is_rasterizing) { if (!flags()->HasShader() || flags()->getShader()->shader_type() != PaintShader::Type::kPaintRecord) return; - // TODO(khushalsagar): For OOP, we have to decode everything during - // serialization. This will force us to use original sized decodes. - if (flags()->getShader()->image_analysis_state() != - ImageAnalysisState::kAnimatedImages) + // Only early out here if we are rasterizing and not serializing directly. + // In process raster will cache the skia shader by letting Skia handle + // the decodes as needed. Out of process raster should never early out + // and should always make sure the fonts and images are processed at the + // correct scale. + if (is_rasterizing && flags()->getShader()->image_analysis_state() != + ImageAnalysisState::kAnimatedImages) { return; + } auto decoded_shader = flags()->getShader()->CreateDecodedPaintRecord( ctm, &*decode_stashing_image_provider_); @@ -119,7 +123,7 @@ return; } - if (create_skia_shader) + if (is_rasterizing) decoded_shader->CreateSkShader(&*decode_stashing_image_provider_); MutableFlags()->setShader(std::move(decoded_shader)); }
diff --git a/cc/paint/scoped_raster_flags.h b/cc/paint/scoped_raster_flags.h index 5407b5e..e692d33 100644 --- a/cc/paint/scoped_raster_flags.h +++ b/cc/paint/scoped_raster_flags.h
@@ -18,11 +18,13 @@ class CC_PAINT_EXPORT ScopedRasterFlags { public: // |flags| and |image_provider| must outlive this class. + // |is_rasterizing| is true if these flags are for direct rasterization + // and false if these flags are being used for serialization. ScopedRasterFlags(const PaintFlags* flags, ImageProvider* image_provider, const SkMatrix& ctm, uint8_t alpha, - bool create_skia_shaders); + bool is_rasterizing); ~ScopedRasterFlags(); // The usage of these flags should not extend beyond the lifetime of this @@ -36,7 +38,7 @@ private: void DecodeImageShader(const SkMatrix& ctm); - void DecodeRecordShader(const SkMatrix& ctm, bool create_skia_shader); + void DecodeRecordShader(const SkMatrix& ctm, bool is_rasterizing); void DecodeFilter(); void AdjustStrokeIfNeeded(const SkMatrix& ctm);
diff --git a/cc/paint/shader_transfer_cache_entry.cc b/cc/paint/shader_transfer_cache_entry.cc new file mode 100644 index 0000000..5e66f1b6 --- /dev/null +++ b/cc/paint/shader_transfer_cache_entry.cc
@@ -0,0 +1,31 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/shader_transfer_cache_entry.h" + +namespace cc { + +ServiceShaderTransferCacheEntry::ServiceShaderTransferCacheEntry( + sk_sp<PaintShader> shader, + uint32_t raster_color_space_id, + size_t size) + : shader_(std::move(shader)), + raster_color_space_id_(raster_color_space_id), + size_(size) {} + +ServiceShaderTransferCacheEntry::~ServiceShaderTransferCacheEntry() = default; + +size_t ServiceShaderTransferCacheEntry::CachedSize() const { + return size_; +} + +bool ServiceShaderTransferCacheEntry::Deserialize( + GrContext* context, + base::span<const uint8_t> data) { + // These entries must be created directly via CreateLocalEntry. + NOTREACHED(); + return false; +} + +} // namespace cc
diff --git a/cc/paint/shader_transfer_cache_entry.h b/cc/paint/shader_transfer_cache_entry.h new file mode 100644 index 0000000..fcb6abb7 --- /dev/null +++ b/cc/paint/shader_transfer_cache_entry.h
@@ -0,0 +1,46 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_SHADER_TRANSFER_CACHE_ENTRY_H_ +#define CC_PAINT_SHADER_TRANSFER_CACHE_ENTRY_H_ + +#include "base/containers/span.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/paint_shader.h" +#include "cc/paint/transfer_cache_entry.h" + +namespace cc { + +// There is only a service transfer cache entry here. The reason shaders +// are cached at all are to reuse internal Skia caches for SkPictureShaders. +// However, the major reason not to transfer from the client is that it +// avoids the design change to make it possible for transfer cache entries +// to depend on transfer cache entries. This adds a number of wrinkles +// (during serialization, deserialization, scheduling). The assumption +// is that most picture shaders are small (e.g. a few ops to draw a tiled +// image) and that the design complication for this edge case isn't worth +// it. + +class CC_PAINT_EXPORT ServiceShaderTransferCacheEntry + : public ServiceTransferCacheEntryBase<TransferCacheEntryType::kShader> { + public: + explicit ServiceShaderTransferCacheEntry(sk_sp<PaintShader> shader, + uint32_t raster_color_space_id, + size_t size); + ~ServiceShaderTransferCacheEntry() final; + size_t CachedSize() const final; + bool Deserialize(GrContext* context, base::span<const uint8_t> data) final; + + sk_sp<PaintShader> shader() const { return shader_; } + uint32_t raster_color_space_id() const { return raster_color_space_id_; } + + private: + sk_sp<PaintShader> shader_; + uint32_t raster_color_space_id_; + size_t size_ = 0; +}; + +} // namespace cc + +#endif // CC_PAINT_SHADER_TRANSFER_CACHE_ENTRY_H_
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc index 83128d5c..686ed2b 100644 --- a/cc/paint/skia_paint_canvas.cc +++ b/cc/paint/skia_paint_canvas.cc
@@ -16,7 +16,7 @@ namespace cc { -const bool SkiaPaintCanvas::kCreateSkiaShaders = true; +const bool SkiaPaintCanvas::kIsRasterizing = true; SkiaPaintCanvas::ContextFlushes::ContextFlushes() : enable(false), max_draws_before_flush(-1) {} @@ -170,9 +170,8 @@ SkScalar x1, SkScalar y1, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -182,9 +181,8 @@ } void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -194,9 +192,8 @@ } void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -206,9 +203,8 @@ } void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -218,9 +214,8 @@ } void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -232,9 +227,8 @@ void SkiaPaintCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -247,9 +241,8 @@ SkScalar rx, SkScalar ry, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -259,9 +252,8 @@ } void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -277,7 +269,7 @@ base::Optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - 255u, kCreateSkiaShaders); + 255u, kIsRasterizing); if (!scoped_flags->flags()) return; } @@ -297,7 +289,7 @@ base::Optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - 255u, kCreateSkiaShaders); + 255u, kIsRasterizing); if (!scoped_flags->flags()) return; } @@ -317,7 +309,7 @@ if (flags) { ScopedRasterFlags raster_flags(flags, image_provider_, canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -332,9 +324,8 @@ SkScalar x, SkScalar y, const PaintFlags& flags) { - ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u, - kCreateSkiaShaders); + ScopedRasterFlags raster_flags( + &flags, image_provider_, canvas_->getTotalMatrix(), 255u, kIsRasterizing); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint();
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h index d5f39f6..502be1b6 100644 --- a/cc/paint/skia_paint_canvas.h +++ b/cc/paint/skia_paint_canvas.h
@@ -143,7 +143,7 @@ private: // We always need skia shaders since the ops will be played on an SkCanvas. - static const bool kCreateSkiaShaders; + static const bool kIsRasterizing; void WrapCanvasInColorSpaceXformCanvas( sk_sp<SkColorSpace> target_color_space);
diff --git a/cc/paint/transfer_cache_deserialize_helper.h b/cc/paint/transfer_cache_deserialize_helper.h index 48d4c6f..530b479 100644 --- a/cc/paint/transfer_cache_deserialize_helper.h +++ b/cc/paint/transfer_cache_deserialize_helper.h
@@ -32,16 +32,28 @@ if (entry == nullptr) { return nullptr; } + + total_size_ += entry->CachedSize(); + // The service side entry is created using T::kType, so the class created is // guaranteed to make the entry type. DCHECK_EQ(entry->Type(), entry_type); return static_cast<T*>(entry); } + // Creates an entry directly. If an entry exists, it will be clobbered. + virtual void CreateLocalEntry( + uint32_t id, + std::unique_ptr<ServiceTransferCacheEntry> entry) = 0; + + size_t GetTotalEntrySizes() const { return total_size_; } + private: virtual ServiceTransferCacheEntry* GetEntryInternal( TransferCacheEntryType entry_type, uint32_t entry_id) = 0; + + size_t total_size_ = 0; }; }; // namespace cc
diff --git a/cc/paint/transfer_cache_entry.cc b/cc/paint/transfer_cache_entry.cc index 66c9622..eb51292 100644 --- a/cc/paint/transfer_cache_entry.cc +++ b/cc/paint/transfer_cache_entry.cc
@@ -12,6 +12,7 @@ #include "cc/paint/paint_typeface_transfer_cache_entry.h" #include "cc/paint/path_transfer_cache_entry.h" #include "cc/paint/raw_memory_transfer_cache_entry.h" +#include "cc/paint/shader_transfer_cache_entry.h" namespace cc { @@ -28,6 +29,10 @@ return std::make_unique<ServiceColorSpaceTransferCacheEntry>(); case TransferCacheEntryType::kPath: return std::make_unique<ServicePathTransferCacheEntry>(); + case TransferCacheEntryType::kShader: + // ServiceShaderTransferCache is only created via CreateLocalEntry + // and is never serialized/deserialized. + return nullptr; } return nullptr;
diff --git a/cc/paint/transfer_cache_entry.h b/cc/paint/transfer_cache_entry.h index dca7b96e..474bd97 100644 --- a/cc/paint/transfer_cache_entry.h +++ b/cc/paint/transfer_cache_entry.h
@@ -25,8 +25,9 @@ kPaintTypeface, kColorSpace, kPath, + kShader, // Add new entries above this line, make sure to update kLast. - kLast = kPath, + kLast = kShader, }; // An interface used on the client to serialize a transfer cache entry
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index bdef6b4f..33e8417f 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -735,7 +735,7 @@ #if defined(OS_ANDROID) transfer_resource.is_backed_by_surface_texture = video_frame->metadata()->IsTrue( - media::VideoFrameMetadata::SURFACE_TEXTURE); + media::VideoFrameMetadata::TEXTURE_OWNER); transfer_resource.wants_promotion_hint = video_frame->metadata()->IsTrue( media::VideoFrameMetadata::WANTS_PROMOTION_HINT); #endif
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 994b1ce..1579df03 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -871,7 +871,7 @@ const viz::LocalSurfaceId& local_surface_id) { DCHECK(main_task_runner_->BelongsToCurrentThread()); if (layer_tree_host_) - layer_tree_host_->SetLocalSurfaceId(local_surface_id); + layer_tree_host_->SetLocalSurfaceIdFromParent(local_surface_id); } void LayerTreeTest::DispatchSetDeferCommits(bool defer_commits) {
diff --git a/cc/test/transfer_cache_test_helper.cc b/cc/test/transfer_cache_test_helper.cc index 073e6d8..8613c422 100644 --- a/cc/test/transfer_cache_test_helper.cc +++ b/cc/test/transfer_cache_test_helper.cc
@@ -44,6 +44,18 @@ EnforceLimits(); } +void TransferCacheTestHelper::CreateLocalEntry( + uint32_t id, + std::unique_ptr<ServiceTransferCacheEntry> entry) { + auto key = std::make_pair(entry->Type(), id); + + DeleteEntryDirect(key); + + entries_[key] = std::move(entry); + local_entries_.insert(key); + last_added_entry_ = key; +} + void TransferCacheTestHelper::UnlockEntriesDirect( const std::vector<EntryKey>& keys) { for (const auto& key : keys) { @@ -54,6 +66,7 @@ void TransferCacheTestHelper::DeleteEntryDirect(const EntryKey& key) { locked_entries_.erase(key); + local_entries_.erase(key); entries_.erase(key); } @@ -70,15 +83,17 @@ TransferCacheEntryType type, uint32_t id) { auto key = std::make_pair(type, id); - if (locked_entries_.count(key) == 0) + if (locked_entries_.count(key) + local_entries_.count(key) == 0) return nullptr; - DCHECK(entries_.find(key) != entries_.end()); + if (entries_.find(key) == entries_.end()) + return nullptr; return entries_[key].get(); } bool TransferCacheTestHelper::LockEntryInternal(const EntryKey& key) { if (entries_.find(key) == entries_.end()) return false; + locked_entries_.insert(key); EnforceLimits(); return true;
diff --git a/cc/test/transfer_cache_test_helper.h b/cc/test/transfer_cache_test_helper.h index 399885d..fc86362 100644 --- a/cc/test/transfer_cache_test_helper.h +++ b/cc/test/transfer_cache_test_helper.h
@@ -39,6 +39,10 @@ const EntryKey& GetLastAddedEntry() const { return last_added_entry_; } + void CreateLocalEntry( + uint32_t id, + std::unique_ptr<ServiceTransferCacheEntry> entry) override; + protected: // Serialization helpers. bool LockEntryInternal(const EntryKey& key) override; @@ -50,6 +54,7 @@ void EnforceLimits(); std::map<EntryKey, std::unique_ptr<ServiceTransferCacheEntry>> entries_; + std::set<EntryKey> local_entries_; std::set<EntryKey> locked_entries_; EntryKey last_added_entry_ = {TransferCacheEntryType::kRawMemory, ~0};
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 7b90131..e3d9d41 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -433,7 +433,7 @@ void LayerTreeHost::UpdateDeferCommitsInternal() { proxy_->SetDeferCommits(defer_commits_ || (settings_.enable_surface_synchronization && - !local_surface_id_.is_valid())); + !local_surface_id_from_parent_.is_valid())); } bool LayerTreeHost::IsUsingLayerLists() const { @@ -1052,8 +1052,8 @@ void LayerTreeHost::SetViewportSizeAndScale( const gfx::Size& device_viewport_size, float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id) { - SetLocalSurfaceId(local_surface_id); + const viz::LocalSurfaceId& local_surface_id_from_parent) { + SetLocalSurfaceIdFromParent(local_surface_id_from_parent); bool changed = false; if (device_viewport_size_ != device_viewport_size) { @@ -1080,7 +1080,8 @@ #if defined(OS_MACOSX) // TODO(ccameron): This check is not valid on Aura or Mus yet, but should // be. - CHECK(!has_pushed_local_surface_id_ || !local_surface_id_.is_valid()); + CHECK(!has_pushed_local_surface_id_from_parent_ || + !local_surface_id_from_parent_.is_valid()); #endif } } @@ -1177,12 +1178,12 @@ SetNeedsCommit(); } -void LayerTreeHost::SetLocalSurfaceId( - const viz::LocalSurfaceId& local_surface_id) { - if (local_surface_id_ == local_surface_id) +void LayerTreeHost::SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent) { + if (local_surface_id_from_parent_ == local_surface_id_from_parent) return; - local_surface_id_ = local_surface_id; - has_pushed_local_surface_id_ = false; + local_surface_id_from_parent_ = local_surface_id_from_parent; + has_pushed_local_surface_id_from_parent_ = false; UpdateDeferCommitsInternal(); SetNeedsCommit(); } @@ -1372,8 +1373,8 @@ tree_impl->set_content_source_id(content_source_id_); - tree_impl->SetLocalSurfaceId(local_surface_id_); - has_pushed_local_surface_id_ = true; + tree_impl->SetLocalSurfaceIdFromParent(local_surface_id_from_parent_); + has_pushed_local_surface_id_from_parent_ = true; if (pending_page_scale_animation_) { tree_impl->SetPendingPageScaleAnimation(
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 9673b70..7954f931 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -292,9 +292,10 @@ return event_listener_properties_[static_cast<size_t>(event_class)]; } - void SetViewportSizeAndScale(const gfx::Size& device_viewport_size, - float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id); + void SetViewportSizeAndScale( + const gfx::Size& device_viewport_size, + float device_scale_factor, + const viz::LocalSurfaceId& local_surface_id_from_parent); void SetViewportVisibleRect(const gfx::Rect& visible_rect); @@ -337,9 +338,10 @@ // If this LayerTreeHost needs a valid viz::LocalSurfaceId then commits will // be deferred until a valid viz::LocalSurfaceId is provided. - void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id); - const viz::LocalSurfaceId& local_surface_id() const { - return local_surface_id_; + void SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent); + const viz::LocalSurfaceId& local_surface_id_from_parent() const { + return local_surface_id_from_parent_; } void SetRasterColorSpace(const gfx::ColorSpace& raster_color_space); @@ -636,9 +638,9 @@ gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; - viz::LocalSurfaceId local_surface_id_; + viz::LocalSurfaceId local_surface_id_from_parent_; // Used to detect surface invariant violations. - bool has_pushed_local_surface_id_ = false; + bool has_pushed_local_surface_id_from_parent_ = false; bool defer_commits_ = false; SkColor background_color_ = SK_ColorWHITE;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index a8772a5c3..86208aee 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -929,12 +929,14 @@ // If we have a new LocalSurfaceId, we must always submit a CompositorFrame // because the parent is blocking on us. - bool local_surface_id_changed = - last_draw_local_surface_id_ != active_tree->local_surface_id(); + bool local_surface_id_from_parent_changed = + last_draw_local_surface_id_ != + active_tree->local_surface_id_from_parent(); return root_surface_has_visible_damage || active_tree_->property_trees()->effect_tree.HasCopyRequests() || - must_always_swap || hud_wants_to_draw_ || local_surface_id_changed; + must_always_swap || hud_wants_to_draw_ || + local_surface_id_from_parent_changed; } DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { @@ -1895,8 +1897,8 @@ metadata.device_scale_factor = active_tree_->painted_device_scale_factor() * active_tree_->device_scale_factor(); metadata.viewport_size_in_pixels = device_viewport_size(); - if (active_tree()->local_surface_id().is_valid()) - metadata.local_surface_id = active_tree()->local_surface_id(); + if (active_tree()->local_surface_id_from_parent().is_valid()) + metadata.local_surface_id = active_tree()->local_surface_id_from_parent(); active_tree_->GetViewportSelection(&metadata.selection); metadata.is_mobile_optimized = IsMobileOptimized(active_tree_.get()); @@ -2028,11 +2030,11 @@ // LocalSurfaceId might slip through, but single-thread-without-scheduler // mode is only used in tests so it doesn't matter. CHECK(!settings_.single_thread_proxy_scheduler || - active_tree()->local_surface_id().is_valid()); + active_tree()->local_surface_id_from_parent().is_valid()); layer_tree_frame_sink_->SetLocalSurfaceId( - active_tree()->local_surface_id()); + active_tree()->local_surface_id_from_parent()); } - last_draw_local_surface_id_ = active_tree()->local_surface_id(); + last_draw_local_surface_id_ = active_tree()->local_surface_id_from_parent(); if (const char* client_name = GetClientNameForMetrics()) { size_t total_quad_count = 0; for (const auto& pass : compositor_frame.render_pass_list) @@ -3187,9 +3189,15 @@ scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; if (!scrolling_node) { - scroll_status.thread = SCROLL_IGNORED; - if (settings_.is_layer_tree_for_subframe) + if (settings_.is_layer_tree_for_subframe) { + TRACE_EVENT_INSTANT0("cc", "Ignored - No ScrollNode (OOPIF)", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; + } else { + TRACE_EVENT_INSTANT0("cc", "Ignroed - No ScrollNode", + TRACE_EVENT_SCOPE_THREAD); + scroll_status.thread = SCROLL_IGNORED; + } scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNoScrollingLayer; return scroll_status; @@ -3211,6 +3219,8 @@ // If the CurrentlyScrollingNode doesn't exist after distributing scroll // delta, no scroller can scroll in the given delta hint direction(s). if (!active_tree_->CurrentlyScrollingNode()) { + TRACE_EVENT_INSTANT0("cc", "Ignored - Didnt Scroll", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = InputHandler::SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3270,6 +3280,7 @@ if (layer_impl) { if (!IsInitialScrollHitTestReliable(layer_impl, device_viewport_point)) { + TRACE_EVENT_INSTANT0("cc", "Failed Hit Test", TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kFailedHitTest; @@ -3336,6 +3347,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( ScrollState* scroll_state) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollAnimatedBegin"); InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3347,6 +3359,8 @@ if (ScrollAnimationUpdateTarget(scroll_node, delta, base::TimeDelta())) { scroll_status.thread = SCROLL_ON_IMPL_THREAD; } else { + TRACE_EVENT_INSTANT0("cc", "Failed to create animation", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3436,6 +3450,7 @@ const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta, base::TimeDelta delayed_by) { + TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollAnimated"); InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; @@ -3462,6 +3477,8 @@ if (ScrollAnimationUpdateTarget(scroll_node, delta, delayed_by)) { scroll_status.thread = SCROLL_ON_IMPL_THREAD; } else { + TRACE_EVENT_INSTANT0("cc", "Failed to update animation", + TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollable; @@ -3991,6 +4008,9 @@ void LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset( const gfx::ScrollOffset& root_offset) { + TRACE_EVENT2("cc", + "LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset", + "offset_x", root_offset.x(), "offset_y", root_offset.y()); bool changed = active_tree_->DistributeRootScrollOffset(root_offset); if (!changed) return;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index a4afbc7..f97dd57 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -180,7 +180,7 @@ } void DidActivateSyncTree() override { // Make sure the active tree always has a valid LocalSurfaceId. - host_impl_->active_tree()->SetLocalSurfaceId( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); } void WillPrepareTiles() override {} @@ -242,7 +242,7 @@ bool init = host_impl_->InitializeRenderer(layer_tree_frame_sink_.get()); host_impl_->SetViewportSize(gfx::Size(10, 10)); host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); - host_impl_->active_tree()->SetLocalSurfaceId( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); // Set the viz::BeginFrameArgs so that methods which use it are able to. host_impl_->WillBeginImplFrame(viz::CreateBeginFrameArgsForTesting( @@ -3532,7 +3532,7 @@ host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); host_impl_->active_tree()->HandleScrollbarShowRequestsFromMain(); - host_impl_->active_tree()->SetLocalSurfaceId( + host_impl_->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); DrawFrame(); @@ -9081,7 +9081,7 @@ root->test_properties()->AddChild(std::move(child)); layer_tree_host_impl->active_tree()->SetRootLayerForTesting(std::move(root)); layer_tree_host_impl->active_tree()->BuildPropertyTreesForTesting(); - layer_tree_host_impl->active_tree()->SetLocalSurfaceId( + layer_tree_host_impl->active_tree()->SetLocalSurfaceIdFromParent( viz::LocalSurfaceId(1, base::UnguessableToken::Deserialize(2u, 3u))); TestFrameData frame;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 34cc3a3..e35e5eb8 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2242,7 +2242,7 @@ // a second commit as a result. layer_tree_host()->SetViewportSizeAndScale( layer_tree_host()->device_viewport_size(), 4.f, - layer_tree_host()->local_surface_id()); + layer_tree_host()->local_surface_id_from_parent()); break; default: // No extra commits. @@ -2287,7 +2287,7 @@ if (layer_tree_host()->SourceFrameNumber() == 1) { layer_tree_host()->SetViewportSizeAndScale( layer_tree_host()->device_viewport_size(), 4.f, - layer_tree_host()->local_surface_id()); + layer_tree_host()->local_surface_id_from_parent()); } } @@ -8012,7 +8012,7 @@ DrawResult draw_result) override { EXPECT_EQ(DRAW_SUCCESS, draw_result); EXPECT_EQ(expected_local_surface_id_, - host_impl->active_tree()->local_surface_id()); + host_impl->active_tree()->local_surface_id_from_parent()); return draw_result; }
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 1da7d9f..642763b 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -469,7 +469,7 @@ target_tree->set_content_source_id(content_source_id()); - target_tree->SetLocalSurfaceId(local_surface_id()); + target_tree->SetLocalSurfaceIdFromParent(local_surface_id_from_parent()); target_tree->pending_page_scale_animation_ = std::move(pending_page_scale_animation_); @@ -963,11 +963,11 @@ host_impl_->SetNeedUpdateGpuRasterizationStatus(); } -void LayerTreeImpl::SetLocalSurfaceId( - const viz::LocalSurfaceId& local_surface_id) { +void LayerTreeImpl::SetLocalSurfaceIdFromParent( + const viz::LocalSurfaceId& local_surface_id_from_parent) { CHECK(!settings().enable_surface_synchronization || !viewport_size_invalid_ || - local_surface_id_ != local_surface_id); - local_surface_id_ = local_surface_id; + local_surface_id_from_parent_ != local_surface_id_from_parent); + local_surface_id_from_parent_ = local_surface_id_from_parent; } void LayerTreeImpl::SetRasterColorSpace(
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index de485a9..f2fac6a5 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -298,9 +298,9 @@ void set_content_source_id(uint32_t id) { content_source_id_ = id; } uint32_t content_source_id() { return content_source_id_; } - void SetLocalSurfaceId(const viz::LocalSurfaceId& id); - const viz::LocalSurfaceId& local_surface_id() const { - return local_surface_id_; + void SetLocalSurfaceIdFromParent(const viz::LocalSurfaceId& id); + const viz::LocalSurfaceId& local_surface_id_from_parent() const { + return local_surface_id_from_parent_; } void SetRasterColorSpace(int raster_color_space_id, @@ -605,7 +605,7 @@ gfx::ColorSpace raster_color_space_; uint32_t content_source_id_; - viz::LocalSurfaceId local_surface_id_; + viz::LocalSurfaceId local_surface_id_from_parent_; scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_;
diff --git a/chrome/VERSION b/chrome/VERSION index be6f264..a8f5a7e 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=68 MINOR=0 -BUILD=3425 +BUILD=3426 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 7b7ceed8..72621a5 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -858,7 +858,6 @@ ":chrome_jni_for_test_registration($default_toolchain)", "//base/test:test_support", "//components/heap_profiling:test_support", - "//content/public/test/android:content_native_test_support", ] } @@ -1124,7 +1123,6 @@ } deps = [ "//components/heap_profiling:heap_profiling_java_test_support", - "//content/public/test/android:content_java_test_support", ] }
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index b83bd56..93dae039 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -57,10 +57,13 @@ "*ic_file_download_white*", # Bottom edge seems misaligned. "*ic_lock.*", # Bottom edge seems misaligned. ] - _native_lib_file = - rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) - native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" - native_lib_version_rule = "//build/util:chrome_version_json" + + if (defined(shared_libraries) && shared_libraries != []) { + _native_lib_file = + rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) + native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" + native_lib_version_rule = "//build/util:chrome_version_json" + } if (!defined(aapt_locale_whitelist)) { aapt_locale_whitelist = locales - android_chrome_omitted_locales }
diff --git a/chrome/android/java/res/anim/fast_out_slow_in_interpolator.xml b/chrome/android/java/res/anim/fast_out_slow_in_interpolator.xml new file mode 100644 index 0000000..043aa21 --- /dev/null +++ b/chrome/android/java/res/anim/fast_out_slow_in_interpolator.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:controlX1="0.4" + android:controlY1="0" + android:controlX2="0.2" + android:controlY2="1" + tools:targetApi="21"/>
diff --git a/chrome/android/java/res/drawable-hdpi/btn_settings.png b/chrome/android/java/res/drawable-hdpi/btn_settings.png new file mode 100644 index 0000000..110af6e --- /dev/null +++ b/chrome/android/java/res/drawable-hdpi/btn_settings.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_settings.png b/chrome/android/java/res/drawable-mdpi/btn_settings.png new file mode 100644 index 0000000..4512431 --- /dev/null +++ b/chrome/android/java/res/drawable-mdpi/btn_settings.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_settings.png b/chrome/android/java/res/drawable-xhdpi/btn_settings.png new file mode 100644 index 0000000..0584aaaf --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/btn_settings.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_settings.png b/chrome/android/java/res/drawable-xxhdpi/btn_settings.png new file mode 100644 index 0000000..ba6e4803 --- /dev/null +++ b/chrome/android/java/res/drawable-xxhdpi/btn_settings.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_settings.png b/chrome/android/java/res/drawable-xxxhdpi/btn_settings.png new file mode 100644 index 0000000..786191c --- /dev/null +++ b/chrome/android/java/res/drawable-xxxhdpi/btn_settings.png Binary files differ
diff --git a/chrome/android/java/res/drawable/signin_header_animation.xml b/chrome/android/java/res/drawable/signin_header_animation.xml index badebed..459d307f 100644 --- a/chrome/android/java/res/drawable/signin_header_animation.xml +++ b/chrome/android/java/res/drawable/signin_header_animation.xml
@@ -135,17 +135,18 @@ </vector> </aapt:attr> <!-- Each animation here has a period of 10.45 seconds. Animation is restarted from the code. --> - <!-- Light grey circle --> <target android:name="cloud1_animation_group"> <aapt:attr name="android:animation"> <set android:ordering="sequentially"> <objectAnimator android:duration="3900" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="0" android:valueTo="-3.24"/> <objectAnimator android:duration="6550" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="-3.24" android:valueTo="0"/> @@ -157,11 +158,13 @@ <set android:ordering="sequentially"> <objectAnimator android:duration="4650" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="0" android:valueTo="-2.16"/> <objectAnimator android:duration="5800" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="-2.16" android:valueTo="0"/> @@ -173,11 +176,13 @@ <set android:ordering="sequentially"> <objectAnimator android:duration="6150" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="0" android:valueTo="-5.04"/> <objectAnimator android:duration="4300" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="-5.04" android:valueTo="0"/> @@ -189,11 +194,13 @@ <set android:ordering="sequentially"> <objectAnimator android:duration="5550" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="0" android:valueTo="5.04"/> <objectAnimator android:duration="4900" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="translateX" android:valueFrom="5.04" android:valueTo="0"/> @@ -205,23 +212,27 @@ <set android:ordering="sequentially"> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:valueFrom="0" android:valueTo="-360"/> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:startOffset="1900" android:valueFrom="0" android:valueTo="-360"/> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:startOffset="1900" android:valueFrom="0" android:valueTo="-360"/> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:startOffset="1900" android:valueFrom="0" @@ -234,6 +245,7 @@ <set android:ordering="sequentially"> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:valueFrom="-120" android:valueTo="120"/> @@ -244,6 +256,7 @@ android:valueTo="120"/> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:valueFrom="120" android:valueTo="-120"/> @@ -254,6 +267,7 @@ android:valueTo="-120"/> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:valueFrom="-120" android:valueTo="120"/> @@ -264,6 +278,7 @@ android:valueTo="120"/> <objectAnimator android:duration="700" + android:interpolator="@anim/fast_out_slow_in_interpolator" android:propertyName="rotation" android:valueFrom="120" android:valueTo="-120"/>
diff --git a/chrome/android/java/res/menu/download_manager_menu.xml b/chrome/android/java/res/menu/download_manager_menu.xml index 8292553e..962c956 100644 --- a/chrome/android/java/res/menu/download_manager_menu.xml +++ b/chrome/android/java/res/menu/download_manager_menu.xml
@@ -29,29 +29,18 @@ <group android:id="@+id/with_settings_normal_menu_group" android:visible="false" > <item + android:id="@+id/settings_menu_id" + android:icon="@drawable/btn_settings" + android:title="@string/preferences" + android:visible="false" + chrome:showAsAction="ifRoom" /> + <item android:id="@+id/with_settings_search_menu_id" android:icon="@drawable/ic_search" android:title="@string/search" android:visible="false" chrome:showAsAction="ifRoom" /> <item - android:id="@+id/extra_menu_id" - android:icon="@drawable/ic_more_vert_black_24dp" - android:title="" - chrome:showAsAction="ifRoom" > - <menu> - <item - android:id="@+id/with_settings_info_menu_id" - android:title="@string/download_manager_ui_show_storage" - android:visible="false" - chrome:showAsAction="never" /> - <item - android:id="@+id/settings_menu_id" - android:title="@string/preferences" - chrome:showAsAction="never" /> - </menu> - </item> - <item android:id="@+id/with_settings_close_menu_id" android:icon="@drawable/btn_close" android:title="@string/close"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index dcd923d..a398a8f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -166,8 +166,6 @@ public static final String CHROME_HOME = "ChromeHome"; public static final String CHROME_HOME_DROP_ALL_BUT_FIRST_THUMBNAIL = "ChromeHomeDropAllButFirstThumbnail"; - public static final String CHROME_HOME_MENU_ITEMS_EXPAND_SHEET = - "ChromeHomeMenuItemsExpandSheet"; public static final String CHROME_HOME_PERSISTENT_IPH = "ChromeHomePersistentIph"; public static final String CHROME_HOME_PULL_TO_REFRESH_IPH_AT_TOP = "ChromeHomePullToRefreshIphAtTop";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index a91a42c1..527b081 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -25,7 +25,6 @@ import android.util.Pair; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; -import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; @@ -1499,23 +1498,6 @@ @Override public View getHeaderView() { - // Return early if Chrome Home is not enabled. - if (getBottomSheet() == null) return null; - - boolean isPageMenu = getAppMenuPropertiesDelegate().shouldShowPageMenu(); - - // Return early if the conditions aren't right to show the Chrome Home IPH menu - // header. - if (mControlContainer.getVisibility() != View.VISIBLE - || getBottomSheet().isSheetOpen() || !isPageMenu - || AppMenuPropertiesDelegate.shouldShowNavMenuItems()) { - return null; - } - - LayoutInflater inflater = LayoutInflater.from(ChromeTabbedActivity.this); - Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile()); - - // Default is no header. return null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java index f28b13f..a0072fc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser; import android.os.Bundle; +import android.support.annotation.CallSuper; import android.support.v7.app.AppCompatActivity; import org.chromium.base.Log; @@ -22,6 +23,7 @@ public abstract class SynchronousInitializationActivity extends AppCompatActivity { private static final String TAG = "SyncInitActivity"; + @CallSuper @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java index 63cd081..73d1e970 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -20,11 +20,9 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; -import org.chromium.base.StrictModeContext; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.UrlConstants; @@ -33,12 +31,10 @@ import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.share.ShareHelper; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.webapk.lib.client.WebApkValidator; @@ -49,24 +45,6 @@ * App Menu helper that handles hiding and showing menu items based on activity state. */ public class AppMenuPropertiesDelegate { - /** - * The param name for the "ChromeHomeMenuItemsExpandSheet" experiment. This specifies the number - * of times a menu item can be tapped before being hidden. - */ - private static final String CHROME_HOME_MENU_ITEM_TAP_PARAM_NAME = "max_taps"; - - /** - * The number of times that bookmarks, downloads, and history can be triggered from the overflow - * menu in Chrome Home before they are hidden. - */ - private static final int CHROME_HOME_MENU_ITEM_TAP_MAX = 10; - - /** - * Whether or not the Chrome Home menu items should be hidden because they have been tapped the - * maximum number of times. - */ - private static boolean sHideChromeHomeMenuItems; - protected MenuItem mReloadMenuItem; protected final ChromeActivity mActivity; @@ -221,13 +199,6 @@ // Only display the Enter VR button if VR Shell Dev environment is enabled. menu.findItem(R.id.enter_vr_id).setVisible( CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_VR_SHELL_DEV)); - - if (!shouldShowNavMenuItems()) { - // History, downloads, and bookmarks are shown in the Chrome Home bottom sheet. - menu.findItem(R.id.open_history_menu_id).setVisible(false); - menu.findItem(R.id.downloads_menu_id).setVisible(false); - menu.findItem(R.id.all_bookmarks_menu_id).setVisible(false); - } } if (isOverviewMenu) { @@ -441,32 +412,4 @@ ? mActivity.getString(R.string.menu_request_desktop_site_on) : mActivity.getString(R.string.menu_request_desktop_site_off)); } - - /** - * @return Whether bookmarks, downloads, and history should be shown in the menu. - */ - public static boolean shouldShowNavMenuItems() { - if (!FeatureUtilities.isChromeHomeEnabled()) return true; - - try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { - int maxTapCount = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( - ChromeFeatureList.CHROME_HOME_MENU_ITEMS_EXPAND_SHEET, - CHROME_HOME_MENU_ITEM_TAP_PARAM_NAME, CHROME_HOME_MENU_ITEM_TAP_MAX); - - sHideChromeHomeMenuItems = sHideChromeHomeMenuItems - || ChromePreferenceManager.getInstance().getChromeHomeMenuItemClickCount() - >= maxTapCount; - } - - boolean chromeHomeMenuItemFlagEnabled = ChromeFeatureList.isInitialized() - && ChromeFeatureList.isEnabled( - ChromeFeatureList.CHROME_HOME_MENU_ITEMS_EXPAND_SHEET); - - // If Chrome Home or the menu item feature is disabled, clear the menu tap preference. - if (!chromeHomeMenuItemFlagEnabled) { - ChromePreferenceManager.getInstance().clearChromeHomeMenuItemClickCount(); - } - - return chromeHomeMenuItemFlagEnabled && !sHideChromeHomeMenuItems; - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java index 1060101..03068d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
@@ -318,7 +318,7 @@ } @CalledByNative - private void didSwapBuffers() { + private void didSwapBuffers(boolean swappedCurrentSize) { // If we're in the middle of a surface swap, then see if we've received a new frame yet for // the new surface before hiding the outgoing surface. if (mFramesUntilHideBackground > 1) { @@ -333,7 +333,10 @@ mCompositorSurfaceManager.doneWithUnownedSurface(); } - runDrawFinishedCallbacks(); + // Only run our draw finished callbacks if the frame we swapped was the correct size. + if (swappedCurrentSize) { + runDrawFinishedCallbacks(); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java index 0d5443f..53a5475 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
@@ -11,10 +11,10 @@ import android.support.annotation.IntDef; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.animation.Interpolator; import android.widget.FrameLayout; import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.LayerTitleCache; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable; @@ -38,10 +38,8 @@ import org.chromium.chrome.browser.tabmodel.TabList; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelUtils; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.ui.base.LocalizationUtils; -import org.chromium.ui.interpolators.BakedBezierInterpolator; import org.chromium.ui.resources.ResourceManager; import java.io.Serializable; @@ -89,9 +87,6 @@ private static final int FLING_MIN_DURATION = 100; // ms private static final float THRESHOLD_TO_SWITCH_STACK = 0.4f; - private static final int NEW_TAB_ANIMATION_DURATION_MS = 300; - - public static final int MODERN_TOP_MARGIN_DP = 16; /** * The delta time applied on the velocity from the fling. This is to compute the kick to help @@ -99,6 +94,12 @@ */ private static final float SWITCH_STACK_FLING_DT = 1.0f / 30.0f; + /** + * True if this is currently the active layout and startHiding() has not yet been called, false + * otherwise. + */ + protected boolean mIsActiveLayout; + /** The list of potentially visible stacks. */ protected final ArrayList<Stack> mStacks; @@ -151,6 +152,9 @@ private static final int LAYOUTTAB_ASYNCHRONOUS_INITIALIZATION_BATCH_SIZE = 4; private boolean mDelayedLayoutTabInitRequired; + /** Which model (normal or incognito) was active when StackLayout was shown. */ + private int mModelIndexWhenOpened; + /** * Temporarily stores the index of the selected tab stack. This is used to set the currently * selected stack in TabModelSelector once the stack-switching animation finishes. @@ -168,15 +172,6 @@ private StackLayoutGestureHandler mGestureHandler; - /** A {@link LayoutTab} used for new tab animations. */ - private LayoutTab mNewTabLayoutTab; - - /** - * Whether or not the new layout tab has been properly initialized (a frame can occur between - * creation and initialization). - */ - private boolean mIsNewTabInitialized; - private class StackLayoutGestureHandler implements GestureHandler { @Override public void onDown(float x, float y, boolean fromMouse, int buttons) { @@ -441,6 +436,22 @@ @Override public void onTabSelecting(long time, int tabId) { + // We update TabModelSelector's current model when incognito mode is toggled in the tab + // switcher. So the "current model index" is already the one that we're leaving active when + // the tab switcher is closed. + final int newModelIndex = mTabModelSelector.getCurrentModelIndex(); + if (newModelIndex != mModelIndexWhenOpened) { + final int indexInNewModel = mTabModelSelector.getCurrentModel().index(); + if (indexInNewModel == mTabModelSelector.getCurrentModel().index()) { + // TabModelImpl logs this action when we switch to a different index within a + // TabModelImpl. If we switch between TabModelImpls (i.e. switch between normal and + // incognito mode), but leave the index the same (i.e. switch back to the most + // recently active tab in that stack), TabModelImpl doesn't catch that case, so we + // log it here. + RecordUserAction.record("MobileTabSwitched"); + } + } + commitOutstandingModelState(time); if (tabId == Tab.INVALID_TAB_ID) tabId = mTabModelSelector.getCurrentTabId(); super.onTabSelecting(time, tabId); @@ -535,23 +546,14 @@ startHiding(id, false); mStacks.get(getTabStackIndex(id)).tabCreated(time, id); - if (FeatureUtilities.isChromeHomeEnabled()) { - mNewTabLayoutTab = createLayoutTab(id, newIsIncognito, NO_CLOSE_BUTTON, NO_TITLE); - mNewTabLayoutTab.setScale(1.f); - mNewTabLayoutTab.setBorderScale(1.f); - mNewTabLayoutTab.setDecorationAlpha(0.f); - mNewTabLayoutTab.setY(getHeight() / 2); - - mIsNewTabInitialized = true; - - Interpolator interpolator = BakedBezierInterpolator.TRANSFORM_CURVE; - addToAnimation(mNewTabLayoutTab, LayoutTab.Property.Y, mNewTabLayoutTab.getY(), 0.f, - NEW_TAB_ANIMATION_DURATION_MS, 0, false, interpolator); - } else { - startMarginAnimation(false); - } + startMarginAnimation(false); } + // This method is called if the following sequence of operations occurs: + // 1. Enter multi-window mode + // 2. Create a second Chrome instance by moving a tab to the other window + // 3. In the top window, enter the tab switcher + // 4. Expand the top window to full screen. @Override public void onTabRestored(long time, int tabId) { super.onTabRestored(time, tabId); @@ -593,10 +595,6 @@ @Override protected void onAnimationFinished() { if (mStackAnimationCount == 0) super.onAnimationFinished(); - if (mNewTabLayoutTab != null) { - mIsNewTabInitialized = false; - mNewTabLayoutTab = null; - } } /** @@ -693,6 +691,21 @@ public void show(long time, boolean animate) { super.show(time, animate); + if (!mIsActiveLayout) { + // The mIsActiveLayout check is necessary because there are certain edge cases where + // show() is called (e.g. to refresh the Stacks) while the tab switcher is already + // showing. + + // Note: there are some edge cases (e.g. the last open tab is closed somehow while the + // tab switcher is not open) that can also cause this event to be logged without a + // toolbar interaction. The event name contains "Toolbar" for historical reasons; the + // current intent is to log whenever the tab switcher is entered. + RecordUserAction.record("MobileToolbarShowStackView"); + + mModelIndexWhenOpened = mTabModelSelector.getCurrentModelIndex(); + } + mIsActiveLayout = true; + Tab tab = mTabModelSelector.getCurrentTab(); if (tab != null && tab.isNativePage()) mTabContentManager.cacheTabThumbnail(tab); @@ -942,7 +955,6 @@ } float getTopHeightOffset() { - if (FeatureUtilities.isChromeHomeEnabled()) return MODERN_TOP_MARGIN_DP; return getTopBrowserControlsHeight() * mStackOffsetYPercent; } } @@ -1147,12 +1159,10 @@ tabVisibleCount += mStacks.get(i).getVisibleCount(); } - int layoutTabCount = tabVisibleCount + (mNewTabLayoutTab == null ? 0 : 1); - - if (layoutTabCount == 0) { + if (tabVisibleCount == 0) { mLayoutTabs = null; - } else if (mLayoutTabs == null || mLayoutTabs.length != layoutTabCount) { - mLayoutTabs = new LayoutTab[layoutTabCount]; + } else if (mLayoutTabs == null || mLayoutTabs.length != tabVisibleCount) { + mLayoutTabs = new LayoutTab[tabVisibleCount]; } int index = 0; @@ -1169,11 +1179,6 @@ if (mLayoutTabs[i].updateSnap(dt)) needUpdate = true; } - if (mNewTabLayoutTab != null && mIsNewTabInitialized) { - mLayoutTabs[mLayoutTabs.length - 1] = mNewTabLayoutTab; - if (mNewTabLayoutTab.updateSnap(dt)) needUpdate = true; - } - if (needUpdate) requestUpdate(); // Since we've updated the positions of the stacks and tabs, let's go ahead and update @@ -1219,6 +1224,15 @@ } @Override + public void startHiding(int nextTabId, boolean hintAtTabSelection) { + // Reset mIsActiveLayout here instead of in doneHiding() so if a user hits the tab switcher + // button on the toolbar to re-open it while we're still in the process of hiding the tab + // switcher, we don't skip the logging. + super.startHiding(nextTabId, hintAtTabSelection); + mIsActiveLayout = false; + } + + @Override public void doneHiding() { super.doneHiding();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java index 4baef34e..69eee007 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
@@ -25,7 +25,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabList; import org.chromium.chrome.browser.tabmodel.TabModelUtils; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.ui.base.LocalizationUtils; @@ -404,12 +403,10 @@ * @param id The id of the new tab to animate. */ public void tabCreated(long time, int id) { - if (!FeatureUtilities.isChromeHomeEnabled()) { - if (!createTabHelper(id)) return; - mIsDying = false; + if (!createTabHelper(id)) return; + mIsDying = false; - finishAnimation(time); - } + finishAnimation(time); startAnimation(time, OverviewAnimationType.NEW_TAB_OPENED, TabModelUtils.getTabIndexById(mTabList, id), TabList.INVALID_TAB_INDEX, false); } @@ -2008,7 +2005,7 @@ LayoutTab layoutTab = mLayout.createLayoutTab(tabId, isIncognito, Layout.SHOW_CLOSE_BUTTON, needTitle, maxContentWidth, maxContentHeight); layoutTab.setInsetBorderVertical(true); - layoutTab.setShowToolbar(!FeatureUtilities.isChromeHomeEnabled()); + layoutTab.setShowToolbar(true); layoutTab.setToolbarAlpha(0.f); layoutTab.setAnonymizeToolbar(!mIsStackForCurrentTabList || mTabList.index() != i); @@ -2280,9 +2277,6 @@ * @return The maximum height of a layout tab in the tab switcher. */ public float getMaxTabHeight() { - if (FeatureUtilities.isChromeHomeEnabled() && mCurrentMode == Orientation.PORTRAIT) { - return mLayout.getHeightMinusBrowserControls() - StackLayoutBase.MODERN_TOP_MARGIN_DP; - } return mLayout.getHeightMinusBrowserControls(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java index f46f95c..35dcab7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape.java
@@ -21,7 +21,6 @@ import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable; import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.ui.base.LocalizationUtils; @@ -129,11 +128,8 @@ set, tab, SCALE, tab.getScale(), 1.0f, TAB_FOCUSED_ANIMATION_DURATION, 0); addAnimation(set, tab, X_IN_STACK_INFLUENCE, tab.getXInStackInfluence(), 0.0f, TAB_FOCUSED_ANIMATION_DURATION, 0); - int tabYInfluenceDuration = FeatureUtilities.isChromeHomeEnabled() - ? TAB_FOCUSED_ANIMATION_DURATION - : TAB_FOCUSED_Y_STACK_DURATION; addAnimation(set, tab, Y_IN_STACK_INFLUENCE, tab.getYInStackInfluence(), 0.0f, - tabYInfluenceDuration, 0); + TAB_FOCUSED_Y_STACK_DURATION, 0); addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT, tab.getLayoutTab().getMaxContentHeight(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java index 3475350..b12c318d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationPortrait.java
@@ -20,7 +20,6 @@ import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable; import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.ui.base.LocalizationUtils; @@ -137,11 +136,8 @@ TAB_FOCUSED_ANIMATION_DURATION, 0); addAnimation( set, tab, SCALE, tab.getScale(), 1.0f, TAB_FOCUSED_ANIMATION_DURATION, 0); - int tabYInfluenceDuration = FeatureUtilities.isChromeHomeEnabled() - ? TAB_FOCUSED_ANIMATION_DURATION - : TAB_FOCUSED_Y_STACK_DURATION; addAnimation(set, tab, Y_IN_STACK_INFLUENCE, tab.getYInStackInfluence(), 0.0f, - tabYInfluenceDuration, 0); + TAB_FOCUSED_Y_STACK_DURATION, 0); addAnimation(set, tab.getLayoutTab(), MAX_CONTENT_HEIGHT, tab.getLayoutTab().getMaxContentHeight(), tab.getLayoutTab().getUnclampedOriginalContentHeight(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java index 5fb023e..201aa37 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java
@@ -192,11 +192,7 @@ @Override public void onSizeChanged( - float width, float height, float visibleViewportOffsetY, int orientation) { - // If Chrome Home is enabled, a size change means the toolbar is now in a different - // location so a render is needed. - if (FeatureUtilities.isChromeHomeEnabled()) mRenderHost.requestRender(); - } + float width, float height, float visibleViewportOffsetY, int orientation) {} @Override public void getVirtualViews(List<VirtualView> views) {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java index d69e6da9..b8420b12 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
@@ -7,6 +7,7 @@ import android.content.Context; import android.support.v7.widget.AppCompatSpinner; import android.util.AttributeSet; +import android.view.MenuItem; import android.view.View; import android.widget.Spinner; @@ -97,9 +98,8 @@ @Override protected void onDataChanged(int numItems) { super.onDataChanged(numItems); - getMenu() - .findItem(mInfoMenuItemId) - .setVisible(!mIsSearching && !mIsSelectionEnabled && numItems > 0); + MenuItem item = getMenu().findItem(mInfoMenuItemId); + if (item != null) item.setVisible(!mIsSearching && !mIsSelectionEnabled && numItems > 0); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java index d39659e3..7fc7459 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -7,6 +7,8 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Intent; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Handler; import android.support.annotation.IntDef; @@ -20,6 +22,7 @@ import android.view.ViewGroup; import android.widget.TextView; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.base.CollectionUtil; import org.chromium.base.DiscardableReferencePool; @@ -222,7 +225,7 @@ * activity than the main Chrome activity. * @param snackbarManager The {@link SnackbarManager} used to display snackbars. */ - @SuppressWarnings("unchecked") // mSelectableListLayout + @SuppressWarnings({"unchecked"}) // mSelectableListLayout public DownloadManagerUi(Activity activity, boolean isOffTheRecord, ComponentName parentComponent, boolean isSeparateActivity, SnackbarManager snackbarManager) { @@ -266,7 +269,7 @@ int normalGroupId = isLocationEnabled ? R.id.with_settings_normal_menu_group : R.id.normal_menu_group; mSearchMenuId = isLocationEnabled ? R.id.with_settings_search_menu_id : R.id.search_menu_id; - mInfoMenuId = isLocationEnabled ? R.id.with_settings_info_menu_id : R.id.info_menu_id; + mInfoMenuId = isLocationEnabled ? 0 : R.id.info_menu_id; mToolbar = (DownloadManagerToolbar) mSelectableListLayout.initializeToolbar( R.layout.download_manager_toolbar, mBackendProvider.getSelectionDelegate(), 0, null, @@ -282,10 +285,11 @@ addObserver(mToolbar); if (isLocationEnabled) { - mToolbar.setExtraMenuItem(R.id.extra_menu_id); - mToolbar.setInfoButtonText(R.string.download_manager_ui_show_storage, - R.string.download_manager_ui_hide_storage); - mToolbar.setShowInfoIcon(false); + // TODO(xingliu): Use the new settings icon with better alpha value. + Drawable settingIcon = mToolbar.getMenu().findItem(R.id.settings_menu_id).getIcon(); + settingIcon.setColorFilter(ApiCompatibilityUtils.getColor(getActivity().getResources(), + R.color.black_alpha_65), + PorterDuff.Mode.SRC_IN); final Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile()); tracker.addOnInitializedCallback( @@ -568,7 +572,7 @@ if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_SETTINGS_FEATURE)) return; // Build and show text bubble. - View anchorView = mToolbar.findViewById(R.id.extra_menu_id); + View anchorView = mToolbar.findViewById(R.id.settings_menu_id); TextBubble textBubble = new TextBubble(mActivity, (View) mToolbar, R.string.iph_download_settings_text, R.string.iph_download_settings_accessibility_text, @@ -583,7 +587,7 @@ } private void toggleHighlightForDownloadSettingsTextBubble(boolean shouldHighlight) { - View view = mToolbar.findViewById(R.id.extra_menu_id); + View view = mToolbar.findViewById(R.id.settings_menu_id); if (shouldHighlight) { ViewHighlighter.turnOnHighlight(view, true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java index c3d0f87..7823930 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java
@@ -10,6 +10,7 @@ import android.view.ViewGroup; import android.widget.TextView; +import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.R; @@ -20,6 +21,9 @@ * continue the redirection by tapping on a link. */ public class FramebustBlockInfoBar extends InfoBar { + /** For Log statements. */ + private static final String TAG = "Framebust Infobar"; + private final String mBlockedUrl; /** Whether the infobar should be shown as a mini-infobar or a classic expanded one. */ @@ -42,6 +46,9 @@ layout.setMessage(getString(R.string.redirect_blocked_message)); InfoBarControlLayout control = layout.addControlLayout(); + // TODO(crbug.com/834959): remove after bug fixed. + Log.i(TAG, "Mark possible occurance of crbug.com/834959"); + ViewGroup ellipsizerView = (ViewGroup) LayoutInflater.from(getContext()) .inflate(R.layout.infobar_control_url_ellipsizer, control, false); @@ -61,7 +68,8 @@ ellipsizerView.setOnClickListener(view -> onLinkClicked()); control.addView(ellipsizerView); - layout.setButtons(getContext().getResources().getString(R.string.got_it), null); + layout.setButtons( + getContext().getResources().getString(R.string.always_allow_redirects), null); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java index 774aff6..5a21cb2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java
@@ -12,7 +12,7 @@ import android.widget.RadioGroup.OnCheckedChangeListener; import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.widget.RadioButtonLayout; import java.util.ArrayList;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java index 8e8c0a97..c15fcaff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java
@@ -26,8 +26,8 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.chrome.browser.preferences.SearchEnginePreference; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.snackbar.Snackbar; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java index 33ba2a2..cc8cc22 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
@@ -22,6 +22,7 @@ import android.widget.RemoteViews; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; @@ -77,6 +78,9 @@ */ private static final int BUTTON_ICON_COLOR_MATERIAL = 0xff757575; + /** For Log statements. */ + private static final String TAG = "Custom Notification"; + private final Context mContext; public CustomNotificationBuilder(Context context) { @@ -116,6 +120,9 @@ StrictMode.setThreadPolicy(oldPolicy); } + // TODO(crbug.com/834959): remove after bug fixed. + Log.i(TAG, "Mark possible occurrence of crbug.com/834959"); + for (RemoteViews view : new RemoteViews[] {compactView, bigView}) { view.setTextViewText(R.id.time, formattedTime); view.setTextViewText(R.id.title, mTitle);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java index 706ce4b..21289a71 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -70,8 +70,6 @@ public static final String CHROME_HOME_INFO_PROMO_SHOWN_KEY = "chrome_home_info_promo_shown"; - private static final String CHROME_HOME_MENU_ITEM_CLICK_COUNT_KEY = - "chrome_home_menu_item_click_count"; private static final String SOLE_INTEGRATION_ENABLED_KEY = "sole_integration_enabled"; private static final String COMMAND_LINE_ON_NON_ROOTED_ENABLED_KEY = @@ -454,30 +452,6 @@ removeKey(CHROME_HOME_OPT_OUT_SNACKBAR_SHOWN); } - /** - * @return The number of times that bookmarks, history, or downloads have been triggered from - * the overflow menu while Chrome Home is enabled. - */ - public int getChromeHomeMenuItemClickCount() { - return readInt(CHROME_HOME_MENU_ITEM_CLICK_COUNT_KEY); - } - - /** - * Increment the count for the number of times bookmarks, history, or downloads have been - * triggered from the overflow menu while Chrome Home is enabled. - */ - public void incrementChromeHomeMenuItemClickCount() { - writeInt(CHROME_HOME_MENU_ITEM_CLICK_COUNT_KEY, getChromeHomeMenuItemClickCount() + 1); - } - - /** - * Remove the count for number of times bookmarks, history, or downloads were clicked while - * Chrome Home is enabled. - */ - public void clearChromeHomeMenuItemClickCount() { - mSharedPreferences.edit().remove(CHROME_HOME_MENU_ITEM_CLICK_COUNT_KEY).apply(); - } - /** Marks that the content suggestions surface has been shown. */ public void setSuggestionsSurfaceShown() { writeBoolean(CONTENT_SUGGESTIONS_SHOWN_KEY, true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java index 4470899..1366f2c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
@@ -21,8 +21,8 @@ import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.preferences.datareduction.DataReductionPreferences; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.base.DeviceFormFactor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java index 6cc2c9b..66dc51fe6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java
@@ -9,6 +9,7 @@ import android.content.res.Resources; import android.os.Build; import android.os.Bundle; +import android.support.annotation.IntDef; import android.support.annotation.StringRes; import android.text.SpannableString; import android.text.TextUtils; @@ -36,14 +37,20 @@ import org.chromium.chrome.browser.preferences.website.NotificationInfo; import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences; import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.components.location.LocationUtils; import org.chromium.ui.text.SpanApplier; import org.chromium.ui.text.SpanApplier.SpanInfo; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; import java.util.List; +import java.util.concurrent.TimeUnit; /** * A custom adapter for listing search engines. @@ -57,6 +64,20 @@ private static final int VIEW_TYPE_DIVIDER = 1; private static final int VIEW_TYPE_COUNT = 2; + public static final int MAX_RECENT_ENGINE_NUM = 3; + public static final long MAX_DISPLAY_TIME_SPAN_MS = TimeUnit.DAYS.toMillis(2); + + /** + * Type for source of search engine. This is needed because if a custom search engine is set as + * default, it will be moved to the prepopulated list. + */ + @IntDef({TYPE_DEFAULT, TYPE_PREPOPULATED, TYPE_RECENT}) + @Retention(RetentionPolicy.SOURCE) + public @interface TemplateUrlSourceType {} + public static final int TYPE_DEFAULT = 0; + public static final int TYPE_PREPOPULATED = 1; + public static final int TYPE_RECENT = 2; + /** The current context. */ private Context mContext; @@ -139,7 +160,10 @@ return; // Flow continues in onTemplateUrlServiceLoaded below. } - List<TemplateUrl> templateUrls = templateUrlService.getSearchEngines(); + List<TemplateUrl> templateUrls = templateUrlService.getTemplateUrls(); + TemplateUrl defaultSearchEngineTemplateUrl = + templateUrlService.getDefaultSearchEngineTemplateUrl(); + sortAndFilterUnnecessaryTemplateUrl(templateUrls, defaultSearchEngineTemplateUrl); boolean forceRefresh = mIsLocationPermissionChanged; mIsLocationPermissionChanged = false; if (!didSearchEnginesChange(templateUrls)) { @@ -152,27 +176,24 @@ for (int i = 0; i < templateUrls.size(); i++) { TemplateUrl templateUrl = templateUrls.get(i); - if (templateUrl.getType() == TemplateUrlService.TYPE_PREPOPULATED - || templateUrl.getType() == TemplateUrlService.TYPE_DEFAULT) { - mPrepopulatedSearchEngines.add(templateUrl); - } else { + if (getSearchEngineSourceType(templateUrl, defaultSearchEngineTemplateUrl) + == TYPE_RECENT) { mRecentSearchEngines.add(templateUrl); + } else { + mPrepopulatedSearchEngines.add(templateUrl); } } - int defaultSearchEngineIndex = - TemplateUrlService.getInstance().getDefaultSearchEngineIndex(); - // Convert the TemplateUrl index into an index of mSearchEngines. mSelectedSearchEnginePosition = -1; for (int i = 0; i < mPrepopulatedSearchEngines.size(); ++i) { - if (mPrepopulatedSearchEngines.get(i).getIndex() == defaultSearchEngineIndex) { + if (mPrepopulatedSearchEngines.get(i).equals(defaultSearchEngineTemplateUrl)) { mSelectedSearchEnginePosition = i; } } for (int i = 0; i < mRecentSearchEngines.size(); ++i) { - if (mRecentSearchEngines.get(i).getIndex() == defaultSearchEngineIndex) { + if (mRecentSearchEngines.get(i).equals(defaultSearchEngineTemplateUrl)) { // Add one to offset the title for the recent search engine list. mSelectedSearchEnginePosition = i + computeStartIndexForRecentSearchEngines(); } @@ -188,11 +209,62 @@ notifyDataSetChanged(); } + public static void sortAndFilterUnnecessaryTemplateUrl( + List<TemplateUrl> templateUrls, TemplateUrl defaultSearchEngine) { + Collections.sort(templateUrls, new Comparator<TemplateUrl>() { + @Override + public int compare(TemplateUrl templateUrl1, TemplateUrl templateUrl2) { + if (templateUrl1.getIsPrepopulated() && templateUrl2.getIsPrepopulated()) { + return templateUrl1.getPrepopulatedId() - templateUrl2.getPrepopulatedId(); + } else if (templateUrl1.getIsPrepopulated()) { + return -1; + } else if (templateUrl2.getIsPrepopulated()) { + return 1; + } else if (templateUrl1.equals(templateUrl2)) { + return 0; + } else if (templateUrl1.equals(defaultSearchEngine)) { + return -1; + } else if (templateUrl2.equals(defaultSearchEngine)) { + return 1; + } else { + return ApiCompatibilityUtils.compareLong( + templateUrl2.getLastVisitedTime(), templateUrl1.getLastVisitedTime()); + } + } + }); + int recentEngineNum = 0; + long displayTime = System.currentTimeMillis() - MAX_DISPLAY_TIME_SPAN_MS; + Iterator<TemplateUrl> iterator = templateUrls.iterator(); + while (iterator.hasNext()) { + TemplateUrl templateUrl = iterator.next(); + if (getSearchEngineSourceType(templateUrl, defaultSearchEngine) != TYPE_RECENT) { + continue; + } + if (recentEngineNum < MAX_RECENT_ENGINE_NUM + && templateUrl.getLastVisitedTime() > displayTime) { + recentEngineNum++; + } else { + iterator.remove(); + } + } + } + + private static @TemplateUrlSourceType int getSearchEngineSourceType( + TemplateUrl templateUrl, TemplateUrl defaultSearchEngine) { + if (templateUrl.getIsPrepopulated()) { + return TYPE_PREPOPULATED; + } else if (templateUrl.equals(defaultSearchEngine)) { + return TYPE_DEFAULT; + } else { + return TYPE_RECENT; + } + } + private static boolean containsTemplateUrl( List<TemplateUrl> templateUrls, TemplateUrl targetTemplateUrl) { for (int i = 0; i < templateUrls.size(); i++) { TemplateUrl templateUrl = templateUrls.get(i); - // Explicitly excluding TemplateUrlType and Index as they might change if a search + // Explicitly excluding TemplateUrlSourceType and Index as they might change if a search // engine is set as default. if (templateUrl.getIsPrepopulated() == targetTemplateUrl.getIsPrepopulated() && TextUtils.equals(templateUrl.getKeyword(), targetTemplateUrl.getKeyword())
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java index 6d22897..daa86443 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java
@@ -151,9 +151,9 @@ R.string.website_settings_category_notifications_ask, 0)); localMap.put(ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS, new ResourceItem(R.drawable.permission_popups, R.string.popup_permission_title, - R.string.popup_permission_title, ContentSetting.ALLOW, - ContentSetting.BLOCK, 0, - R.string.website_settings_category_popups_blocked)); + R.string.popup_permission_title, ContentSetting.ALLOW, + ContentSetting.BLOCK, 0, + R.string.website_settings_category_popups_redirects_blocked)); localMap.put(ContentSettingsType.CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, new ResourceItem(R.drawable.permission_protected_media, org.chromium.chrome.R.string.protected_content,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrl.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrl.java new file mode 100644 index 0000000..f3bd8673 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrl.java
@@ -0,0 +1,84 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.search_engines; + +import org.chromium.base.annotations.CalledByNative; + +import java.util.Locale; + +/** + * Represents object of a search engine. It only caches the native pointer of TemplateURL object + * from native side. Any class uses this need to register a {@link TemplateUrlServiceObserver} on + * {@link TemplatUrlService} to listen the native changes in case the native pointer is destroyed. + */ +public class TemplateUrl { + private final long mTemplateUrlPtr; + + @CalledByNative + private static TemplateUrl create(long templateUrlPtr) { + return new TemplateUrl(templateUrlPtr); + } + + protected TemplateUrl(long templateUrlPtr) { + mTemplateUrlPtr = templateUrlPtr; + } + + /** + * @return The name of the search engine. + */ + public String getShortName() { + return nativeGetShortName(mTemplateUrlPtr); + } + + /** + * @return The prepopulated id of the search engine. For predefined engines, this field is a + * non-zero, for custom search engines, it will return 0. + */ + public int getPrepopulatedId() { + return nativeGetPrepopulatedId(mTemplateUrlPtr); + } + + /** + * @return Whether a search engine is prepopulated or created by policy. + */ + public boolean getIsPrepopulated() { + return nativeIsPrepopulatedOrCreatedByPolicy(mTemplateUrlPtr); + } + + /** + * @return The keyword of the search engine. + */ + public String getKeyword() { + return nativeGetKeyword(mTemplateUrlPtr); + } + + /** + * @return The last time used this search engine. If a search engine hasn't been used, it will + * return 0. + */ + public long getLastVisitedTime() { + return nativeGetLastVisitedTime(mTemplateUrlPtr); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TemplateUrl)) return false; + TemplateUrl otherTemplateUrl = (TemplateUrl) other; + return mTemplateUrlPtr == otherTemplateUrl.mTemplateUrlPtr; + } + + @Override + public String toString() { + return String.format(Locale.US, + "TemplateURL -- keyword: %s, short name: %s, " + + "prepopulated: %b", + getKeyword(), getShortName(), getIsPrepopulated()); + } + + private static native String nativeGetShortName(long templateUrlPtr); + private static native String nativeGetKeyword(long templateUrlPtr); + private static native boolean nativeIsPrepopulatedOrCreatedByPolicy(long templateUrlPtr); + private static native long nativeGetLastVisitedTime(long templateUrlPtr); + private static native int nativeGetPrepopulatedId(long templateUrlPtr); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java index df1817ed..21b19d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
@@ -4,21 +4,15 @@ package org.chromium.chrome.browser.search_engines; -import android.support.annotation.IntDef; -import android.text.TextUtils; +import android.support.annotation.Nullable; import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; -import java.util.Locale; - -import javax.annotation.Nullable; /** * Android wrapper of the TemplateUrlService which provides access from the Java @@ -48,95 +42,6 @@ void onTemplateURLServiceChanged(); } - /** - * Type for default search engine which is not prepopulated. This is needed because - * if a custom search engine is set as default, it will be moved to the prepopulated list. - */ - @IntDef({TYPE_DEFAULT, TYPE_PREPOPULATED, TYPE_RECENT}) - @Retention(RetentionPolicy.SOURCE) - public @interface TemplateUrlType {} - public static final int TYPE_DEFAULT = 0; - public static final int TYPE_PREPOPULATED = 1; - public static final int TYPE_RECENT = 2; - - /** - * Represents search engine with its index. - */ - public static class TemplateUrl { - private final int mIndex; - private final String mShortName; - private final boolean mIsPrepopulated; - private final String mKeyword; - @TemplateUrlType private int mTemplateUrlType; - - @CalledByNative("TemplateUrl") - public static TemplateUrl create( - int index, String shortName, boolean isPrepopulated, String keyword) { - return new TemplateUrl(index, shortName, isPrepopulated, keyword); - } - - public TemplateUrl( - int index, String shortName, boolean isPrepopulated, String keyword) { - mIndex = index; - mShortName = shortName; - mIsPrepopulated = isPrepopulated; - mKeyword = keyword; - } - - public int getIndex() { - return mIndex; - } - - public String getShortName() { - return mShortName; - } - - public boolean getIsPrepopulated() { - return mIsPrepopulated; - } - - public String getKeyword() { - return mKeyword; - } - - public void setType(@TemplateUrlType int templateUrlType) { - mTemplateUrlType = templateUrlType; - } - - @TemplateUrlType - public int getType() { - return mTemplateUrlType; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + mIndex; - result = prime * result + ((mShortName == null) ? 0 : mShortName.hashCode()); - return result; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof TemplateUrl)) return false; - TemplateUrl otherTemplateUrl = (TemplateUrl) other; - return mIndex == otherTemplateUrl.mIndex - && mTemplateUrlType == otherTemplateUrl.mTemplateUrlType - && mIsPrepopulated == otherTemplateUrl.mIsPrepopulated - && TextUtils.equals(mKeyword, otherTemplateUrl.mKeyword) - && TextUtils.equals(mShortName, otherTemplateUrl.mShortName); - } - - @Override - public String toString() { - return String.format(Locale.US, - "TemplateURL -- keyword: %s, short name: %s, index: %d, " - + "type: %d, prepopulated: %b", - mKeyword, mShortName, mIndex, mTemplateUrlType, mIsPrepopulated); - } - } - private static TemplateUrlService sService; public static TemplateUrlService getInstance() { @@ -194,47 +99,24 @@ } /** - * Sets whether filtering of the search engines is enabled. Filtering ensures the list of - * search engines is appropriate for displaying in settings, but can cause issues if you expect - * the list of search engines returned here to match the underlying TemplateUrlService in - * native. - * - * @param enableFiltering Whether to enable filtering. + * Returns a list of the all available search engines. */ - public void setFilteringEnabled(boolean enableFiltering) { - nativeSetFilteringEnabled(mNativeTemplateUrlServiceAndroid, enableFiltering); - } - - /** - * Returns a list of the prepopulated search engines. - * - * Warning: TemplateUrl.getIndex() is *not* an index into this list, since this list contains - * only prepopulated search engines. E.g. getLocalizedSearchEngines().get(0).getIndex() could - * return 3. - */ - public List<TemplateUrl> getSearchEngines() { + public List<TemplateUrl> getTemplateUrls() { ThreadUtils.assertOnUiThread(); - int defaultSearchEngineIndex = getDefaultSearchEngineIndex(); - int templateUrlCount = nativeGetTemplateUrlCount(mNativeTemplateUrlServiceAndroid); - List<TemplateUrl> templateUrls = new ArrayList<TemplateUrl>(templateUrlCount); - for (int i = 0; i < templateUrlCount; i++) { - TemplateUrl templateUrl = nativeGetTemplateUrlAt(mNativeTemplateUrlServiceAndroid, i); - if (templateUrl != null) { - setSearchEngineType(templateUrl, defaultSearchEngineIndex); - templateUrls.add(templateUrl); - } - } + List<TemplateUrl> templateUrls = new ArrayList<>(); + nativeGetTemplateUrls(mNativeTemplateUrlServiceAndroid, templateUrls); return templateUrls; } - private void setSearchEngineType(TemplateUrl templateUrl, int defaultSearchEngineIndex) { - if (templateUrl.getIsPrepopulated()) { - templateUrl.setType(TYPE_PREPOPULATED); - } else if (templateUrl.getIndex() == defaultSearchEngineIndex) { - templateUrl.setType(TYPE_DEFAULT); - } else { - templateUrl.setType(TYPE_RECENT); - } + /** + * Called from native to populate the list of all available search engines. + * @param templateUrls The list of {@link TemplateUrl} to be added. + * @param templateUrl The {@link TemplateUrl} would add to the list. + */ + @CalledByNative + private static void addTemplateUrlToList( + List<TemplateUrl> templateUrls, TemplateUrl templateUrl) { + templateUrls.add(templateUrl); } /** @@ -256,28 +138,12 @@ } /** - * @return The default search engine index (e.g., 0, 1, 2,...). - */ - public int getDefaultSearchEngineIndex() { - ThreadUtils.assertOnUiThread(); - return nativeGetDefaultSearchProviderIndex(mNativeTemplateUrlServiceAndroid); - } - - /** - * @return {@link TemplateUrlService.TemplateUrl} for the default search engine. This can + * @return {@link TemplateUrl} for the default search engine. This can * be null if DSEs are disabled entirely by administrators. */ public @Nullable TemplateUrl getDefaultSearchEngineTemplateUrl() { if (!isLoaded()) return null; - - int defaultSearchEngineIndex = getDefaultSearchEngineIndex(); - if (defaultSearchEngineIndex == -1) return null; - - assert defaultSearchEngineIndex >= 0; - assert defaultSearchEngineIndex < nativeGetTemplateUrlCount( - mNativeTemplateUrlServiceAndroid); - - return nativeGetTemplateUrlAt(mNativeTemplateUrlServiceAndroid, defaultSearchEngineIndex); + return nativeGetDefaultSearchEngine(mNativeTemplateUrlServiceAndroid); } public void setSearchEngine(String selectedKeyword) { @@ -458,13 +324,8 @@ private native long nativeInit(); private native void nativeLoad(long nativeTemplateUrlServiceAndroid); private native boolean nativeIsLoaded(long nativeTemplateUrlServiceAndroid); - private native void nativeSetFilteringEnabled( - long nativeTemplateUrlServiceAndroid, boolean disableFiltering); - private native int nativeGetTemplateUrlCount(long nativeTemplateUrlServiceAndroid); - private native TemplateUrl nativeGetTemplateUrlAt(long nativeTemplateUrlServiceAndroid, int i); private native void nativeSetUserSelectedDefaultSearchProvider( long nativeTemplateUrlServiceAndroid, String selectedKeyword); - private native int nativeGetDefaultSearchProviderIndex(long nativeTemplateUrlServiceAndroid); private native boolean nativeIsDefaultSearchManaged(long nativeTemplateUrlServiceAndroid); private native boolean nativeIsSearchResultsPageFromDefaultSearchProvider( long nativeTemplateUrlServiceAndroid, String url); @@ -488,4 +349,7 @@ long nativeTemplateUrlServiceAndroid, String keyword); private native String nativeExtractSearchTermsFromUrl( long nativeTemplateUrlServiceAndroid, String url); + private native void nativeGetTemplateUrls( + long nativeTemplateUrlServiceAndroid, List<TemplateUrl> templateUrls); + private native TemplateUrl nativeGetDefaultSearchEngine(long nativeTemplateUrlServiceAndroid); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java index cf56df04..d543745 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java
@@ -32,9 +32,9 @@ import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.omnibox.LocationBarLayout; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrlServiceObserver; import org.chromium.chrome.browser.util.IntentUtils;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java index 14ea392d..ac98911 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
@@ -9,15 +9,12 @@ import android.content.Intent; import android.os.Bundle; import android.support.annotation.IntDef; -import android.support.v7.app.AppCompatActivity; -import org.chromium.base.Log; -import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.SynchronousInitializationActivity; import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.PreferencesLauncher; @@ -31,7 +28,7 @@ * An Activity displayed from the MainPreferences to allow the user to pick an account to * sign in to. The AccountSigninView.Delegate interface is fulfilled by the AppCompatActivity. */ -public class AccountSigninActivity extends AppCompatActivity +public class AccountSigninActivity extends SynchronousInitializationActivity implements AccountSigninView.Listener, AccountSigninView.Delegate { private static final String TAG = "AccountSigninActivity"; private static final String INTENT_IS_FROM_PERSONALIZED_PROMO = @@ -144,17 +141,6 @@ @Override protected void onCreate(Bundle savedInstanceState) { - // The browser process must be started here because this activity may be started from the - // recent apps list and it relies on other activities and the native library to be loaded. - try { - ChromeBrowserInitializer.getInstance(this).handleSynchronousStartup(); - } catch (ProcessInitException e) { - Log.e(TAG, "Failed to start browser process.", e); - // Since the library failed to initialize nothing in the application - // can work, so kill the whole application not just the activity - System.exit(-1); - } - // We don't trust android to restore the saved state correctly, so pass null. super.onCreate(null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java index 7bd8e2c..08a09a1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java
@@ -9,18 +9,15 @@ import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; -import android.support.v7.app.AppCompatActivity; -import org.chromium.base.Log; -import org.chromium.base.library_loader.ProcessInitException; import org.chromium.chrome.R; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.SynchronousInitializationActivity; /** * Allows user to pick an account and sign in. Started from Settings and various sign-in promos. */ // TODO(https://crbug.com/820491): extend AsyncInitializationActivity. -public class SigninActivity extends AppCompatActivity { +public class SigninActivity extends SynchronousInitializationActivity { private static final String TAG = "SigninActivity"; /** @@ -37,17 +34,6 @@ @Override protected void onCreate(Bundle savedInstanceState) { - // The browser process must be started here because this activity may be started from the - // recent apps list and it relies on other activities and the native library to be loaded. - try { - ChromeBrowserInitializer.getInstance(this).handleSynchronousStartup(); - } catch (ProcessInitException e) { - Log.e(TAG, "Failed to start browser process.", e); - // Since the library failed to initialize nothing in the application - // can work, so kill the whole application not just the activity - System.exit(-1); - } - super.onCreate(savedInstanceState); setContentView(R.layout.signin_activity);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index e093bf9f..d04d0a0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -57,8 +57,8 @@ import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.partnercustomizations.HomepageManager.HomepageStateListener; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrlServiceObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index f407ac6b..108a2c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -592,7 +592,6 @@ dismissTabSwitcherCallout(); cancelAppMenuUpdateBadgeAnimation(); mTabSwitcherListener.onClick(mToggleTabStackButton); - RecordUserAction.record("MobileToolbarShowStackView"); } } @@ -2701,4 +2700,3 @@ } } } -
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java index a5e8b41..3058f71 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -47,9 +47,12 @@ import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; +import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; +import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; +import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.vr_shell.keyboard.VrInputMethodManagerWrapper; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; import org.chromium.chrome.browser.widget.newtab.NewTabButton; @@ -85,6 +88,7 @@ private final boolean mVrBrowsingEnabled; private TabModelSelectorTabObserver mTabModelSelectorTabObserver; + private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver; private long mNativeVrShell; @@ -373,7 +377,8 @@ swapToTab(tab); createTabList(); mActivity.getTabModelSelector().addObserver(mTabModelSelectorObserver); - createTabModelSelectorTabObserver(); + attachTabModelSelectorTabObserver(); + attachTabModelSelectorTabModelObserver(); updateHistoryButtonsVisibility(); mPresentationView.setOnTouchListener(mTouchListener); @@ -705,6 +710,7 @@ } mTabModelSelector.removeObserver(mTabModelSelectorObserver); mTabModelSelectorTabObserver.destroy(); + mTabModelSelectorTabModelObserver.destroy(); if (mTab != null) { mTab.removeObserver(mTabObserver); restoreTabFromVR(); @@ -903,7 +909,8 @@ if (mNativeVrShell != 0) nativeSetSurface(mNativeVrShell, null); } - private void createTabModelSelectorTabObserver() { + /** Creates and attaches a TabModelSelectorTabObserver to the tab model selector. */ + private void attachTabModelSelectorTabObserver() { assert mTabModelSelectorTabObserver == null; mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) { @Override @@ -931,6 +938,18 @@ }; } + /** Creates and attaches a TabModelSelectorTabModelObserver to the tab model selector. */ + private void attachTabModelSelectorTabModelObserver() { + assert mTabModelSelectorTabModelObserver == null; + mTabModelSelectorTabModelObserver = + new TabModelSelectorTabModelObserver(mTabModelSelector) { + @Override + public void didSelectTab(Tab tab, TabSelectionType type, int lastId) { + nativeOnTabSelected(mNativeVrShell, tab.isIncognito(), tab.getId()); + } + }; + } + @CalledByNative public boolean hasDaydreamSupport() { return mDelegate.hasDaydreamSupport(); @@ -1000,6 +1019,15 @@ } @CalledByNative + public void selectTab(int id, boolean incognito) { + TabModel tabModel = mTabModelSelector.getModel(incognito); + int index = TabModelUtils.getTabIndexById(tabModel, id); + if (index != TabModel.INVALID_TAB_INDEX) { + tabModel.setIndex(index, TabSelectionType.FROM_USER); + } + } + + @CalledByNative public void openBookmarks() { mActivity.onMenuOrKeyboardAction(R.id.all_bookmarks_menu_id, true); } @@ -1228,6 +1256,7 @@ private native void nativeOnTabUpdated(long nativeVrShell, boolean incognito, int id, String title); private native void nativeOnTabRemoved(long nativeVrShell, boolean incognito, int id); + private native void nativeOnTabSelected(long nativeVrShell, boolean incognito, int id); private native void nativeCloseAlertDialog(long nativeVrShell); private native void nativeSetAlertDialog(long nativeVrShell, float width, float height); private native void nativeSetDialogBufferSize(long nativeVrShell, float width, float height);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java index 3f5eab9..e8aed82 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java
@@ -80,7 +80,7 @@ (FrameLayout.LayoutParams) mTabModelWrapper.getLayoutParams(); if (params == null) return; - params.bottomMargin = (int) (getTopBrowserControlsHeight() * mDensity); + params.bottomMargin = (int) (getBottomBrowserControlsHeight() * mDensity); params.topMargin = (int) (getTopBrowserControlsHeight() * mDensity); mTabModelWrapper.setLayoutParams(params);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 7f19249d..25f3c88 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -134,9 +134,6 @@ <message name="IDS_OK_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR-LIMIT=20]"> OK, got it </message> - <message name="IDS_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR-LIMIT=20]"> - Got it - </message> <message name="IDS_CANCEL" desc="Label for a cancel button. Used in multiple contexts. [CHAR-LIMIT=20]"> Cancel </message> @@ -798,8 +795,8 @@ <message name="IDS_MEDIA_PERMISSION_TITLE" desc="Title of the menu containing the media permissions [CHAR-LIMIT=32]"> Media </message> - <message name="IDS_POPUP_PERMISSION_TITLE" desc="Title of the permission to display pop-up windows [CHAR-LIMIT=32]"> - Pop-ups + <message name="IDS_POPUP_PERMISSION_TITLE" desc="Title of the permission to display pop-up windows and redirects [CHAR-LIMIT=32]"> + Pop-ups and redirects </message> <message name="IDS_PUSH_NOTIFICATIONS_PERMISSION_TITLE" desc="Title for the permission for showing push notifications [CHAR-LIMIT=32]"> Notifications @@ -933,8 +930,8 @@ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_USB_BLOCKED" desc="Summary text explaining that the USB permission is set to block all requests for access to devices. To be shown in the list of permission categories."> Block sites from connecting to devices </message> - <message name="IDS_WEBSITE_SETTINGS_CATEGORY_POPUPS_BLOCKED" desc="Summary text explaining that sites are blocked from showing popups and that it is the recommended setting."> - Block sites from showing pop-ups (recommended) + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_POPUPS_REDIRECTS_BLOCKED" desc="Summary text explaining that sites are blocked from showing popups/redirects and that it is the recommended setting."> + Block sites from showing pop-ups and redirects (recommended) </message> <message name="IDS_WEBSITE_SETTINGS_CATEGORY_ADS_BLOCKED" desc="Summary text explaining that ads are being blocked on some sites."> Block ads from sites that tend to show intrusive ads @@ -2240,12 +2237,6 @@ <message name="IDS_DOWNLOAD_MANAGER_LIST_ITEM_DESCRIPTION" desc="Text containing the download list item description."> <ph name="FILE_SIZE">%1$s<ex>1.56 MB</ex></ph> - <ph name="DESCRIPTION">%2$s<ex>www.example.com</ex></ph> </message> - <message name="IDS_DOWNLOAD_MANAGER_UI_SHOW_STORAGE" desc="Text that tells the user to show the storage information in downloads home."> - Show storage - </message> - <message name="IDS_DOWNLOAD_MANAGER_UI_HIDE_STORAGE" desc="Text that tells the user to hide the storage information in downloads home."> - Hide storage - </message> <!-- Browsing History UI --> <message name="IDS_HISTORY_MANAGER_EMPTY" desc="Indicates that there are no browsing history items."> @@ -3287,11 +3278,14 @@ <!-- Interventions --> <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to."> - Redirect blocked to site: + Redirect blocked: </message> <message name="IDS_REDIRECT_BLOCKED_SHORT_MESSAGE" desc="The short message stating that a redirect (noun) was blocked on this page."> Redirect blocked. </message> + <message name="IDS_ALWAYS_ALLOW_REDIRECTS" desc="The infobar button text allowing a user to always allow redirects (noun) after they were blocked on this page."> + Always allow + </message> <message name="IDS_NEAR_OOM_INTERVENTION_MESSAGE" desc="The message stating that the browser intervened to stop the page using too much memory."> This page uses too much memory, so Chrome paused it. </message>
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_UI_HIDE_STORAGE.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_UI_HIDE_STORAGE.png.sha1 deleted file mode 100644 index d265bbc9..0000000 --- a/chrome/android/java/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_UI_HIDE_STORAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -86199850f71f7549080fbac10d865d243bfdc950 \ No newline at end of file
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_UI_SHOW_STORAGE.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_UI_SHOW_STORAGE.png.sha1 deleted file mode 100644 index afe5d01..0000000 --- a/chrome/android/java/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_UI_SHOW_STORAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -68c8dff06fca220ad3e2000d6849a8f443368a25 \ No newline at end of file
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index e8c6bd97..4822894 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1110,6 +1110,7 @@ "java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java", "java/src/org/chromium/chrome/browser/rlz/RevenueStats.java", "java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java", + "java/src/org/chromium/chrome/browser/search_engines/TemplateUrl.java", "java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java", "java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java", "java/src/org/chromium/chrome/browser/searchwidget/SearchActivityFadingBackgroundView.java",
diff --git a/chrome/android/javatests/DEPS b/chrome/android/javatests/DEPS index bc9cb0a..901f115 100644 --- a/chrome/android/javatests/DEPS +++ b/chrome/android/javatests/DEPS
@@ -24,6 +24,7 @@ "+content/public/android/java/src/org/chromium/content_public", "!content/public/android/java/src/org/chromium/content/browser/BindingManager.java", "!content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java", + "!content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java", "!content/public/android/java/src/org/chromium/content/common/ContentSwitches.java", "-content/public/android/javatests",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java index 56b4387..1232b93 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -32,8 +32,8 @@ import org.chromium.chrome.browser.locale.DefaultSearchEngineDialogHelperUtils; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.searchwidget.SearchActivity; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.MultiActivityTestRule; @@ -256,7 +256,7 @@ @Override public List<TemplateUrl> getSearchEnginesForPromoDialog(int promoType) { - return TemplateUrlService.getInstance().getSearchEngines(); + return TemplateUrlService.getInstance().getTemplateUrls(); } }; LocaleManager.setInstanceForTest(mockManager);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java index 85d19fcf7..af23144 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java
@@ -21,7 +21,7 @@ import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.widget.RadioButtonLayout; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -53,6 +53,34 @@ } } + private class TestTemplateUrl extends TemplateUrl { + private String mShortName; + private String mKeyword; + public TestTemplateUrl(String shortName, String keyword) { + super(0); + mShortName = shortName; + mKeyword = keyword; + } + + @Override + public String getShortName() { + return mShortName; + } + + @Override + public String getKeyword() { + return mKeyword; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof TemplateUrl)) return false; + TestTemplateUrl otherTemplateUrl = (TestTemplateUrl) other; + return TextUtils.equals(mKeyword, otherTemplateUrl.mKeyword) + && TextUtils.equals(mShortName, otherTemplateUrl.mShortName); + } + } + private class TestDialogHelper extends DefaultSearchEngineDialogHelper { public TestDelegate delegate; @@ -91,10 +119,10 @@ mContext = InstrumentationRegistry.getTargetContext(); mTemplateUrls.clear(); - mTemplateUrls.add(new TemplateUrl(0, "Google: Search by Google", true, "keyword 1")); - mTemplateUrls.add(new TemplateUrl(5, "This", true, "keyword 2")); - mTemplateUrls.add(new TemplateUrl(10, "That", true, "keyword 3")); - mTemplateUrls.add(new TemplateUrl(15, "The Other Thing", true, "keyword 4")); + mTemplateUrls.add(new TestTemplateUrl("Google: Search by Google", "keyword 1")); + mTemplateUrls.add(new TestTemplateUrl("This", "keyword 2")); + mTemplateUrls.add(new TestTemplateUrl("That", "keyword 3")); + mTemplateUrls.add(new TestTemplateUrl("The Other Thing", "keyword 4")); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java index 305f59d..55d0da9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java
@@ -1,4 +1,3 @@ -// 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. @@ -20,8 +19,8 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.searchwidget.SearchActivity; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ActivityUtils; @@ -49,7 +48,7 @@ LocaleManager mockManager = new LocaleManager() { @Override public List<TemplateUrl> getSearchEnginesForPromoDialog(int promoType) { - return TemplateUrlService.getInstance().getSearchEngines(); + return TemplateUrlService.getInstance().getTemplateUrls(); } }; LocaleManager.setInstanceForTest(mockManager);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java index f56a265e..827859eb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java
@@ -1,4 +1,3 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -31,9 +30,9 @@ import org.chromium.chrome.browser.preferences.website.ContentSetting; import org.chromium.chrome.browser.preferences.website.GeolocationInfo; import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.test.ChromeBrowserTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ActivityUtils; @@ -267,7 +266,7 @@ private int indexOfFirstHttpSearchEngine(SearchEnginePreference pref) { TemplateUrlService templateUrlService = TemplateUrlService.getInstance(); - List<TemplateUrl> urls = templateUrlService.getSearchEngines(); + List<TemplateUrl> urls = templateUrlService.getTemplateUrls(); int index; for (index = 0; index < urls.size(); ++index) { String keyword = pref.getKeywordFromIndexForTesting(index);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java index 4a2fe7b..cc1c89b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
@@ -18,8 +18,8 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; +import org.chromium.chrome.browser.preferences.SearchEngineAdapter; import org.chromium.chrome.browser.search_engines.TemplateUrlService.LoadListener; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.test.ChromeBrowserTestRule; import org.chromium.chrome.browser.test.ClearAppDataTestRule; import org.chromium.content.browser.test.util.Criteria; @@ -145,37 +145,38 @@ ThreadUtils.runOnUiThreadBlockingNoException(new Callable<List<TemplateUrl>>() { @Override public List<TemplateUrl> call() throws Exception { - return templateUrlService.getSearchEngines(); + return templateUrlService.getTemplateUrls(); } }); // Ensure known state of default search index before running test. - String searchEngineKeyword = - ThreadUtils.runOnUiThreadBlockingNoException(new Callable<String>() { + TemplateUrl defaultSearchEngine = + ThreadUtils.runOnUiThreadBlockingNoException(new Callable<TemplateUrl>() { @Override - public String call() throws Exception { - return templateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword(); + public TemplateUrl call() throws Exception { + return templateUrlService.getDefaultSearchEngineTemplateUrl(); } }); - Assert.assertEquals(searchEngines.get(0).getKeyword(), searchEngineKeyword); + SearchEngineAdapter.sortAndFilterUnnecessaryTemplateUrl(searchEngines, defaultSearchEngine); + Assert.assertEquals(searchEngines.get(0), defaultSearchEngine); // Set search engine index and verified it stuck. ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - List<TemplateUrl> searchEngines = templateUrlService.getSearchEngines(); Assert.assertTrue( "There must be more than one search engine to change searchEngines", searchEngines.size() > 1); templateUrlService.setSearchEngine(searchEngines.get(1).getKeyword()); } }); - searchEngineKeyword = ThreadUtils.runOnUiThreadBlockingNoException(new Callable<String>() { - @Override - public String call() throws Exception { - return templateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword(); - } - }); - Assert.assertEquals(searchEngines.get(1).getKeyword(), searchEngineKeyword); + defaultSearchEngine = + ThreadUtils.runOnUiThreadBlockingNoException(new Callable<TemplateUrl>() { + @Override + public TemplateUrl call() throws Exception { + return templateUrlService.getDefaultSearchEngineTemplateUrl(); + } + }); + Assert.assertEquals(searchEngines.get(1), defaultSearchEngine); } @Test @@ -187,6 +188,14 @@ // Get the number of prepopulated search engine. final int prepopulatedEngineNum = getSearchEngineCount(templateUrlService); + TemplateUrl defaultSearchEngine = + ThreadUtils.runOnUiThreadBlockingNoException(new Callable<TemplateUrl>() { + @Override + public TemplateUrl call() throws Exception { + return templateUrlService.getDefaultSearchEngineTemplateUrl(); + } + }); + // Add custom search engines and verified only engines visited within 2 days are added. // Also verified custom engines are sorted correctly. List<TemplateUrl> customSearchEngines = @@ -196,7 +205,9 @@ templateUrlService.addSearchEngineForTesting("keyword1", 0); templateUrlService.addSearchEngineForTesting("keyword2", 0); templateUrlService.addSearchEngineForTesting("keyword3", 3); - List<TemplateUrl> searchEngines = templateUrlService.getSearchEngines(); + List<TemplateUrl> searchEngines = templateUrlService.getTemplateUrls(); + SearchEngineAdapter.sortAndFilterUnnecessaryTemplateUrl( + searchEngines, defaultSearchEngine); return searchEngines.subList(prepopulatedEngineNum, searchEngines.size()); } }); @@ -212,7 +223,9 @@ public List<TemplateUrl> call() throws Exception { templateUrlService.addSearchEngineForTesting("keyword4", 0); templateUrlService.addSearchEngineForTesting("keyword5", 0); - List<TemplateUrl> searchEngines = templateUrlService.getSearchEngines(); + List<TemplateUrl> searchEngines = templateUrlService.getTemplateUrls(); + SearchEngineAdapter.sortAndFilterUnnecessaryTemplateUrl( + searchEngines, defaultSearchEngine); return searchEngines.subList(prepopulatedEngineNum, searchEngines.size()); } }); @@ -227,7 +240,9 @@ @Override public List<TemplateUrl> call() throws Exception { templateUrlService.updateLastVisitedForTesting("keyword3"); - List<TemplateUrl> searchEngines = templateUrlService.getSearchEngines(); + List<TemplateUrl> searchEngines = templateUrlService.getTemplateUrls(); + SearchEngineAdapter.sortAndFilterUnnecessaryTemplateUrl( + searchEngines, defaultSearchEngine); return searchEngines.subList(prepopulatedEngineNum, searchEngines.size()); } }); @@ -243,7 +258,11 @@ @Override public List<TemplateUrl> call() throws Exception { templateUrlService.setSearchEngine("keyword4"); - List<TemplateUrl> searchEngines = templateUrlService.getSearchEngines(); + List<TemplateUrl> searchEngines = templateUrlService.getTemplateUrls(); + TemplateUrl newDefaultSearchEngine = + templateUrlService.getDefaultSearchEngineTemplateUrl(); + SearchEngineAdapter.sortAndFilterUnnecessaryTemplateUrl( + searchEngines, newDefaultSearchEngine); return searchEngines.subList(prepopulatedEngineNum, searchEngines.size()); } }); @@ -254,33 +273,11 @@ Assert.assertEquals("keyword2", customSearchEngines.get(3).getKeyword()); } - @Test - @SmallTest - @Feature({"SearchEngines"}) - public void testDisableFiltering() { - final TemplateUrlService templateUrlService = waitForTemplateUrlServiceToLoad(); - - // Get the number of prepopulated search engine. - final int prepopulatedEngineNum = getSearchEngineCount(templateUrlService); - - ThreadUtils.runOnUiThreadBlocking(() -> { - for (int i = 0; i < 10; i++) { - templateUrlService.addSearchEngineForTesting("keyword" + i, 0); - } - }); - - Assert.assertEquals(prepopulatedEngineNum + 3, getSearchEngineCount(templateUrlService)); - templateUrlService.setFilteringEnabled(false); - Assert.assertEquals(prepopulatedEngineNum + 10, getSearchEngineCount(templateUrlService)); - templateUrlService.setFilteringEnabled(true); - Assert.assertEquals(prepopulatedEngineNum + 3, getSearchEngineCount(templateUrlService)); - } - private int getSearchEngineCount(final TemplateUrlService templateUrlService) { return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() { @Override public Integer call() throws Exception { - return templateUrlService.getSearchEngines().size(); + return templateUrlService.getTemplateUrls().size(); } }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java index 5513303..33d7bc5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
@@ -39,8 +39,8 @@ import org.chromium.chrome.browser.omnibox.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.OmniboxSuggestion.MatchClassification; import org.chromium.chrome.browser.omnibox.UrlBar; +import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl; import org.chromium.chrome.browser.searchwidget.SearchActivity.SearchActivityDelegate; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -108,7 +108,7 @@ @Override public List<TemplateUrl> getSearchEnginesForPromoDialog(int promoType) { - return TemplateUrlService.getInstance().getSearchEngines(); + return TemplateUrlService.getInstance().getTemplateUrls(); } }); super.showSearchEngineDialogIfNeeded(activity, onSearchEngineFinalized);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java index 494e0bf..6435c86 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
@@ -34,7 +34,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.DisableInTabbedMode; -import org.chromium.content.browser.test.InterstitialPageDelegateAndroid; +import org.chromium.content.browser.InterstitialPageDelegateAndroid; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.ui.test.util.UiRestriction; @@ -249,7 +249,10 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - delegate.showInterstitialPage(brandColorUrl, mActivityTestRule.getWebContents()); + mActivityTestRule.getActivity() + .getActivityTab() + .getWebContents() + .showInterstitialPage(brandColorUrl, delegate.getNative()); } }); CriteriaHelper.pollUiThread(new Criteria() {
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 687b805..84647d0 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -215,6 +215,9 @@ <message name="IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_LABEL" desc="Downloads local directory label."> Downloads </message> + <message name="IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL" desc="A label for the 'Linux Files' root which shows crostini files."> + Linux Files + </message> <message name="IDS_FILE_BROWSER_MEDIA_VIEW_IMAGES_ROOT_LABEL" desc="A label for the 'Images' root of media views."> Images </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 3b63bb109..0eeacab 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -10024,9 +10024,6 @@ <message name="IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY" desc="Body text of an auto-generated notification informing the user that the site may have received an update in the background, in case the site did not satisfy the visible notification requirement itself."> This site has been updated in the background. </message> - <message name="IDS_NOTIFICATIONS_BACKGROUND_SERVICE_NAME" desc="The name of the Notifications service that can run in the background"> - Notifications - </message> <!-- Easy Unlock strings --> <!-- Strings for the Easy Unlock promo notification -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 31d73e0f..f8e06f4 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -820,8 +820,6 @@ "net/spdyproxy/data_reduction_proxy_chrome_settings.h", "net/spdyproxy/data_reduction_proxy_chrome_settings_factory.cc", "net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h", - "net/sth_distributor_provider.cc", - "net/sth_distributor_provider.h", "net/system_network_context_manager.cc", "net/system_network_context_manager.h", "net/timed_cache.cc", @@ -2339,6 +2337,8 @@ "profiles/profile_android.h", "search/contextual_search_policy_handler_android.cc", "search/contextual_search_policy_handler_android.h", + "search_engines/template_url_android.cc", + "search_engines/template_url_android.h", "search_engines/template_url_service_android.cc", "search_engines/template_url_service_android.h", "signin/oauth2_token_service_delegate_android.cc", @@ -4405,6 +4405,7 @@ "../android/java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java", "../android/java/src/org/chromium/chrome/browser/rlz/RevenueStats.java", "../android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java", + "../android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrl.java", "../android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java", "../android/java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java", "../android/java/src/org/chromium/chrome/browser/signin/AccountManagementScreenHelper.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 830ca6d8..99e57ce5 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1561,9 +1561,6 @@ {"multidevice-service", flag_descriptions::kMultiDeviceApiName, flag_descriptions::kMultiDeviceApiDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kMultiDeviceApi)}, - {"mus", flag_descriptions::kUseMusName, - flag_descriptions::kUseMusDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kMus)}, {"mash", flag_descriptions::kUseMashName, flag_descriptions::kUseMashDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kMash)}, @@ -1894,10 +1891,6 @@ flag_descriptions::kChromeHomeInactivitySheetExpansionDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kChromeHomeInactivitySheetExpansion)}, - {"enable-chrome-home-menu-items", - flag_descriptions::kChromeHomeMenuItemsName, - flag_descriptions::kChromeHomeMenuItemsDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kChromeHomeMenuItemsExpandSheet)}, {"chrome-home-swipe-logic", flag_descriptions::kChromeHomeSwipeLogicName, flag_descriptions::kChromeHomeSwipeLogicDescription, kOsAndroid, MULTI_VALUE_TYPE(kChromeHomeSwipeLogicChoices)}, @@ -2389,14 +2382,6 @@ flag_descriptions::kUseWinrtMidiApiDescription, kOsWin, FEATURE_VALUE_TYPE(midi::features::kMidiManagerWinrt)}, #endif // OS_WIN -#if BUILDFLAG(ENABLE_BACKGROUND_MODE) - {"enable-push-api-background-mode", - flag_descriptions::kPushApiBackgroundModeName, - flag_descriptions::kPushApiBackgroundModeDescription, - kOsMac | kOsWin | kOsLinux, - ENABLE_DISABLE_VALUE_TYPE(switches::kEnablePushApiBackgroundMode, - switches::kDisablePushApiBackgroundMode)}, -#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE) #if defined(OS_CHROMEOS) {"cros-regions-mode", flag_descriptions::kCrosRegionsModeName, flag_descriptions::kCrosRegionsModeDescription, kOsCrOS, @@ -3821,12 +3806,12 @@ FEATURE_VALUE_TYPE(features::kViewsCastDialog)}, #endif // defined(TOOLKIT_VIEWS) -#if defined(OS_MACOSX) +#if defined(OS_MACOSX) || defined(OS_WIN) {"enable-emoji-context-menu", flag_descriptions::kEnableEmojiContextMenuName, - flag_descriptions::kEnableEmojiContextMenuDescription, kOsMac, + flag_descriptions::kEnableEmojiContextMenuDescription, kOsMac | kOsWin, FEATURE_VALUE_TYPE(features::kEnableEmojiContextMenu)}, -#endif // OS_MACOSX +#endif // OS_MACOSX || OS_WIN {"SupervisedUserCommittedInterstitials", flag_descriptions::kSupervisedUserCommittedInterstitialsName, @@ -3922,6 +3907,14 @@ FEATURE_VALUE_TYPE(features::kDisplayCutoutAPI)}, #endif // OS_ANDROID +#if defined(USE_AURA) + {"touchpad-overscroll-history-navigation", + flag_descriptions::kTouchpadOverscrollHistoryNavigationName, + flag_descriptions::kTouchpadOverscrollHistoryNavigationDescription, + kOsWin | kOsCrOS, + FEATURE_VALUE_TYPE(features::kTouchpadOverscrollHistoryNavigation)}, +#endif + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc index 42cc6cf..a81113c 100644 --- a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc +++ b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/favicon_types.h" @@ -313,9 +314,10 @@ })"); GetLargeIconService() ->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - page_url, kPartnerBookmarksMinimumFaviconSizePx, - desired_favicon_size_px, false /* may_page_url_be_private */, - traffic_annotation, + favicon::FaviconServerFetcherParams::CreateForMobile( + page_url, kPartnerBookmarksMinimumFaviconSizePx, + desired_favicon_size_px), + false /* may_page_url_be_private */, traffic_annotation, base::Bind(&PartnerBookmarksReader::OnGetFaviconFromServerFinished, base::Unretained(this), page_url, desired_favicon_size_px, base::Passed(std::move(callback))));
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index f879dd0..9ae9c6d 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -71,7 +71,6 @@ &kCCTRedirectPreconnect, &kChromeDuplexFeature, &kChromeHomeInactivitySheetExpansion, - &kChromeHomeMenuItemsExpandSheet, &kChromeHomePersistentIph, &kChromeHomePullToRefreshIphAtTop, &kChromeHomeSwipeLogic, @@ -205,9 +204,6 @@ const base::Feature kChromeHomeInactivitySheetExpansion{ "ChromeHomeInactivitySheetExpansion", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kChromeHomeMenuItemsExpandSheet{ - "ChromeHomeMenuItemsExpandSheet", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kChromeHomePersistentIph{"ChromeHomePersistentIph", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 3331923..9007eb3 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -24,7 +24,6 @@ extern const base::Feature kCCTRedirectPreconnect; extern const base::Feature kChromeDuplexFeature; extern const base::Feature kChromeHomeInactivitySheetExpansion; -extern const base::Feature kChromeHomeMenuItemsExpandSheet; extern const base::Feature kChromeHomePersistentIph; extern const base::Feature kChromeHomePullToRefreshIphAtTop; extern const base::Feature kChromeHomeSurvey;
diff --git a/chrome/browser/android/compositor/compositor_view.cc b/chrome/browser/android/compositor/compositor_view.cc index 387164d..d0c90c9 100644 --- a/chrome/browser/android/compositor/compositor_view.cc +++ b/chrome/browser/android/compositor/compositor_view.cc
@@ -127,9 +127,11 @@ Java_CompositorView_didSwapFrame(env, obj_, pending_frames); } -void CompositorView::DidSwapBuffers() { +void CompositorView::DidSwapBuffers(const gfx::Size& swap_size) { JNIEnv* env = base::android::AttachCurrentThread(); - Java_CompositorView_didSwapBuffers(env, obj_); + bool swapped_current_size = + swap_size == gfx::Size(content_width_, content_height_); + Java_CompositorView_didSwapBuffers(env, obj_, swapped_current_size); } ui::UIResourceProvider* CompositorView::GetUIResourceProvider() {
diff --git a/chrome/browser/android/compositor/compositor_view.h b/chrome/browser/android/compositor/compositor_view.h index 1074f5b0..d994948 100644 --- a/chrome/browser/android/compositor/compositor_view.h +++ b/chrome/browser/android/compositor/compositor_view.h
@@ -89,7 +89,7 @@ // CompositorClient implementation: void UpdateLayerTreeHost() override; void DidSwapFrame(int pending_frames) override; - void DidSwapBuffers() override; + void DidSwapBuffers(const gfx::Size& swap_size) override; ui::UIResourceProvider* GetUIResourceProvider(); private:
diff --git a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc index f33ebc7..0b2697b 100644 --- a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc +++ b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc
@@ -132,6 +132,10 @@ } } +void OomInterventionTabHelper::DeclineInterventionSticky() { + NOTREACHED(); +} + void OomInterventionTabHelper::WebContentsDestroyed() { OutOfMemoryReporter::FromWebContents(web_contents())->RemoveObserver(this); StopMonitoring();
diff --git a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h index 98916d1..c43472b 100644 --- a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h +++ b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h
@@ -43,6 +43,7 @@ // InterventionDelegate: void AcceptIntervention() override; void DeclineIntervention() override; + void DeclineInterventionSticky() override; private: explicit OomInterventionTabHelper(content::WebContents* web_contents);
diff --git a/chrome/browser/android/vr/vr_gl_thread.cc b/chrome/browser/android/vr/vr_gl_thread.cc index 703dac98..207e981 100644 --- a/chrome/browser/android/vr/vr_gl_thread.cc +++ b/chrome/browser/android/vr/vr_gl_thread.cc
@@ -249,6 +249,13 @@ base::BindOnce(&VrShell::OpenNewTab, weak_vr_shell_, incognito)); } +void VrGLThread::SelectTab(int id, bool incognito) { + DCHECK(OnGlThread()); + main_thread_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VrShell::SelectTab, weak_vr_shell_, id, incognito)); +} + void VrGLThread::OpenBookmarks() { DCHECK(OnGlThread()); main_thread_task_runner_->PostTask( @@ -539,6 +546,13 @@ base::BindOnce(&BrowserUiInterface::RemoveAllTabs, weak_browser_ui_)); } +void VrGLThread::OnTabSelected(int id, bool incognito) { + DCHECK(OnMainThread()); + task_runner()->PostTask(FROM_HERE, + base::BindOnce(&BrowserUiInterface::OnTabSelected, + weak_browser_ui_, id, incognito)); +} + void VrGLThread::ReportUiActivityResultForTesting( const VrUiTestActivityResult& result) { DCHECK(OnGlThread());
diff --git a/chrome/browser/android/vr/vr_gl_thread.h b/chrome/browser/android/vr/vr_gl_thread.h index 9883f1e0b..60b600d 100644 --- a/chrome/browser/android/vr/vr_gl_thread.h +++ b/chrome/browser/android/vr/vr_gl_thread.h
@@ -87,6 +87,7 @@ void NavigateForward() override; void ReloadTab() override; void OpenNewTab(bool incognito) override; + void SelectTab(int id, bool incognito) override; void OpenBookmarks() override; void OpenRecentTabs() override; void OpenHistory() override; @@ -138,6 +139,7 @@ const base::string16& title) override; void RemoveTab(int id, bool incognito) override; void RemoveAllTabs() override; + void OnTabSelected(int id, bool incognito) override; void ReportUiActivityResultForTesting( const VrUiTestActivityResult& result) override;
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc index 871b4bb..0d6629d 100644 --- a/chrome/browser/android/vr/vr_shell.cc +++ b/chrome/browser/android/vr/vr_shell.cc
@@ -372,6 +372,11 @@ Java_VrShellImpl_openNewTab(env, j_vr_shell_, incognito); } +void VrShell::SelectTab(int id, bool incognito) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_VrShellImpl_selectTab(env, j_vr_shell_, id, incognito); +} + void VrShell::OpenBookmarks() { JNIEnv* env = base::android::AttachCurrentThread(); Java_VrShellImpl_openBookmarks(env, j_vr_shell_); @@ -624,6 +629,13 @@ ui_->RemoveTab(id, incognito); } +void VrShell::OnTabSelected(JNIEnv* env, + const JavaParamRef<jobject>& obj, + jboolean incognito, + jint id) { + ui_->OnTabSelected(id, incognito); +} + void VrShell::SetAlertDialog(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, float width,
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h index 3400c2c..5f5b475 100644 --- a/chrome/browser/android/vr/vr_shell.h +++ b/chrome/browser/android/vr/vr_shell.h
@@ -129,12 +129,17 @@ const base::android::JavaParamRef<jobject>& obj, jboolean incognito, jint id); + void OnTabSelected(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + jboolean incognito, + jint id); void OnContentPaused(bool paused); void Navigate(GURL url, NavigationMethod method); void NavigateBack(); void NavigateForward(); void ReloadTab(); void OpenNewTab(bool incognito); + void SelectTab(int id, bool incognito); void OpenBookmarks(); void OpenRecentTabs(); void OpenHistory();
diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc index 2c91c17..8a29faf 100644 --- a/chrome/browser/autocomplete/autocomplete_browsertest.cc +++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc
@@ -57,7 +57,7 @@ } // namespace -class AutocompleteBrowserTest : public ExtensionBrowserTest { +class AutocompleteBrowserTest : public extensions::ExtensionBrowserTest { protected: void WaitForTemplateURLServiceToLoad() { search_test_utils::WaitForTemplateURLServiceToLoad(
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc index 02a3a9ee..f2a13b3 100644 --- a/chrome/browser/chrome_security_exploit_browsertest.cc +++ b/chrome/browser/chrome_security_exploit_browsertest.cc
@@ -35,13 +35,14 @@ // perform any dangerous operations in such cases. // This is similar to the security_exploit_browsertest.cc tests, but also // includes chrome/ layer concepts such as extensions. -class ChromeSecurityExploitBrowserTest : public ExtensionBrowserTest { +class ChromeSecurityExploitBrowserTest + : public extensions::ExtensionBrowserTest { public: ChromeSecurityExploitBrowserTest() {} ~ChromeSecurityExploitBrowserTest() override {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(embedded_test_server()->Start()); host_resolver()->AddRule("*", "127.0.0.1"); @@ -50,7 +51,7 @@ } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); // Since we assume exploited renderer process, it can bypass the same origin // policy at will. Simulate that by passing the disable-web-security flag. command_line->AppendSwitch(switches::kDisableWebSecurity);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index db86a24..9ace0bc 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -33,6 +33,7 @@ "//chromeos:vm_applications_apps_proto", "//components/policy/proto", "//content/app/resources", + "//ui/accessibility/mojom", "//ui/chromeos/resources", "//ui/chromeos/strings", "//ui/resources",
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc index 94e10fe9..7f522ef9 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
@@ -31,7 +31,8 @@ #include "components/arc/connection_holder.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" -#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h" +#include "ui/accessibility/ax_assistant_structure.h" +#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/gfx/geometry/dip_util.h" @@ -49,30 +50,33 @@ base::TimeDelta::FromMinutes(1); mojom::VoiceInteractionStructurePtr CreateVoiceInteractionStructure( - const ui::AXSnapshotNodeAndroid& view_structure) { + const ui::AssistantTree& tree, + const ui::AssistantNode& node) { auto structure = mojom::VoiceInteractionStructure::New(); - structure->text = view_structure.text; - structure->text_size = view_structure.text_size; + structure->text = node.text; + structure->text_size = node.text_size; - structure->bold = view_structure.bold; - structure->italic = view_structure.italic; - structure->underline = view_structure.underline; - structure->line_through = view_structure.line_through; - structure->color = view_structure.color; - structure->bgcolor = view_structure.bgcolor; + structure->bold = node.bold; + structure->italic = node.italic; + structure->underline = node.underline; + structure->line_through = node.line_through; + structure->color = node.color; + structure->bgcolor = node.bgcolor; - structure->role = view_structure.role; + structure->role = node.role; - structure->class_name = view_structure.class_name; - structure->rect = view_structure.rect; + structure->class_name = node.class_name; + structure->rect = node.rect; - if (view_structure.has_selection) { - structure->selection = gfx::Range(view_structure.start_selection, - view_structure.end_selection); + if (node.selection.has_value()) { + structure->selection = + gfx::Range(node.selection->start(), node.selection->end()); } - for (auto& child : view_structure.children) - structure->children.push_back(CreateVoiceInteractionStructure(*child)); + for (int child : node.children_indices) { + structure->children.push_back( + CreateVoiceInteractionStructure(tree, *tree.nodes[child])); + } return structure; } @@ -97,8 +101,10 @@ title_node->rect = gfx::Rect(bounds.size()); title_node->class_name = "android.view.dummy.WebTitle"; title_node->text = title; + + auto assistant_tree = ui::CreateAssistantTree(update, false); title_node->children.push_back(CreateVoiceInteractionStructure( - *ui::AXSnapshotNodeAndroid::Create(update, false))); + *assistant_tree, *assistant_tree->nodes.front())); root->children.push_back(std::move(title_node)); std::move(callback).Run(std::move(root)); } @@ -334,8 +340,9 @@ // static mojom::VoiceInteractionStructurePtr ArcVoiceInteractionArcHomeService::CreateVoiceInteractionStructureForTesting( - const ui::AXSnapshotNodeAndroid& view_structure) { - return CreateVoiceInteractionStructure(view_structure); + const ui::AssistantTree& tree, + const ui::AssistantNode& node) { + return CreateVoiceInteractionStructure(tree, node); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.h b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.h index 1dc704f..7ed239d3 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.h +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.h
@@ -20,8 +20,9 @@ } // namespace content namespace ui { -struct AXSnapshotNodeAndroid; -} // ui +struct AssistantTree; +struct AssistantNode; +} // namespace ui namespace arc { @@ -66,8 +67,8 @@ void OnVoiceInteractionOobeSetupComplete() override; static mojom::VoiceInteractionStructurePtr - CreateVoiceInteractionStructureForTesting( - const ui::AXSnapshotNodeAndroid& view_structure); + CreateVoiceInteractionStructureForTesting(const ui::AssistantTree& tree, + const ui::AssistantNode& node); void set_assistant_started_timeout_for_testing( const base::TimeDelta& timeout) {
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc index 9a68ae0..9cd93bd 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc
@@ -17,8 +17,8 @@ #include "chrome/test/base/interactive_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" +#include "ui/accessibility/ax_assistant_structure.h" #include "ui/accessibility/ax_tree_update.h" -#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h" namespace arc { @@ -63,9 +63,11 @@ base::Unretained(&waiter)), ui::kAXModeComplete); waiter.Wait(); - auto node = ui::AXSnapshotNodeAndroid::Create(waiter.snapshot(), false); + std::unique_ptr<ui::AssistantTree> tree = + ui::CreateAssistantTree(waiter.snapshot(), false); + return ArcVoiceInteractionArcHomeService:: - CreateVoiceInteractionStructureForTesting(*node); + CreateVoiceInteractionStructureForTesting(*tree, *tree->nodes.front()); } private:
diff --git a/chrome/browser/chromeos/ash_config.cc b/chrome/browser/chromeos/ash_config.cc index 54d61e5..0c18f36f 100644 --- a/chrome/browser/chromeos/ash_config.cc +++ b/chrome/browser/chromeos/ash_config.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/chromeos/ash_config.h" -#include "services/service_manager/runner/common/client_util.h" #include "ui/base/ui_base_features.h" namespace chromeos { @@ -12,15 +11,8 @@ namespace { ash::Config ComputeAshConfig() { - ash::Config config = ash::Config::CLASSIC; - if (base::FeatureList::IsEnabled(features::kMash)) - config = ash::Config::MASH; - else if (base::FeatureList::IsEnabled(features::kMus)) - config = ash::Config::MUS; - VLOG_IF(1, config != ash::Config::CLASSIC && - !service_manager::ServiceManagerIsRemote()) - << " Running with a simulated ash config (likely for testing)."; - return config; + return base::FeatureList::IsEnabled(features::kMash) ? ash::Config::MASH + : ash::Config::CLASSIC; } } // namespace
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc index 18d9170..bf93713 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -11,11 +11,13 @@ #include <utility> #include <vector> +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h" #include "chrome/browser/chromeos/file_manager/fileapi_util.h" @@ -41,6 +43,7 @@ #include "chrome/common/extensions/api/manifest_types.h" #include "chrome/common/pref_names.h" #include "chrome/services/file_util/public/cpp/zip_file_creator.h" +#include "chromeos/chromeos_switches.h" #include "chromeos/settings/timezone_settings.h" #include "components/account_id/account_id.h" #include "components/drive/drive_pref_names.h" @@ -640,6 +643,25 @@ Respond(NoArguments()); } +bool IsCrostiniEnabled() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kCrostiniFiles) && + crostini::CrostiniManager::IsCrosTerminaInstalled(); +} + +ExtensionFunction::ResponseAction +FileManagerPrivateIsCrostiniEnabledFunction::Run() { + return RespondNow( + OneArgument(std::make_unique<base::Value>(IsCrostiniEnabled()))); +} + +ExtensionFunction::ResponseAction +FileManagerPrivateMountCrostiniContainerFunction::Run() { + // TOOD(https://crbug.com/832509): implement MountCrostiniContainer. + DCHECK(IsCrostiniEnabled()); + return RespondNow(NoArguments()); +} + FileManagerPrivateInternalGetCustomActionsFunction:: FileManagerPrivateInternalGetCustomActionsFunction() : chrome_details_(this) {}
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h index 3be6e5d..c745985 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.h
@@ -261,6 +261,34 @@ DISALLOW_COPY_AND_ASSIGN(FileManagerPrivateConfigureVolumeFunction); }; +// Implements the chrome.fileManagerPrivate.isCrostiniEnabled method. +// Gets crostini sftp mount params. +class FileManagerPrivateIsCrostiniEnabledFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.isCrostiniEnabled", + FILEMANAGERPRIVATE_ISCROSTINIENABLED) + + protected: + ~FileManagerPrivateIsCrostiniEnabledFunction() override {} + + ResponseAction Run() override; +}; + +// Implements the chrome.fileManagerPrivate.mountCrostiniContainer method. +// Starts and mounts crostini container. +class FileManagerPrivateMountCrostiniContainerFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.mountCrostiniContainer", + FILEMANAGERPRIVATE_MOUNTCROSTINICONTAINER) + + protected: + ~FileManagerPrivateMountCrostiniContainerFunction() override {} + + ResponseAction Run() override; +}; + // Implements the chrome.fileManagerPrivate.getCustomActions method. class FileManagerPrivateInternalGetCustomActionsFunction : public UIThreadExtensionFunction {
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc index 018ea447..5eafd139 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -724,6 +724,7 @@ SET_STRING("TOTAL_FILE_COUNT", IDS_FILE_BROWSER_TOTAL_FILE_COUNT_LABEL); SET_STRING("IMAGE_RESOLUTION_COLUMN_LABEL", IDS_FILE_BROWSER_IMAGE_RESOLUTION_COLUMN_LABEL); + SET_STRING("LINUX_FILES_ROOT_LABEL", IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL); SET_STRING("MEDIA_ARTIST_COLUMN_LABEL", IDS_FILE_BROWSER_MEDIA_ARTIST_COLUMN_LABEL); SET_STRING("MEDIA_TITLE_COLUMN_LABEL",
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc index c737767..b4692393 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc
@@ -217,7 +217,7 @@ const user_manager::User* const user = chromeos::ProfileHelper::Get()->GetUserByProfile( chrome_details_.GetProfile()); - chromeos::UserContext user_context(user->GetAccountId()); + chromeos::UserContext user_context(*user); user_context.SetKey(chromeos::Key(params->account_password)); // Alter |user_context| if the user is supervised. @@ -554,7 +554,7 @@ const user_manager::User* const user = chromeos::ProfileHelper::Get()->GetUserByProfile( chrome_details_.GetProfile()); - const chromeos::UserContext user_context(user->GetAccountId()); + const chromeos::UserContext user_context(*user); chromeos::EasyUnlockService::Get(chrome_details_.GetProfile()) ->HandleUserReauth(user_context);
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc index 472e795c..cba573f 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -80,7 +80,7 @@ AuthStatusConsumer* auth_status_consumer) { const AccountId account_id = AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); - UserContext expected_context(account_id); + UserContext expected_context(user_manager::USER_TYPE_REGULAR, account_id); expected_context.SetKey(Key(kValidPassword)); ExtendedAuthenticator* authenticator =
diff --git a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc index ccdc360..2321ff2 100644 --- a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
@@ -5,15 +5,22 @@ #include "chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h" #include "chromeos/chromeos_switches.h" +#include "media/base/media_switches.h" namespace file_manager { +static constexpr bool kUseFakeAudioLayer = true; + template <GuestMode MODE> class VideoPlayerBrowserTestBase : public FileManagerBrowserTestBase { public: void SetUpCommandLine(base::CommandLine* command_line) override { + if (kUseFakeAudioLayer) + command_line->AppendSwitch(switches::kDisableAudioOutput); + command_line->AppendSwitch( chromeos::switches::kEnableVideoPlayerChromecastSupport); + FileManagerBrowserTestBase::SetUpCommandLine(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 025e08c1..2a00be6 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -55,15 +55,14 @@ }; class InputMethodEngineBrowserTest - : public ExtensionBrowserTest, + : public extensions::ExtensionBrowserTest, public ::testing::WithParamInterface<TestType> { public: - InputMethodEngineBrowserTest() - : ExtensionBrowserTest() {} + InputMethodEngineBrowserTest() : extensions::ExtensionBrowserTest() {} virtual ~InputMethodEngineBrowserTest() {} void SetUpInProcessBrowserTestFixture() override { - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); } void TearDownInProcessBrowserTestFixture() override { extension_ = NULL; }
diff --git a/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc b/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc index 7a37cd9..5062e812 100644 --- a/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc +++ b/chrome/browser/chromeos/lock_screen_apps/note_taking_browsertest.cc
@@ -70,7 +70,7 @@ DISALLOW_COPY_AND_ASSIGN(LockScreenAppsEnabledWaiter); }; -class LockScreenNoteTakingTest : public ExtensionBrowserTest { +class LockScreenNoteTakingTest : public extensions::ExtensionBrowserTest { public: LockScreenNoteTakingTest() { set_chromeos_user_ = true; } ~LockScreenNoteTakingTest() override = default; @@ -80,7 +80,7 @@ kTestAppId); cmd_line->AppendSwitch(ash::switches::kAshForceEnableStylusTools); - ExtensionBrowserTest::SetUpCommandLine(cmd_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(cmd_line); } bool EnableLockScreenAppLaunch(const std::string& app_id) {
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc index 783c605..12fa986 100644 --- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
@@ -192,7 +192,8 @@ class CryptohomeAuthenticatorTest : public testing::Test { public: CryptohomeAuthenticatorTest() - : user_context_(AccountId::FromUserEmail("me@nowhere.org")), + : user_context_(user_manager::USER_TYPE_REGULAR, + AccountId::FromUserEmail("me@nowhere.org")), user_manager_(new chromeos::FakeChromeUserManager()), user_manager_enabler_(base::WrapUnique(user_manager_)), mock_caller_(NULL),
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc index 0db0930..1ad00ce 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc
@@ -60,7 +60,7 @@ } // namespace -class DemoAppLauncherTest : public ExtensionBrowserTest { +class DemoAppLauncherTest : public extensions::ExtensionBrowserTest { public: DemoAppLauncherTest() { set_exit_when_last_browser_closes(false); } @@ -78,7 +78,7 @@ void SetUp() override { chromeos::DemoAppLauncher::SetDemoAppPathForTesting(GetTestDemoAppPath()); - ExtensionBrowserTest::SetUp(); + extensions::ExtensionBrowserTest::SetUp(); } private:
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc index 7b62f7dc..743088e0 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -476,8 +476,11 @@ UserSessionManager::GetInstance()->GetEasyUnlockKeyManager(); DCHECK(key_manager); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + DCHECK(user); key_manager->GetDeviceDataList( - UserContext(account_id), + UserContext(*user), base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking, weak_ptr_factory_.GetWeakPtr(), account_id, paired_devices)); }
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc index a228cf60..4b9e906 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
@@ -95,8 +95,11 @@ UserSessionManager::GetInstance()->GetEasyUnlockKeyManager(); DCHECK(key_manager); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + DCHECK(user); key_manager->GetDeviceDataList( - UserContext(account_id), + UserContext(*user), base::Bind(&RetryDataLoadOnError, account_id, backoff_ms, callback)); }
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 522f81fc..03c626a 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -983,8 +983,9 @@ // Inform |auth_status_consumer_| about successful login. // TODO(nkostylev): Pass UserContext back crbug.com/424550 if (auth_status_consumer_) { - auth_status_consumer_->OnAuthSuccess( - UserContext(last_login_attempt_account_id_)); + const user_manager::User* const user = + chromeos::ProfileHelper::Get()->GetUserByProfile(profile); + auth_status_consumer_->OnAuthSuccess(UserContext(*user)); } }
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index a185c4c..c428624 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -243,7 +243,9 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest, DISABLED_ExistingUserLogin) { EXPECT_CALL(*mock_login_display_, SetUIEnabled(false)).Times(2); - UserContext user_context(gaia_account_id_); + const user_manager::User* user = + user_manager::UserManager::Get()->FindUser(gaia_account_id_); + UserContext user_context(*user); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); test::UserSessionManagerTestApi session_manager_test_api( @@ -290,7 +292,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest, ExistingUserLoginForbidden) { - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); existing_user_controller()->Login(user_context, SigninSpecifics()); @@ -304,7 +307,8 @@ #endif IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest, MAYBE_NewUserLoginForbidden) { - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); existing_user_controller()->CompleteLogin(user_context); @@ -319,7 +323,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest, SupervisedUserLoginForbidden) { - UserContext user_context(AccountId::FromUserEmail(kSupervisedUserID)); + UserContext user_context(user_manager::UserType::USER_TYPE_SUPERVISED, + AccountId::FromUserEmail(kSupervisedUserID)); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); existing_user_controller()->Login(user_context, SigninSpecifics()); @@ -588,7 +593,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest, DISABLED_LoginStopsAutoLogin) { // Set up mocks to check login success. - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(user_context.GetAccountId().GetUserEmail()); ExpectSuccessfulLogin(user_context); @@ -620,7 +626,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest, GuestModeLoginStopsAutoLogin) { EXPECT_CALL(*mock_login_display_, SetUIEnabled(false)).Times(2); - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); test::UserSessionManagerTestApi session_manager_test_api( UserSessionManager::GetInstance()); @@ -649,7 +656,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest, CompleteLoginStopsAutoLogin) { // Set up mocks to check login success. - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(user_context.GetAccountId().GetUserEmail()); ExpectSuccessfulLogin(user_context); @@ -719,7 +727,8 @@ // Check that the attempt to start a public session fails with an error. ExpectLoginFailure(); - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(user_context.GetAccountId().GetUserEmail()); existing_user_controller()->Login(user_context, SigninSpecifics()); @@ -910,7 +919,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, ActiveDirectoryOnlineLogin_Success) { ExpectLoginSuccess(); - UserContext user_context(ad_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + ad_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(ad_account_id_.GetUserEmail()); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); @@ -930,7 +940,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, PolicyChangeTriggersFileUpdate) { ExpectLoginSuccess(); - UserContext user_context(ad_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + ad_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(ad_account_id_.GetUserEmail()); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); @@ -956,7 +967,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, ActiveDirectoryOfflineLogin_Success) { ExpectLoginSuccess(); - UserContext user_context(ad_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + ad_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(ad_account_id_.GetUserEmail()); ASSERT_EQ(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, @@ -975,7 +987,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, GAIAAccountLogin_Failure) { ExpectLoginFailure(); - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); existing_user_controller()->CompleteLogin(user_context); @@ -985,7 +998,8 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryUserWhitelistTest, Success) { ExpectLoginSuccess(); - UserContext user_context(ad_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + ad_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(ad_account_id_.GetUserEmail()); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); @@ -1005,7 +1019,8 @@ ExpectLoginWhitelistFailure(); AccountId account_id = AccountId::AdFromUserEmailObjGuid(kUserNotMatchingWhitelist, kGaiaID); - UserContext user_context(account_id); + UserContext user_context(user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, + account_id); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(account_id.GetUserEmail()); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); @@ -1029,7 +1044,8 @@ // profile prefs. IN_PROC_BROWSER_TEST_F(ExistingUserControllerSavePasswordHashTest, GaiaOnlineLoginSavesPasswordHashToPrefs) { - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); content::WindowedNotificationObserver profile_prepared_observer( @@ -1052,7 +1068,8 @@ // prefs. IN_PROC_BROWSER_TEST_F(ExistingUserControllerSavePasswordHashTest, OfflineLoginSavesPasswordHashToPrefs) { - UserContext user_context(gaia_account_id_); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + gaia_account_id_); user_context.SetKey(Key(kPassword)); user_context.SetUserIDHash(gaia_account_id_.GetUserEmail()); content::WindowedNotificationObserver profile_prepared_observer(
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc index 61630bb..5091a56 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -693,7 +693,7 @@ return; } - UserContext user_context(active_user->GetType(), active_user->GetAccountId()); + UserContext user_context(*active_user); if (!base::ContainsKey(matches, active_user->username_hash())) { OnFingerprintAuthFailure(*active_user); return;
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc index d3475f8c..446da6ec 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -169,7 +169,8 @@ EXPECT_GT(lock_bounds.width(), 10); EXPECT_GT(lock_bounds.height(), 10); - UserContext user_context(user_manager::StubAccountId()); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + user_manager::StubAccountId()); user_context.SetKey(Key("pass")); tester->InjectStubUserContext(user_context); EXPECT_TRUE(tester->IsLocked()); @@ -227,7 +228,8 @@ EXPECT_FALSE(window_state->GetHideShelfWhenFullscreen()); EXPECT_TRUE(tester->IsLocked()); } - UserContext user_context(user_manager::StubAccountId()); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + user_manager::StubAccountId()); user_context.SetKey(Key("pass")); tester->InjectStubUserContext(user_context); tester->EnterPassword("pass");
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc index 923ea9be..7c8e3a85 100644 --- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -172,7 +172,10 @@ quick_unlock_storage->IsPinAuthenticationAvailable() || !authenticated_by_pin); - UserContext user_context(account_id); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + DCHECK(user); + UserContext user_context(*user); Key::KeyType key_type = authenticated_by_pin ? chromeos::Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234 : chromeos::Key::KEY_TYPE_SALTED_SHA256_TOP_HALF;
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index fad1ec3..4171c7b 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -173,6 +173,7 @@ StartGaiaAuthOffline(); UserContext user_context( + user_manager::UserType::USER_TYPE_REGULAR, AccountId::FromUserEmailGaiaId(kTestUser, kGaiaId)); user_context.SetKey(Key(kPassword)); SetExpectedCredentials(user_context);
diff --git a/chrome/browser/chromeos/login/login_manager_test.cc b/chrome/browser/chromeos/login/login_manager_test.cc index 5a1d61d9..5a076fc 100644 --- a/chrome/browser/chromeos/login/login_manager_test.cc +++ b/chrome/browser/chromeos/login/login_manager_test.cc
@@ -52,7 +52,8 @@ constexpr char kTestRefreshToken2[] = "fake-refresh-token-2"; UserContext CreateUserContext(const AccountId& account_id) { - UserContext user_context(account_id); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + account_id); user_context.SetKey(Key("password")); if (account_id.GetUserEmail() == LoginManagerTest::kEnterpriseUser1) { user_context.SetRefreshToken(kTestRefreshToken1);
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc index fdd0c31..cbdfddc 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -749,7 +749,10 @@ const std::string& key_label) { DCHECK_EQ(GetScreenType(), SIGNIN_SCREEN); - UserContext user_context(account_id); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + DCHECK(user); + UserContext user_context(*user); user_context.SetAuthFlow(UserContext::AUTH_FLOW_EASY_UNLOCK); user_context.SetKey(Key(secret)); user_context.GetKey()->SetLabel(key_label);
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 65561208..0123894 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1737,6 +1737,11 @@ pending_user_sessions_.erase(account_id); // Check that this user is not logged in yet. + + // TODO(alemate): Investigate whether this could be simplified by enforcing + // session restore to existing users only. Currently this breakes some tests + // (namely CrashRestoreComplexTest.RestoreSessionForThreeUsers), but + // it may be test-specific and could probably be changed. user_manager::UserList logged_in_users = user_manager::UserManager::Get()->GetLoggedInUsers(); bool user_already_logged_in = false; @@ -1751,7 +1756,12 @@ DCHECK(!user_already_logged_in); if (!user_already_logged_in) { - UserContext user_context(account_id); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + UserContext user_context = + user ? UserContext(*user) + : UserContext(user_manager::UserType::USER_TYPE_REGULAR, + account_id); user_context.SetUserIDHash(user_id_hash); user_context.SetIsUsingOAuth(false);
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc index 03b0bc4c..1bacf692 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -336,7 +336,8 @@ return false; } - UserContext user_context(account_id); + UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + account_id); user_context.SetKey(Key(password)); controller->Login(user_context, SigninSpecifics()); content::WindowedNotificationObserver( @@ -657,6 +658,7 @@ ExistingUserController* const controller = ExistingUserController::current_controller(); UserContext user_context( + user_manager::USER_TYPE_REGULAR, AccountId::FromUserEmailGaiaId(kTestEmail, kTestGaiaId)); user_context.SetKey(Key(kTestAccountPassword)); controller->Login(user_context, SigninSpecifics());
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc index ac2b215..33d83b0 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -205,7 +205,14 @@ controller_.reset(new SupervisedUserCreationControllerNew(this, manager_id)); - UserContext user_context(manager_id); + const user_manager::User* const manager = + user_manager::UserManager::Get()->FindUser(manager_id); + // Tests depend on the ability to create users on-demand, so we cannot + // require manager to exist here. + UserContext user_context = + manager + ? UserContext(*manager) + : UserContext(user_manager::UserType::USER_TYPE_REGULAR, manager_id); user_context.SetKey(Key(manager_password)); ExistingUserController::current_controller()->Login(user_context, SigninSpecifics());
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc index 7b729f37..652f1aa 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -215,7 +215,10 @@ on_authenticated_ = std::move(callback); - UserContext user_context(account_id); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + DCHECK(user); + UserContext user_context(*user); user_context.SetKey(Key(chromeos::Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, std::string(), hashed_password)); user_context.SetSyncPasswordData(sync_password_data);
diff --git a/chrome/browser/chromeos/policy/affiliation_test_helper.cc b/chrome/browser/chromeos/policy/affiliation_test_helper.cc index 33b8883..cfe65d7 100644 --- a/chrome/browser/chromeos/policy/affiliation_test_helper.cc +++ b/chrome/browser/chromeos/policy/affiliation_test_helper.cc
@@ -117,7 +117,8 @@ chromeos::UserSessionManager::GetInstance()); session_manager_test_api.SetShouldObtainTokenHandleInTests(false); - chromeos::UserContext user_context(account_id); + chromeos::UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, + account_id); user_context.SetKey(chromeos::Key("password")); if (account_id.GetUserEmail() == kEnterpriseUserEmail) { user_context.SetRefreshToken(kFakeRefreshToken);
diff --git a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc index 32168051..16a815e 100644 --- a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
@@ -244,7 +244,7 @@ // must be false. const bool cannot_tell_if_policy_required = (requires_policy_user_property == ProfileRequiresPolicy::kUnknown) && - !is_stub_user && + !is_stub_user && !is_active_directory && !command_line->HasSwitch(chromeos::switches::kProfileRequiresPolicy) && !command_line->HasSwitch( chromeos::switches::kAllowFailedPolicyFetchForTest); @@ -275,12 +275,13 @@ // command-line flag (required for ephemeral users who are not persisted // in the known_user database). const bool policy_required = - !command_line->HasSwitch( - chromeos::switches::kAllowFailedPolicyFetchForTest) && - ((requires_policy_user_property == - ProfileRequiresPolicy::kPolicyRequired) || - (command_line->GetSwitchValueASCII( - chromeos::switches::kProfileRequiresPolicy) == "true")); + is_active_directory || + (!command_line->HasSwitch( + chromeos::switches::kAllowFailedPolicyFetchForTest) && + ((requires_policy_user_property == + ProfileRequiresPolicy::kPolicyRequired) || + (command_line->GetSwitchValueASCII( + chromeos::switches::kProfileRequiresPolicy) == "true"))); DCHECK(!(cannot_tell_if_policy_required && policy_required));
diff --git a/chrome/browser/chromeos/printing/printers_sync_bridge.cc b/chrome/browser/chromeos/printing/printers_sync_bridge.cc index 67a40d4..6c4f1020 100644 --- a/chrome/browser/chromeos/printing/printers_sync_bridge.cc +++ b/chrome/browser/chromeos/printing/printers_sync_bridge.cc
@@ -73,6 +73,7 @@ store_->CommitWriteBatch( std::move(batch), base::BindOnce(&StoreProxy::OnCommit, weak_ptr_factory_.GetWeakPtr())); + owner_->NotifyPrintersUpdated(); } private:
diff --git a/chrome/browser/component_updater/sth_set_component_installer.cc b/chrome/browser/component_updater/sth_set_component_installer.cc index 2c88ad1..962ae51 100644 --- a/chrome/browser/component_updater/sth_set_component_installer.cc +++ b/chrome/browser/component_updater/sth_set_component_installer.cc
@@ -22,14 +22,15 @@ #include "base/values.h" #include "base/version.h" #include "chrome/browser/after_startup_task_utils.h" -#include "chrome/browser/net/sth_distributor_provider.h" -#include "components/certificate_transparency/sth_distributor.h" #include "components/certificate_transparency/sth_observer.h" #include "components/component_updater/component_updater_paths.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "crypto/sha2.h" #include "net/cert/ct_log_response_parser.h" #include "net/cert/signed_tree_head.h" +#include "services/network/network_service.h" +#include "services/service_manager/public/cpp/service.h" using component_updater::ComponentUpdateService; @@ -42,27 +43,6 @@ .Append(kSTHsDirName); } -// Lives and dies on the UI thread, but proxies notifications to the IO -// thread to notify the chrome_browser_net::GetGlobalSTHDistributor(), as -// it always lives on the IO thread. -class IOThreadSTHObserver : public certificate_transparency::STHObserver { - public: - ~IOThreadSTHObserver() override = default; - - void NewSTHObserved(const net::ct::SignedTreeHead& sth) override { - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce( - [](const net::ct::SignedTreeHead& sth) { - certificate_transparency::STHObserver* observer = - chrome_browser_net::GetGlobalSTHDistributor(); - if (observer) - observer->NewSTHObserved(sth); - }, - sth)); - } -}; - // Loads the STHs from |sths_path|, which contains a series of files that // are the in the form "[log_id].sth", where [log_id] is the hex-encoded ID // of the log, and the contents are JSON STH. Parsed STHs will be posted to @@ -150,15 +130,15 @@ const char kSTHSetFetcherManifestName[] = "Signed Tree Heads"; -STHSetComponentInstallerPolicy::STHSetComponentInstallerPolicy( - std::unique_ptr<certificate_transparency::STHObserver> sth_observer) - : sth_observer_(std::move(sth_observer)), weak_ptr_factory_(this) {} +STHSetComponentInstallerPolicy::STHSetComponentInstallerPolicy() + : weak_ptr_factory_(this) {} STHSetComponentInstallerPolicy::~STHSetComponentInstallerPolicy() = default; -void STHSetComponentInstallerPolicy::NewSTHObserved( - const net::ct::SignedTreeHead& sth) { - sth_observer_->NewSTHObserved(sth); +void STHSetComponentInstallerPolicy::SetNetworkServiceForTesting( + network::mojom::NetworkService* network_service) { + DCHECK(network_service); + network_service_for_testing_ = network_service; } bool STHSetComponentInstallerPolicy:: @@ -166,6 +146,16 @@ return false; } +void STHSetComponentInstallerPolicy::OnSTHLoaded( + const net::ct::SignedTreeHead& sth) { + // TODO(rsleevi): https://crbug.com/840444 - Ensure the network service + // is notified of the STHs if it crashes/restarts. + network::mojom::NetworkService* network_service = + network_service_for_testing_ ? network_service_for_testing_ + : content::GetNetworkService(); + network_service->UpdateSignedTreeHead(sth); +} + // Public data is delivered via this component, no need for encryption. bool STHSetComponentInstallerPolicy::RequiresNetworkEncryption() const { return false; @@ -195,7 +185,7 @@ base::BindOnce( &LoadSTHsFromDisk, GetInstalledPath(install_dir), base::SequencedTaskRunnerHandle::Get(), - base::BindRepeating(&STHSetComponentInstallerPolicy::NewSTHObserved, + base::BindRepeating(&STHSetComponentInstallerPolicy::OnSTHLoaded, weak_ptr_factory_.GetWeakPtr()))); } @@ -231,10 +221,8 @@ void RegisterSTHSetComponent(ComponentUpdateService* cus, const base::FilePath& user_data_dir) { DVLOG(1) << "Registering STH Set fetcher component."; - auto installer = base::MakeRefCounted<ComponentInstaller>( - std::make_unique<STHSetComponentInstallerPolicy>( - std::make_unique<IOThreadSTHObserver>())); + std::make_unique<STHSetComponentInstallerPolicy>()); installer->Register(cus, base::Closure()); }
diff --git a/chrome/browser/component_updater/sth_set_component_installer.h b/chrome/browser/component_updater/sth_set_component_installer.h index 4049b92..bf14080 100644 --- a/chrome/browser/component_updater/sth_set_component_installer.h +++ b/chrome/browser/component_updater/sth_set_component_installer.h
@@ -15,16 +15,18 @@ #include "base/memory/weak_ptr.h" #include "components/component_updater/component_installer.h" -namespace certificate_transparency { -class STHObserver; -} // namespace certificate_transparency - namespace net { namespace ct { struct SignedTreeHead; } // namespace ct } // namespace net +namespace network { +namespace mojom { +class NetworkService; +} // namespace mojom +} // namespace network + namespace component_updater { class ComponentUpdateService; @@ -41,15 +43,16 @@ // persistence. class STHSetComponentInstallerPolicy : public ComponentInstallerPolicy { public: - // The |sth_observer| will be notified each time a new STH is observed. - explicit STHSetComponentInstallerPolicy( - std::unique_ptr<certificate_transparency::STHObserver> sth_observer); + STHSetComponentInstallerPolicy(); ~STHSetComponentInstallerPolicy() override; private: friend class STHSetComponentInstallerTest; + void SetNetworkServiceForTesting( + network::mojom::NetworkService* network_service); - void NewSTHObserved(const net::ct::SignedTreeHead& sth); + // Indicates that a new STH has been loaded. + void OnSTHLoaded(const net::ct::SignedTreeHead& sth); // ComponentInstallerPolicy implementation. bool SupportsGroupPolicyEnabledComponentUpdates() const override; @@ -69,7 +72,7 @@ update_client::InstallerAttributes GetInstallerAttributes() const override; std::vector<std::string> GetMimeTypes() const override; - std::unique_ptr<certificate_transparency::STHObserver> sth_observer_; + network::mojom::NetworkService* network_service_for_testing_ = nullptr; base::WeakPtrFactory<STHSetComponentInstallerPolicy> weak_ptr_factory_;
diff --git a/chrome/browser/component_updater/sth_set_component_installer_unittest.cc b/chrome/browser/component_updater/sth_set_component_installer_unittest.cc index 62793cfe..67bb1e7 100644 --- a/chrome/browser/component_updater/sth_set_component_installer_unittest.cc +++ b/chrome/browser/component_updater/sth_set_component_installer_unittest.cc
@@ -19,10 +19,12 @@ #include "base/version.h" #include "chrome/browser/after_startup_task_utils.h" #include "components/certificate_transparency/sth_observer.h" +#include "components/certificate_transparency/sth_reporter.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/cert/signed_tree_head.h" #include "net/test/ct_test_util.h" #include "services/data_decoder/public/cpp/testing_json_parser.h" +#include "services/network/network_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -39,8 +41,14 @@ class STHSetComponentInstallerTest : public PlatformTest { public: - STHSetComponentInstallerTest() { + STHSetComponentInstallerTest() : network_service_(nullptr) { AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting(); + + network_service_.sth_reporter()->RegisterObserver(&observer_); + } + + ~STHSetComponentInstallerTest() override { + network_service_.sth_reporter()->UnregisterObserver(&observer_); } void SetUp() override { @@ -48,11 +56,8 @@ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - std::unique_ptr<StoringSTHObserver> observer = - std::make_unique<StoringSTHObserver>(); - observer_ = observer.get(); - policy_ = - std::make_unique<STHSetComponentInstallerPolicy>(std::move(observer)); + policy_ = std::make_unique<STHSetComponentInstallerPolicy>(); + policy_->SetNetworkServiceForTesting(&network_service_); } void WriteSTHToFile(const std::string& sth_json, @@ -87,10 +92,11 @@ protected: content::TestBrowserThreadBundle thread_bundle_; + network::NetworkService network_service_; + StoringSTHObserver observer_; + base::ScopedTempDir temp_dir_; std::unique_ptr<STHSetComponentInstallerPolicy> policy_; - // Note that |observer_| is owned by |policy_|. - StoringSTHObserver* observer_ = nullptr; data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_; private: @@ -114,15 +120,15 @@ LoadSTHs(manifest, sths_dir); - EXPECT_EQ(2u, observer_->sths.size()); + EXPECT_EQ(2u, observer_.sths.size()); const std::string first_log_id("abc"); - ASSERT_TRUE(observer_->sths.find(first_log_id) != observer_->sths.end()); - const net::ct::SignedTreeHead& first_sth(observer_->sths[first_log_id]); + ASSERT_TRUE(observer_.sths.find(first_log_id) != observer_.sths.end()); + const net::ct::SignedTreeHead& first_sth(observer_.sths[first_log_id]); EXPECT_EQ(21u, first_sth.tree_size); const std::string second_log_id("a\00d", 3); - ASSERT_TRUE(observer_->sths.find(second_log_id) != observer_->sths.end()); + ASSERT_TRUE(observer_.sths.find(second_log_id) != observer_.sths.end()); } // Does not notify of invalid STH JSON. @@ -136,7 +142,7 @@ WriteSTHToFile(std::string("{invalid json}"), invalid_sth); LoadSTHs(manifest, sths_dir); - EXPECT_EQ(0u, observer_->sths.size()); + EXPECT_EQ(0u, observer_.sths.size()); } // Does not notify of valid JSON but in a file not hex-encoded log id. @@ -151,7 +157,7 @@ WriteSTHToFile(net::ct::GetSampleSTHAsJson(), not_hex_sth_file); LoadSTHs(manifest, sths_dir); - EXPECT_EQ(0u, observer_->sths.size()); + EXPECT_EQ(0u, observer_.sths.size()); } } // namespace component_updater
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index b21faa7..075b517 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -2178,6 +2178,13 @@ DevToolsWindowTesting::CloseDevToolsWindowSync(window_); } +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DisposeEmptyBrowserContext) { + window_ = + DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(), false); + RunTestMethod("testDisposeEmptyBrowserContext"); + DevToolsWindowTesting::CloseDevToolsWindowSync(window_); +} + IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsSanityTest, InspectElement) { GURL url(embedded_test_server()->GetURL("a.com", "/devtools/oopif.html")); GURL iframe_url(
diff --git a/chrome/browser/devtools/inspector_protocol_config.json b/chrome/browser/devtools/inspector_protocol_config.json index 96b580a7..38dfa64c 100644 --- a/chrome/browser/devtools/inspector_protocol_config.json +++ b/chrome/browser/devtools/inspector_protocol_config.json
@@ -18,7 +18,8 @@ }, { "domain": "Target", - "include": [ "setRemoteLocations", "createBrowserContext", "createTarget", "disposeBrowserContext" ], + "include": [ "setRemoteLocations", "createBrowserContext", "getBrowserContexts", "createTarget", "disposeBrowserContext" ], + "async": ["disposeBrowserContext"], "include_events": [] }, {
diff --git a/chrome/browser/devtools/protocol/target_handler.cc b/chrome/browser/devtools/protocol/target_handler.cc index cb544fe..f5c6272 100644 --- a/chrome/browser/devtools/protocol/target_handler.cc +++ b/chrome/browser/devtools/protocol/target_handler.cc
@@ -11,8 +11,146 @@ #include "chrome/browser/ui/browser_navigator.h" #include "content/public/browser/devtools_agent_host.h" -TargetHandler::TargetHandler(protocol::UberDispatcher* dispatcher) - : weak_factory_(this) { +namespace { + +class DevToolsBrowserContextManager : public BrowserListObserver { + public: + DevToolsBrowserContextManager(); + protocol::Response CreateBrowserContext(std::string* out_context_id); + protocol::Response GetBrowserContexts( + std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids); + Profile* GetBrowserContext(const std::string& context_id); + void DisposeBrowserContext( + const std::string& context_id, + std::unique_ptr<TargetHandler::DisposeBrowserContextCallback> callback); + + private: + void OnOriginalProfileDestroyed(Profile* profile); + + void OnBrowserRemoved(Browser* browser) override; + + base::flat_map< + std::string, + std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration>> + registrations_; + base::flat_map<std::string, + std::unique_ptr<TargetHandler::DisposeBrowserContextCallback>> + pending_context_disposals_; + + base::WeakPtrFactory<DevToolsBrowserContextManager> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserContextManager); +}; + +DevToolsBrowserContextManager::DevToolsBrowserContextManager() + : weak_factory_(this) {} + +Profile* DevToolsBrowserContextManager::GetBrowserContext( + const std::string& context_id) { + auto it = registrations_.find(context_id); + return it == registrations_.end() ? nullptr : it->second->profile(); +} + +protocol::Response DevToolsBrowserContextManager::CreateBrowserContext( + std::string* out_context_id) { + Profile* original_profile = + ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); + + auto registration = + IndependentOTRProfileManager::GetInstance()->CreateFromOriginalProfile( + original_profile, + base::BindOnce( + &DevToolsBrowserContextManager::OnOriginalProfileDestroyed, + weak_factory_.GetWeakPtr())); + *out_context_id = registration->profile()->UniqueId(); + registrations_[*out_context_id] = std::move(registration); + return protocol::Response::OK(); +} + +protocol::Response DevToolsBrowserContextManager::GetBrowserContexts( + std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) { + *browser_context_ids = std::make_unique<protocol::Array<protocol::String>>(); + for (const auto& registration_pair : registrations_) { + (*browser_context_ids) + ->addItem(registration_pair.second->profile()->UniqueId()); + } + return protocol::Response::OK(); +} + +void DevToolsBrowserContextManager::DisposeBrowserContext( + const std::string& context_id, + std::unique_ptr<TargetHandler::DisposeBrowserContextCallback> callback) { + if (pending_context_disposals_.find(context_id) != + pending_context_disposals_.end()) { + callback->sendFailure(protocol::Response::Error( + "Disposal of browser context " + context_id + " is already pending")); + return; + } + auto it = registrations_.find(context_id); + if (it == registrations_.end()) { + callback->sendFailure(protocol::Response::InvalidParams( + "Failed to find browser context with id " + context_id)); + return; + } + + Profile* profile = it->second->profile(); + bool has_opened_browser = false; + for (auto* opened_browser : *BrowserList::GetInstance()) { + if (opened_browser->profile() == profile) { + has_opened_browser = true; + break; + } + } + + // If no browsers are opened - dispose right away. + if (!has_opened_browser) { + registrations_.erase(it); + callback->sendSuccess(); + return; + } + + if (pending_context_disposals_.empty()) + BrowserList::AddObserver(this); + + pending_context_disposals_[context_id] = std::move(callback); + BrowserList::CloseAllBrowsersWithIncognitoProfile( + profile, base::DoNothing(), base::DoNothing(), + true /* skip_beforeunload */); +} + +void DevToolsBrowserContextManager::OnOriginalProfileDestroyed( + Profile* profile) { + base::EraseIf(registrations_, [&profile](const auto& it) { + return it.second->profile()->GetOriginalProfile() == profile; + }); +} + +void DevToolsBrowserContextManager::OnBrowserRemoved(Browser* browser) { + std::string context_id = browser->profile()->UniqueId(); + auto pending_disposal = pending_context_disposals_.find(context_id); + if (pending_disposal == pending_context_disposals_.end()) + return; + for (auto* opened_browser : *BrowserList::GetInstance()) { + if (opened_browser->profile() == browser->profile()) + return; + } + auto it = registrations_.find(context_id); + // We cannot delete immediately here: the profile might still be referenced + // during the browser tier-down process. + base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, + it->second.release()); + registrations_.erase(it); + pending_disposal->second->sendSuccess(); + pending_context_disposals_.erase(pending_disposal); + if (pending_context_disposals_.empty()) + BrowserList::RemoveObserver(this); +} + +base::LazyInstance<DevToolsBrowserContextManager>::Leaky + g_devtools_browser_context_manager; + +} // namespace + +TargetHandler::TargetHandler(protocol::UberDispatcher* dispatcher) { protocol::Target::Dispatcher::wire(dispatcher, this); } @@ -21,7 +159,6 @@ ChromeDevToolsManagerDelegate::GetInstance(); if (delegate) delegate->UpdateDeviceDiscovery(); - registrations_.clear(); } protocol::Response TargetHandler::SetRemoteLocations( @@ -54,12 +191,12 @@ Profile* profile = ProfileManager::GetActiveUserProfile(); if (browser_context_id.isJust()) { std::string profile_id = browser_context_id.fromJust(); - auto it = registrations_.find(profile_id); - if (it == registrations_.end()) { + profile = + g_devtools_browser_context_manager.Get().GetBrowserContext(profile_id); + if (!profile) { return protocol::Response::Error( "Failed to find browser context with id " + profile_id); } - profile = it->second->profile(); } NavigateParams params(profile, GURL(url), ui::PAGE_TRANSITION_AUTO_TOPLEVEL); @@ -92,42 +229,20 @@ protocol::Response TargetHandler::CreateBrowserContext( std::string* out_context_id) { - Profile* original_profile = - ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); - - auto registration = - IndependentOTRProfileManager::GetInstance()->CreateFromOriginalProfile( - original_profile, - base::BindOnce(&TargetHandler::OnOriginalProfileDestroyed, - weak_factory_.GetWeakPtr())); - *out_context_id = registration->profile()->UniqueId(); - registrations_[*out_context_id] = std::move(registration); - return protocol::Response::OK(); + return g_devtools_browser_context_manager.Get().CreateBrowserContext( + out_context_id); } -void TargetHandler::OnOriginalProfileDestroyed(Profile* profile) { - base::EraseIf(registrations_, [&profile](const auto& it) { - return it.second->profile()->GetOriginalProfile() == profile; - }); +protocol::Response TargetHandler::GetBrowserContexts( + std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) { + return g_devtools_browser_context_manager.Get().GetBrowserContexts( + browser_context_ids); } -protocol::Response TargetHandler::DisposeBrowserContext( +void TargetHandler::DisposeBrowserContext( const std::string& context_id, - bool* out_success) { - auto it = registrations_.find(context_id); - if (it == registrations_.end()) { - return protocol::Response::Error("Failed to find browser context with id " + - context_id); - } - Profile* profile = it->second->profile(); - for (auto* browser : *BrowserList::GetInstance()) { - if (browser->profile() == profile && - !browser->IsAttemptingToCloseBrowser()) { - *out_success = false; - return protocol::Response::OK(); - } - } - registrations_.erase(it); - *out_success = true; - return protocol::Response::OK(); + std::unique_ptr<DisposeBrowserContextCallback> callback) { + g_devtools_browser_context_manager.Get().DisposeBrowserContext( + context_id, std::move(callback)); } +
diff --git a/chrome/browser/devtools/protocol/target_handler.h b/chrome/browser/devtools/protocol/target_handler.h index bfff3d0..e9933b09 100644 --- a/chrome/browser/devtools/protocol/target_handler.h +++ b/chrome/browser/devtools/protocol/target_handler.h
@@ -11,6 +11,8 @@ #include "chrome/browser/devtools/protocol/forward.h" #include "chrome/browser/devtools/protocol/target.h" #include "chrome/browser/media/router/presentation/independent_otr_profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list_observer.h" #include "net/base/host_port_pair.h" using RemoteLocations = std::set<net::HostPortPair>; @@ -34,20 +36,16 @@ protocol::Maybe<std::string> browser_context_id, protocol::Maybe<bool> enable_begin_frame_control, std::string* out_target_id) override; - protocol::Response DisposeBrowserContext(const std::string& context_id, - bool* out_success) override; + protocol::Response GetBrowserContexts( + std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) + override; + void DisposeBrowserContext( + const std::string& context_id, + std::unique_ptr<DisposeBrowserContextCallback> callback) override; private: - void OnOriginalProfileDestroyed(Profile* profile); - - base::flat_map< - std::string, - std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration>> - registrations_; RemoteLocations remote_locations_; - base::WeakPtrFactory<TargetHandler> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(TargetHandler); };
diff --git a/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc b/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc index 752600ca..2289c0a 100644 --- a/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc +++ b/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc
@@ -181,10 +181,8 @@ { scoped_refptr<Extension> auto_launch_kiosk_app( ExtensionBuilder("Test", ExtensionBuilder::Type::PLATFORM_APP) - .MergeManifest(DictionaryBuilder() - .Set("kiosk_enabled", true) - .Set("kiosk_only", true) - .Build()) + .SetManifestKey("kiosk_enabled", true) + .SetManifestKey("kiosk_only", true) .Build()); user_manager_->AddKioskAppUser( AccountId::FromUserEmail(auto_launch_kiosk_app->id())); @@ -211,10 +209,8 @@ // receiving approval from the user. scoped_refptr<Extension> manual_launch_kiosk_app( ExtensionBuilder("Test", ExtensionBuilder::Type::PLATFORM_APP) - .MergeManifest(DictionaryBuilder() - .Set("kiosk_enabled", true) - .Set("kiosk_only", true) - .Build()) + .SetManifestKey("kiosk_enabled", true) + .SetManifestKey("kiosk_only", true) .Build()); user_manager::User* const manual_kiosk_app_user = user_manager_->AddKioskAppUser(
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc index 9c24f96..8b5c6e49 100644 --- a/chrome/browser/extensions/api/identity/identity_apitest.cc +++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -1955,14 +1955,11 @@ scoped_refptr<Extension> CreateTestExtension(const std::string& id) { return ExtensionBuilder("Test") - .MergeManifest( - DictionaryBuilder() - .Set("oauth2", - DictionaryBuilder() - .Set("client_id", "clientId") - .Set("scopes", ListBuilder().Append("scope1").Build()) - .Build()) - .Build()) + .SetManifestKey( + "oauth2", DictionaryBuilder() + .Set("client_id", "clientId") + .Set("scopes", ListBuilder().Append("scope1").Build()) + .Build()) .SetID(id) .Build(); }
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc index 47481fc..adba1640 100644 --- a/chrome/browser/extensions/api/management/management_browsertest.cc +++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -59,7 +59,7 @@ } // namespace -class ExtensionManagementTest : public ExtensionBrowserTest { +class ExtensionManagementTest : public extensions::ExtensionBrowserTest { public: void SetUpInProcessBrowserTestFixture() override { EXPECT_CALL(policy_provider_, IsInitializationComplete(_))
diff --git a/chrome/browser/extensions/background_app_browsertest.cc b/chrome/browser/extensions/background_app_browsertest.cc index f704c2b..e4647ab 100644 --- a/chrome/browser/extensions/background_app_browsertest.cc +++ b/chrome/browser/extensions/background_app_browsertest.cc
@@ -44,7 +44,7 @@ DISALLOW_COPY_AND_ASSIGN(TestBackgroundModeManager); }; -class BackgroundAppBrowserTest: public ExtensionBrowserTest {}; +using BackgroundAppBrowserTest = extensions::ExtensionBrowserTest; // Tests that if we reload a background app, we don't get a popup bubble // telling us that a new background app has been installed.
diff --git a/chrome/browser/extensions/chrome_app_api_browsertest.cc b/chrome/browser/extensions/chrome_app_api_browsertest.cc index 978739c6..fc02b55 100644 --- a/chrome/browser/extensions/chrome_app_api_browsertest.cc +++ b/chrome/browser/extensions/chrome_app_api_browsertest.cc
@@ -25,9 +25,9 @@ using extensions::Extension; -class ChromeAppAPITest : public ExtensionBrowserTest { +class ChromeAppAPITest : public extensions::ExtensionBrowserTest { void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(embedded_test_server()->Start()); }
diff --git a/chrome/browser/extensions/chrome_ui_overrides_browsertest.cc b/chrome/browser/extensions/chrome_ui_overrides_browsertest.cc index 0065195..62b1b17 100644 --- a/chrome/browser/extensions/chrome_ui_overrides_browsertest.cc +++ b/chrome/browser/extensions/chrome_ui_overrides_browsertest.cc
@@ -8,7 +8,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/common/url_constants.h" -class ChromeUIOverridesBrowserTest : public ExtensionBrowserTest {}; +using ChromeUIOverridesBrowserTest = extensions::ExtensionBrowserTest; IN_PROC_BROWSER_TEST_F(ChromeUIOverridesBrowserTest, BookmarkShortcutOverrides) {
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc index c8e7c07..91b49fe 100644 --- a/chrome/browser/extensions/extension_apitest.cc +++ b/chrome/browser/extensions/extension_apitest.cc
@@ -43,6 +43,8 @@ namespace { +using extensions::ExtensionBrowserTest; + const char kTestCustomArg[] = "customArg"; const char kTestDataDirectory[] = "testDataDirectory"; const char kTestWebSocketPort[] = "testWebSocketPort";
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h index e3551ec..e3f7ebb 100644 --- a/chrome/browser/extensions/extension_apitest.h +++ b/chrome/browser/extensions/extension_apitest.h
@@ -29,7 +29,7 @@ // chrome.test.fail // (4) Verify expected browser state. // TODO(erikkay): There should also be a way to drive events in these tests. -class ExtensionApiTest : public ExtensionBrowserTest { +class ExtensionApiTest : public extensions::ExtensionBrowserTest { public: // Flags used to configure how the tests are run. // TODO(aa): Many of these are dupes of ExtensionBrowserTest::Flags. Combine
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index a9cbd6f6..8c89851 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -75,21 +75,16 @@ #include "chromeos/chromeos_switches.h" #endif -using extensions::Extension; -using extensions::ExtensionCreator; -using extensions::ExtensionRegistry; -using extensions::FeatureSwitch; -using extensions::Manifest; -using extensions::ScopedTestDialogAutoConfirm; +namespace extensions { namespace { // Maps all chrome-extension://<id>/_test_resources/foo requests to // chrome/test/data/extensions/foo. This is what allows us to share code between // tests without needing to duplicate files in each extension. -void ExtensionProtocolTestHandler(const base::FilePath& test_dir_root, - base::FilePath* directory_path, - base::FilePath* relative_path) { +void ExtensionProtocolTestResourcesHandler(const base::FilePath& test_dir_root, + base::FilePath* directory_path, + base::FilePath* relative_path) { // Only map paths that begin with _test_resources. if (!base::FilePath(FILE_PATH_LITERAL("_test_resources")) .IsParent(*relative_path)) { @@ -156,7 +151,7 @@ // static const Extension* ExtensionBrowserTest::GetExtensionByPath( - const extensions::ExtensionSet& extensions, + const ExtensionSet& extensions, const base::FilePath& path) { base::ScopedAllowBlockingForTesting allow_blocking; base::FilePath extension_path = base::MakeAbsoluteFilePath(path); @@ -170,7 +165,7 @@ } void ExtensionBrowserTest::SetUp() { - test_extension_cache_.reset(new extensions::ExtensionCacheFake()); + test_extension_cache_.reset(new ExtensionCacheFake()); InProcessBrowserTest::SetUp(); } @@ -184,12 +179,12 @@ if (!ShouldEnableContentVerification()) { ignore_content_verification_.reset( - new extensions::ScopedIgnoreContentVerifierForTest()); + new ScopedIgnoreContentVerifierForTest()); } if (!ShouldEnableInstallVerification()) { ignore_install_verification_.reset( - new extensions::ScopedInstallVerifierBypassForTest()); + new ScopedInstallVerifierBypassForTest()); } #if defined(OS_CHROMEOS) @@ -205,8 +200,7 @@ } void ExtensionBrowserTest::SetUpOnMainThread() { - observer_.reset( - new extensions::ChromeExtensionTestNotificationObserver(browser())); + observer_.reset(new ChromeExtensionTestNotificationObserver(browser())); if (extension_service()->updater()) { extension_service()->updater()->SetExtensionCacheForTesting( test_extension_cache_.get()); @@ -219,14 +213,14 @@ base::PathService::Get(chrome::DIR_TEST_DATA, &test_root_path); test_root_path = test_root_path.AppendASCII("extensions"); test_protocol_handler_ = - base::Bind(&ExtensionProtocolTestHandler, test_root_path); - extensions::SetExtensionProtocolTestHandler(&test_protocol_handler_); + base::Bind(&ExtensionProtocolTestResourcesHandler, test_root_path); + SetExtensionProtocolTestHandler(&test_protocol_handler_); } void ExtensionBrowserTest::TearDownOnMainThread() { ExtensionMessageBubbleFactory::set_override_for_tests( ExtensionMessageBubbleFactory::NO_OVERRIDE); - extensions::SetExtensionProtocolTestHandler(nullptr); + SetExtensionProtocolTestHandler(nullptr); } const Extension* ExtensionBrowserTest::LoadExtension( @@ -249,7 +243,7 @@ const base::FilePath& path, int flags, const std::string& install_param) { - extensions::ChromeTestExtensionLoader loader(profile()); + ChromeTestExtensionLoader loader(profile()); loader.set_require_modern_manifest_version( (flags & kFlagAllowOldManifestVersions) == 0); loader.set_ignore_manifest_warnings( @@ -266,8 +260,8 @@ const Extension* ExtensionBrowserTest::LoadExtensionAsComponentWithManifest( const base::FilePath& path, const base::FilePath::CharType* manifest_relative_path) { - ExtensionService* service = extensions::ExtensionSystem::Get( - profile())->extension_service(); + ExtensionService* service = + ExtensionSystem::Get(profile())->extension_service(); ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); base::ScopedAllowBlockingForTesting allow_blocking; @@ -288,8 +282,7 @@ const Extension* ExtensionBrowserTest::LoadExtensionAsComponent( const base::FilePath& path) { - return LoadExtensionAsComponentWithManifest(path, - extensions::kManifestFilename); + return LoadExtensionAsComponentWithManifest(path, kManifestFilename); } const Extension* ExtensionBrowserTest::LoadAndLaunchApp( @@ -299,9 +292,8 @@ content::WindowedNotificationObserver app_loaded_observer( content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, content::NotificationService::AllSources()); - AppLaunchParams params(profile(), app, extensions::LAUNCH_CONTAINER_NONE, - WindowOpenDisposition::NEW_WINDOW, - extensions::SOURCE_TEST); + AppLaunchParams params(profile(), app, LAUNCH_CONTAINER_NONE, + WindowOpenDisposition::NEW_WINDOW, SOURCE_TEST); params.command_line = *base::CommandLine::ForCurrentProcess(); OpenApplication(params); app_loaded_observer.Wait(); @@ -309,9 +301,8 @@ return app; } -Browser* ExtensionBrowserTest::LaunchAppBrowser( - const extensions::Extension* extension) { - return extensions::browsertest_util::LaunchAppBrowser(profile(), extension); +Browser* ExtensionBrowserTest::LaunchAppBrowser(const Extension* extension) { + return browsertest_util::LaunchAppBrowser(profile(), extension); } base::FilePath ExtensionBrowserTest::PackExtension( @@ -385,8 +376,7 @@ const Extension* ExtensionBrowserTest::InstallBookmarkApp( WebApplicationInfo info) { - return extensions::browsertest_util::InstallBookmarkApp(profile(), - std::move(info)); + return browsertest_util::InstallBookmarkApp(profile(), std::move(info)); } const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore( @@ -441,7 +431,7 @@ bool install_immediately, bool grant_permissions) { ExtensionService* service = - extensions::ExtensionSystem::Get(profile())->extension_service(); + ExtensionSystem::Get(profile())->extension_service(); ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); size_t num_before = registry->enabled_extensions().size(); @@ -472,8 +462,8 @@ install_ui.reset(new ExtensionInstallPrompt( browser->tab_strip_model()->GetActiveWebContents())); } - scoped_refptr<extensions::CrxInstaller> installer( - extensions::CrxInstaller::Create(service, std::move(install_ui))); + scoped_refptr<CrxInstaller> installer( + CrxInstaller::Create(service, std::move(install_ui))); installer->set_expected_id(id); installer->set_creation_flags(creation_flags); installer->set_install_source(install_source); @@ -481,12 +471,11 @@ installer->set_allow_silent_install(grant_permissions); if (!installer->is_gallery_install()) { installer->set_off_store_install_allow_reason( - extensions::CrxInstaller::OffStoreInstallAllowedInTest); + CrxInstaller::OffStoreInstallAllowedInTest); } - observer_->Watch( - extensions::NOTIFICATION_CRX_INSTALLER_DONE, - content::Source<extensions::CrxInstaller>(installer.get())); + observer_->Watch(NOTIFICATION_CRX_INSTALLER_DONE, + content::Source<CrxInstaller>(installer.get())); installer->InstallCrx(crx_path); @@ -506,7 +495,7 @@ VLOG(1) << "Errors follow:"; const std::vector<base::string16>* errors = - extensions::LoadErrorReporter::GetInstance()->GetErrors(); + LoadErrorReporter::GetInstance()->GetErrors(); for (std::vector<base::string16>::const_iterator iter = errors->begin(); iter != errors->end(); ++iter) VLOG(1) << *iter; @@ -520,14 +509,12 @@ } void ExtensionBrowserTest::ReloadExtension(const std::string& extension_id) { - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(profile()); + ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); const Extension* extension = registry->GetInstalledExtension(extension_id); ASSERT_TRUE(extension); - extensions::TestExtensionRegistryObserver observer(registry, extension_id); - extensions::ExtensionSystem::Get(profile()) - ->extension_service() - ->ReloadExtension(extension_id); + TestExtensionRegistryObserver observer(registry, extension_id); + ExtensionSystem::Get(profile())->extension_service()->ReloadExtension( + extension_id); observer.WaitForExtensionLoaded(); // We need to let other ExtensionRegistryObservers handle the extension load @@ -539,30 +526,26 @@ } void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) { - ExtensionService* service = extensions::ExtensionSystem::Get( - profile())->extension_service(); - service->UnloadExtension(extension_id, - extensions::UnloadedExtensionReason::DISABLE); + ExtensionService* service = + ExtensionSystem::Get(profile())->extension_service(); + service->UnloadExtension(extension_id, UnloadedExtensionReason::DISABLE); } void ExtensionBrowserTest::UninstallExtension(const std::string& extension_id) { - ExtensionService* service = extensions::ExtensionSystem::Get( - profile())->extension_service(); - service->UninstallExtension(extension_id, - extensions::UNINSTALL_REASON_FOR_TESTING, - NULL); + ExtensionService* service = + ExtensionSystem::Get(profile())->extension_service(); + service->UninstallExtension(extension_id, UNINSTALL_REASON_FOR_TESTING, NULL); } void ExtensionBrowserTest::DisableExtension(const std::string& extension_id) { - ExtensionService* service = extensions::ExtensionSystem::Get( - profile())->extension_service(); - service->DisableExtension(extension_id, - extensions::disable_reason::DISABLE_USER_ACTION); + ExtensionService* service = + ExtensionSystem::Get(profile())->extension_service(); + service->DisableExtension(extension_id, disable_reason::DISABLE_USER_ACTION); } void ExtensionBrowserTest::EnableExtension(const std::string& extension_id) { - ExtensionService* service = extensions::ExtensionSystem::Get( - profile())->extension_service(); + ExtensionService* service = + ExtensionSystem::Get(profile())->extension_service(); service->EnableExtension(extension_id); } @@ -624,13 +607,12 @@ EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL()); } -extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath( - extensions::ProcessManager* manager, - const std::string& path, - int expected_hosts) { - extensions::ExtensionHost* result_host = nullptr; +ExtensionHost* ExtensionBrowserTest::FindHostWithPath(ProcessManager* manager, + const std::string& path, + int expected_hosts) { + ExtensionHost* result_host = nullptr; int num_hosts = 0; - for (extensions::ExtensionHost* host : manager->background_hosts()) { + for (ExtensionHost* host : manager->background_hosts()) { if (host->GetURL().path() == path) { EXPECT_FALSE(result_host); result_host = host; @@ -644,13 +626,15 @@ std::string ExtensionBrowserTest::ExecuteScriptInBackgroundPage( const std::string& extension_id, const std::string& script) { - return extensions::browsertest_util::ExecuteScriptInBackgroundPage( - profile(), extension_id, script); + return browsertest_util::ExecuteScriptInBackgroundPage(profile(), + extension_id, script); } bool ExtensionBrowserTest::ExecuteScriptInBackgroundPageNoWait( const std::string& extension_id, const std::string& script) { - return extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait( + return browsertest_util::ExecuteScriptInBackgroundPageNoWait( profile(), extension_id, script); } + +} // namespace extensions
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h index 0b2396a8..26791a4 100644 --- a/chrome/browser/extensions/extension_browsertest.h +++ b/chrome/browser/extensions/extension_browsertest.h
@@ -36,7 +36,6 @@ class ExtensionCacheFake; class ExtensionSet; class ProcessManager; -} // Base class for extension browser tests. Provides utilities for loading, // unloading, and installing extensions. @@ -66,7 +65,7 @@ // Useful accessors. ExtensionService* extension_service() { - return extensions::ExtensionSystem::Get(profile())->extension_service(); + return ExtensionSystem::Get(profile())->extension_service(); } const std::string& last_loaded_extension_id() { @@ -88,9 +87,8 @@ // about install verification. virtual bool ShouldEnableInstallVerification(); - static const extensions::Extension* GetExtensionByPath( - const extensions::ExtensionSet& extensions, - const base::FilePath& path); + static const Extension* GetExtensionByPath(const ExtensionSet& extensions, + const base::FilePath& path); // InProcessBrowserTest void SetUp() override; @@ -98,20 +96,19 @@ void SetUpOnMainThread() override; void TearDownOnMainThread() override; - const extensions::Extension* LoadExtension(const base::FilePath& path); + const Extension* LoadExtension(const base::FilePath& path); // Load extension and enable it in incognito mode. - const extensions::Extension* LoadExtensionIncognito( - const base::FilePath& path); + const Extension* LoadExtensionIncognito(const base::FilePath& path); // Load extension from the |path| folder. |flags| is bit mask of values from // |Flags| enum. - const extensions::Extension* LoadExtensionWithFlags( - const base::FilePath& path, int flags); + const Extension* LoadExtensionWithFlags(const base::FilePath& path, + int flags); // Same as above, but sets the installation parameter to the extension // preferences. - const extensions::Extension* LoadExtensionWithInstallParam( + const Extension* LoadExtensionWithInstallParam( const base::FilePath& path, int flags, const std::string& install_param); @@ -119,21 +116,20 @@ // Loads unpacked extension from |path| with manifest |manifest_relative_path| // and imitates that it is a component extension. // |manifest_relative_path| is relative to |path|. - const extensions::Extension* LoadExtensionAsComponentWithManifest( + const Extension* LoadExtensionAsComponentWithManifest( const base::FilePath& path, const base::FilePath::CharType* manifest_relative_path); // Loads unpacked extension from |path| and imitates that it is a component // extension. Equivalent to - // LoadExtensionAsComponentWithManifest(path, extensions::kManifestFilename). - const extensions::Extension* LoadExtensionAsComponent( - const base::FilePath& path); + // LoadExtensionAsComponentWithManifest(path, kManifestFilename). + const Extension* LoadExtensionAsComponent(const base::FilePath& path); // Loads and launches the app from |path|, and returns it. - const extensions::Extension* LoadAndLaunchApp(const base::FilePath& path); + const Extension* LoadAndLaunchApp(const base::FilePath& path); // Launches |extension| as a window and returns the browser. - Browser* LaunchAppBrowser(const extensions::Extension* extension); + Browser* LaunchAppBrowser(const Extension* extension); // Pack the extension in |dir_path| into a crx file and return its path. // Return an empty FilePath if there were errors. @@ -152,18 +148,17 @@ // disabled, if negative). // 1 means you expect a new install, 0 means you expect an upgrade, -1 means // you expect a failed upgrade. - const extensions::Extension* InstallExtension(const base::FilePath& path, - int expected_change) { + const Extension* InstallExtension(const base::FilePath& path, + int expected_change) { return InstallOrUpdateExtension( std::string(), path, INSTALL_UI_TYPE_NONE, expected_change); } // Same as above, but an install source other than Manifest::INTERNAL can be // specified. - const extensions::Extension* InstallExtension( - const base::FilePath& path, - int expected_change, - extensions::Manifest::Location install_source) { + const Extension* InstallExtension(const base::FilePath& path, + int expected_change, + Manifest::Location install_source) { return InstallOrUpdateExtension(std::string(), path, INSTALL_UI_TYPE_NONE, @@ -174,69 +169,63 @@ // Installs an extension and grants it the permissions it requests. // TODO(devlin): It seems like this is probably the desired outcome most of // the time - otherwise the extension installs in a disabled state. - const extensions::Extension* InstallExtensionWithPermissionsGranted( + const Extension* InstallExtensionWithPermissionsGranted( const base::FilePath& file_path, int expected_change) { return InstallOrUpdateExtension( std::string(), file_path, INSTALL_UI_TYPE_NONE, expected_change, - extensions::Manifest::INTERNAL, browser(), - extensions::Extension::NO_FLAGS, false, true); + Manifest::INTERNAL, browser(), Extension::NO_FLAGS, false, true); } // Installs bookmark app for |info|. - const extensions::Extension* InstallBookmarkApp(WebApplicationInfo info); + const Extension* InstallBookmarkApp(WebApplicationInfo info); // Installs extension as if it came from the Chrome Webstore. - const extensions::Extension* InstallExtensionFromWebstore( - const base::FilePath& path, int expected_change); + const Extension* InstallExtensionFromWebstore(const base::FilePath& path, + int expected_change); // Same as above but passes an id to CrxInstaller and does not allow a // privilege increase. - const extensions::Extension* UpdateExtension(const std::string& id, - const base::FilePath& path, - int expected_change) { + const Extension* UpdateExtension(const std::string& id, + const base::FilePath& path, + int expected_change) { return InstallOrUpdateExtension(id, path, INSTALL_UI_TYPE_NONE, expected_change); } // Same as UpdateExtension but waits for the extension to be idle first. - const extensions::Extension* UpdateExtensionWaitForIdle( - const std::string& id, const base::FilePath& path, int expected_change); + const Extension* UpdateExtensionWaitForIdle(const std::string& id, + const base::FilePath& path, + int expected_change); // Same as |InstallExtension| but with the normal extension UI showing up // (for e.g. info bar on success). - const extensions::Extension* InstallExtensionWithUI( - const base::FilePath& path, - int expected_change) { + const Extension* InstallExtensionWithUI(const base::FilePath& path, + int expected_change) { return InstallOrUpdateExtension( std::string(), path, INSTALL_UI_TYPE_NORMAL, expected_change); } - const extensions::Extension* InstallExtensionWithUIAutoConfirm( - const base::FilePath& path, - int expected_change, - Browser* browser) { - return InstallOrUpdateExtension(std::string(), - path, - INSTALL_UI_TYPE_AUTO_CONFIRM, - expected_change, - browser, - extensions::Extension::NO_FLAGS); + const Extension* InstallExtensionWithUIAutoConfirm(const base::FilePath& path, + int expected_change, + Browser* browser) { + return InstallOrUpdateExtension( + std::string(), path, INSTALL_UI_TYPE_AUTO_CONFIRM, expected_change, + browser, Extension::NO_FLAGS); } - const extensions::Extension* InstallExtensionWithSourceAndFlags( + const Extension* InstallExtensionWithSourceAndFlags( const base::FilePath& path, int expected_change, - extensions::Manifest::Location install_source, - extensions::Extension::InitFromValueFlags creation_flags) { + Manifest::Location install_source, + Extension::InitFromValueFlags creation_flags) { return InstallOrUpdateExtension(std::string(), path, INSTALL_UI_TYPE_NONE, expected_change, install_source, browser(), creation_flags, false, false); } // Begins install process but simulates a user cancel. - const extensions::Extension* StartInstallButCancel( - const base::FilePath& path) { + const Extension* StartInstallButCancel(const base::FilePath& path) { return InstallOrUpdateExtension( std::string(), path, INSTALL_UI_TYPE_CANCEL, 0); } @@ -313,19 +302,18 @@ // Looks for an ExtensionHost whose URL has the given path component // (including leading slash). Also verifies that the expected number of hosts // are loaded. - extensions::ExtensionHost* FindHostWithPath( - extensions::ProcessManager* manager, - const std::string& path, - int expected_hosts); + ExtensionHost* FindHostWithPath(ProcessManager* manager, + const std::string& path, + int expected_hosts); // Returns - // extensions::browsertest_util::ExecuteScriptInBackgroundPage(profile(), + // browsertest_util::ExecuteScriptInBackgroundPage(profile(), // extension_id, script). std::string ExecuteScriptInBackgroundPage(const std::string& extension_id, const std::string& script); // Returns - // extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait( + // browsertest_util::ExecuteScriptInBackgroundPageNoWait( // profile(), extension_id, script). bool ExecuteScriptInBackgroundPageNoWait(const std::string& extension_id, const std::string& script); @@ -343,8 +331,7 @@ // TODO(michaelpg): Don't override protected data members. base::FilePath test_data_dir_; - std::unique_ptr<extensions::ChromeExtensionTestNotificationObserver> - observer_; + std::unique_ptr<ChromeExtensionTestNotificationObserver> observer_; private: // Temporary directory for testing. @@ -359,41 +346,38 @@ INSTALL_UI_TYPE_AUTO_CONFIRM, }; - const extensions::Extension* InstallOrUpdateExtension( - const std::string& id, - const base::FilePath& path, - InstallUIType ui_type, - int expected_change); - const extensions::Extension* InstallOrUpdateExtension( + const Extension* InstallOrUpdateExtension(const std::string& id, + const base::FilePath& path, + InstallUIType ui_type, + int expected_change); + const Extension* InstallOrUpdateExtension( const std::string& id, const base::FilePath& path, InstallUIType ui_type, int expected_change, Browser* browser, - extensions::Extension::InitFromValueFlags creation_flags); - const extensions::Extension* InstallOrUpdateExtension( + Extension::InitFromValueFlags creation_flags); + const Extension* InstallOrUpdateExtension(const std::string& id, + const base::FilePath& path, + InstallUIType ui_type, + int expected_change, + Manifest::Location install_source); + const Extension* InstallOrUpdateExtension( const std::string& id, const base::FilePath& path, InstallUIType ui_type, int expected_change, - extensions::Manifest::Location install_source); - const extensions::Extension* InstallOrUpdateExtension( - const std::string& id, - const base::FilePath& path, - InstallUIType ui_type, - int expected_change, - extensions::Manifest::Location install_source, + Manifest::Location install_source, Browser* browser, - extensions::Extension::InitFromValueFlags creation_flags, + Extension::InitFromValueFlags creation_flags, bool wait_for_idle, bool grant_permissions); // Make the current channel "dev" for the duration of the test. - extensions::ScopedCurrentChannel current_channel_; + ScopedCurrentChannel current_channel_; // Disable external install UI. - extensions::FeatureSwitch::ScopedOverride - override_prompt_for_external_extensions_; + FeatureSwitch::ScopedOverride override_prompt_for_external_extensions_; #if defined(OS_WIN) // Use mock shortcut directories to ensure app shortcuts are cleaned up. @@ -408,21 +392,23 @@ Profile* profile_; // Cache cache implementation. - std::unique_ptr<extensions::ExtensionCacheFake> test_extension_cache_; + std::unique_ptr<ExtensionCacheFake> test_extension_cache_; // An override so that chrome-extensions://<extension_id>/_test_resources/foo // maps to chrome/test/data/extensions/foo. - extensions::ExtensionProtocolTestHandler test_protocol_handler_; + ExtensionProtocolTestHandler test_protocol_handler_; // Conditionally disable content verification. - std::unique_ptr<extensions::ScopedIgnoreContentVerifierForTest> + std::unique_ptr<ScopedIgnoreContentVerifierForTest> ignore_content_verification_; // Conditionally disable install verification. - std::unique_ptr<extensions::ScopedInstallVerifierBypassForTest> + std::unique_ptr<ScopedInstallVerifierBypassForTest> ignore_install_verification_; DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserTest); }; +} // namespace extensions + #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSERTEST_H_
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc index 7e99f86..caed3e96 100644 --- a/chrome/browser/extensions/extension_context_menu_browsertest.cc +++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -32,7 +32,8 @@ using extensions::MenuItem; using ui::MenuModel; -class ExtensionContextMenuBrowserTest : public ExtensionBrowserTest { +class ExtensionContextMenuBrowserTest + : public extensions::ExtensionBrowserTest { public: // Helper to load an extension from context_menus/|subdirectory| in the // extensions test data dir.
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc index 6be68a53..03070422 100644 --- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc +++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -39,10 +39,10 @@ using extensions::Extension; using extensions::ExtensionRegistry; -class ExtensionCrashRecoveryTest : public ExtensionBrowserTest { +class ExtensionCrashRecoveryTest : public extensions::ExtensionBrowserTest { protected: void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); display_service_ = std::make_unique<NotificationDisplayServiceTester>(profile()); } @@ -107,7 +107,7 @@ } void LoadTestExtension() { - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("common").AppendASCII("background_page")); ASSERT_TRUE(extension);
diff --git a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc index b12f1da..4b6422b 100644 --- a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc +++ b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
@@ -44,16 +44,17 @@ using extensions::ExtensionPrefs; using extensions::ExtensionSyncData; -class ExtensionDisabledGlobalErrorTest : public ExtensionBrowserTest { +class ExtensionDisabledGlobalErrorTest + : public extensions::ExtensionBrowserTest { protected: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII(switches::kAppsGalleryUpdateURL, "http://localhost/autoupdate/updates.xml"); } void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); service_ = extensions::ExtensionSystem::Get(profile())->extension_service(); registry_ = ExtensionRegistry::Get(profile());
diff --git a/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc b/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc index 5ea929eff..71928f9f 100644 --- a/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc +++ b/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc
@@ -121,8 +121,7 @@ const std::string& version, const base::FilePath& path) { return ExtensionBuilder("test") - .MergeManifest( - DictionaryBuilder().Set(manifest_keys::kVersion, version).Build()) + .SetManifestKey(manifest_keys::kVersion, version) .SetID(id) .SetPath(path) .SetLocation(Manifest::INTERNAL)
diff --git a/chrome/browser/extensions/extension_install_ui_browsertest.cc b/chrome/browser/extensions/extension_install_ui_browsertest.cc index 8902bd59..3be556c5 100644 --- a/chrome/browser/extensions/extension_install_ui_browsertest.cc +++ b/chrome/browser/extensions/extension_install_ui_browsertest.cc
@@ -33,7 +33,7 @@ using extensions::AppSorting; using extensions::Extension; -class ExtensionInstallUIBrowserTest : public ExtensionBrowserTest { +class ExtensionInstallUIBrowserTest : public extensions::ExtensionBrowserTest { public: ExtensionInstallUIBrowserTest() {} ~ExtensionInstallUIBrowserTest() override {}
diff --git a/chrome/browser/extensions/extension_nacl_browsertest.cc b/chrome/browser/extensions/extension_nacl_browsertest.cc index 37d66d1e..a719afe 100644 --- a/chrome/browser/extensions/extension_nacl_browsertest.cc +++ b/chrome/browser/extensions/extension_nacl_browsertest.cc
@@ -38,12 +38,12 @@ // This class tests that the Native Client plugin is blocked unless the // .nexe is part of an extension from the Chrome Webstore. -class NaClExtensionTest : public ExtensionBrowserTest { +class NaClExtensionTest : public extensions::ExtensionBrowserTest { public: NaClExtensionTest() {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(embedded_test_server()->Start()); } @@ -93,7 +93,7 @@ case INSTALL_TYPE_NON_WEBSTORE: // Install native_client.crx but not from the webstore. - if (ExtensionBrowserTest::InstallExtension(file_path, 1)) { + if (extensions::ExtensionBrowserTest::InstallExtension(file_path, 1)) { extension = service->GetExtensionById(last_loaded_extension_id(), false); }
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc index f1dddbc..47eb4a1 100644 --- a/chrome/browser/extensions/extension_protocols_unittest.cc +++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -122,11 +122,9 @@ } scoped_refptr<Extension> CreateTestResponseHeaderExtension() { - DictionaryBuilder web_accessible_resources; - web_accessible_resources.Set("web_accessible_resources", - ListBuilder().Append("test.dat").Build()); return ExtensionBuilder("An extension with web-accessible resources") - .MergeManifest(web_accessible_resources.Build()) + .SetManifestKey("web_accessible_resources", + ListBuilder().Append("test.dat").Build()) .SetPath(GetTestPath("response_headers")) .Build(); }
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 5c392d5e..8dc5a4a 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -7215,16 +7215,10 @@ // Test that calls to disable Shared Modules do not work. TEST_F(ExtensionServiceTest, CannotDisableSharedModules) { InitializeEmptyExtensionService(); - std::unique_ptr<base::DictionaryValue> export_dict = - extensions::DictionaryBuilder() - .Set("resources", extensions::ListBuilder().Append("foo.js").Build()) - .Build(); - scoped_refptr<Extension> extension = ExtensionBuilder("Shared Module") - .MergeManifest(extensions::DictionaryBuilder() - .Set("export", std::move(export_dict)) - .Build()) + .SetManifestPath({"export", "resources"}, + extensions::ListBuilder().Append("foo.js").Build()) .AddFlags(Extension::FROM_WEBSTORE) .Build();
diff --git a/chrome/browser/extensions/extension_startup_browsertest.cc b/chrome/browser/extensions/extension_startup_browsertest.cc index b1b86b1..347c7a25 100644 --- a/chrome/browser/extensions/extension_startup_browsertest.cc +++ b/chrome/browser/extensions/extension_startup_browsertest.cc
@@ -325,7 +325,7 @@ // TODO(catmullings): Remove test in future chrome release, perhaps M59. class DeprecatedLoadComponentExtensionSwitchBrowserTest - : public ExtensionBrowserTest { + : public extensions::ExtensionBrowserTest { public: DeprecatedLoadComponentExtensionSwitchBrowserTest() {} @@ -338,7 +338,7 @@ void DeprecatedLoadComponentExtensionSwitchBrowserTest::SetUpCommandLine( base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); base::FilePath fp1(test_data_dir_.AppendASCII("app_dot_com_app/")); base::FilePath fp2(test_data_dir_.AppendASCII("app/")); @@ -371,7 +371,8 @@ EXPECT_FALSE(is_app_test_extension_installed); } -class DisableExtensionsExceptBrowserTest : public ExtensionBrowserTest { +class DisableExtensionsExceptBrowserTest + : public extensions::ExtensionBrowserTest { public: DisableExtensionsExceptBrowserTest() {} @@ -384,7 +385,7 @@ void DisableExtensionsExceptBrowserTest::SetUpCommandLine( base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); base::FilePath fp1(test_data_dir_.AppendASCII("app_dot_com_app/")); base::FilePath fp2(test_data_dir_.AppendASCII("app/"));
diff --git a/chrome/browser/extensions/extension_url_rewrite_browsertest.cc b/chrome/browser/extensions/extension_url_rewrite_browsertest.cc index 08417d3a..67fd950d 100644 --- a/chrome/browser/extensions/extension_url_rewrite_browsertest.cc +++ b/chrome/browser/extensions/extension_url_rewrite_browsertest.cc
@@ -26,11 +26,11 @@ using content::NavigationEntry; -class ExtensionURLRewriteBrowserTest : public ExtensionBrowserTest { +class ExtensionURLRewriteBrowserTest : public extensions::ExtensionBrowserTest { public: void SetUp() override { extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); - ExtensionBrowserTest::SetUp(); + extensions::ExtensionBrowserTest::SetUp(); } protected:
diff --git a/chrome/browser/extensions/extension_web_ui_unittest.cc b/chrome/browser/extensions/extension_web_ui_unittest.cc index 51dfbcf7..0261326 100644 --- a/chrome/browser/extensions/extension_web_ui_unittest.cc +++ b/chrome/browser/extensions/extension_web_ui_unittest.cc
@@ -162,14 +162,9 @@ TEST_F(ExtensionWebUITest, TestRemovingDuplicateEntriesForHosts) { // Test that duplicate entries for a single extension are removed. This could // happen because of https://crbug.com/782959. - std::unique_ptr<base::DictionaryValue> manifest_overrides = - DictionaryBuilder().Set("newtab", "newtab.html").Build(); scoped_refptr<const Extension> extension = ExtensionBuilder("extension") - .MergeManifest( - DictionaryBuilder() - .Set("chrome_url_overrides", std::move(manifest_overrides)) - .Build()) + .SetManifestPath({"chrome_url_overrides", "newtab"}, "newtab.html") .Build(); const GURL newtab_url = extension->GetResourceURL("newtab.html");
diff --git a/chrome/browser/extensions/file_iframe_apitest.cc b/chrome/browser/extensions/file_iframe_apitest.cc index ad92577..1ccb708 100644 --- a/chrome/browser/extensions/file_iframe_apitest.cc +++ b/chrome/browser/extensions/file_iframe_apitest.cc
@@ -13,7 +13,7 @@ #include "extensions/test/test_extension_dir.h" #include "net/base/filename_util.h" -class FileIFrameAPITest : public ExtensionBrowserTest { +class FileIFrameAPITest : public extensions::ExtensionBrowserTest { public: FileIFrameAPITest() {} void set_has_all_urls(bool val) { has_all_urls_ = val; }
diff --git a/chrome/browser/extensions/gpu_browsertest.cc b/chrome/browser/extensions/gpu_browsertest.cc index 44bc1fd9..93df6f3 100644 --- a/chrome/browser/extensions/gpu_browsertest.cc +++ b/chrome/browser/extensions/gpu_browsertest.cc
@@ -9,6 +9,8 @@ #include "extensions/browser/extension_host.h" #include "extensions/browser/process_manager.h" +namespace extensions { + // Tests that background pages are marked as never visible to prevent GPU // resource allocation. See crbug.com/362165 and crbug.com/163698. IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, BackgroundPageIsNeverVisible) { @@ -17,10 +19,10 @@ .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") .AppendASCII("1.0.0.0"))); - extensions::ProcessManager* manager = - extensions::ProcessManager::Get(browser()->profile()); - extensions::ExtensionHost* host = - FindHostWithPath(manager, "/backgroundpage.html", 1); + ProcessManager* manager = ProcessManager::Get(browser()->profile()); + ExtensionHost* host = FindHostWithPath(manager, "/backgroundpage.html", 1); ASSERT_TRUE(host->host_contents()->GetDelegate()->IsNeverVisible( host->host_contents())); } + +} // namespace extensions
diff --git a/chrome/browser/extensions/install_verifier_unittest.cc b/chrome/browser/extensions/install_verifier_unittest.cc index bfe3ac5..c6cd966 100644 --- a/chrome/browser/extensions/install_verifier_unittest.cc +++ b/chrome/browser/extensions/install_verifier_unittest.cc
@@ -97,10 +97,8 @@ ExtensionBuilder extension_builder(test_case.test_name); extension_builder.SetLocation(test_case.location); if (test_case.update_url) { - extension_builder.MergeManifest( - DictionaryBuilder() - .Set("update_url", test_case.update_url->spec()) - .Build()); + extension_builder.SetManifestKey("update_url", + test_case.update_url->spec()); } scoped_refptr<const Extension> extension = extension_builder.Build();
diff --git a/chrome/browser/extensions/permission_messages_unittest.cc b/chrome/browser/extensions/permission_messages_unittest.cc index 91e2ed6..8701323 100644 --- a/chrome/browser/extensions/permission_messages_unittest.cc +++ b/chrome/browser/extensions/permission_messages_unittest.cc
@@ -56,12 +56,9 @@ std::unique_ptr<base::ListValue> required_permissions, std::unique_ptr<base::ListValue> optional_permissions) { app_ = ExtensionBuilder("Test") - .MergeManifest( - DictionaryBuilder() - .Set("permissions", std::move(required_permissions)) - .Set("optional_permissions", - std::move(optional_permissions)) - .Build()) + .SetManifestKey("permissions", std::move(required_permissions)) + .SetManifestKey("optional_permissions", + std::move(optional_permissions)) .SetID(crx_file::id_util::GenerateId("extension")) .SetLocation(Manifest::INTERNAL) .Build();
diff --git a/chrome/browser/extensions/subscribe_page_action_browsertest.cc b/chrome/browser/extensions/subscribe_page_action_browsertest.cc index c257c5c..11ff43fe 100644 --- a/chrome/browser/extensions/subscribe_page_action_browsertest.cc +++ b/chrome/browser/extensions/subscribe_page_action_browsertest.cc
@@ -14,7 +14,8 @@ #include "net/test/embedded_test_server/embedded_test_server.h" using content::WebContents; -using extensions::Extension; + +namespace extensions { namespace { @@ -68,10 +69,9 @@ if (direct_url) { // We navigate directly to the subscribe page for feeds where the feed // sniffing won't work, in other words, as is the case for malformed feeds. - return GURL(std::string(extensions::kExtensionScheme) + - url::kStandardSchemeSeparator + - extension_id + std::string(kSubscribePage) + std::string("?") + - feed_url.spec() + std::string("&synchronous")); + return GURL(std::string(kExtensionScheme) + url::kStandardSchemeSeparator + + extension_id + std::string(kSubscribePage) + std::string("?") + + feed_url.spec() + std::string("&synchronous")); } else { // Navigate to the feed content (which will cause the extension to try to // sniff the type and display the subscribe page in another tab. @@ -328,3 +328,5 @@ browser(), id, true, "Feed for MyFeedTitle", "Title with no link", "Desc", "No error"); } + +} // namespace extensions
diff --git a/chrome/browser/extensions/view_extension_source_browsertest.cc b/chrome/browser/extensions/view_extension_source_browsertest.cc index 4dbf31f..bb323ff3 100644 --- a/chrome/browser/extensions/view_extension_source_browsertest.cc +++ b/chrome/browser/extensions/view_extension_source_browsertest.cc
@@ -19,7 +19,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "url/gurl.h" -typedef ExtensionBrowserTest ViewExtensionSourceTest; +typedef extensions::ExtensionBrowserTest ViewExtensionSourceTest; // Verify that restoring a view-source tab for a Chrome extension works // properly. See https://crbug.com/699428.
diff --git a/chrome/browser/extensions/wasm_app_browsertest.cc b/chrome/browser/extensions/wasm_app_browsertest.cc index 67f0ee5..f235922 100644 --- a/chrome/browser/extensions/wasm_app_browsertest.cc +++ b/chrome/browser/extensions/wasm_app_browsertest.cc
@@ -9,7 +9,7 @@ // Test ensures that Wasm can run in Chrome Apps. namespace { -class WasmAppTest : public ExtensionBrowserTest {}; +using WasmAppTest = extensions::ExtensionBrowserTest; IN_PROC_BROWSER_TEST_F(WasmAppTest, InstantiateWasmFromFetch) { const Extension* extension =
diff --git a/chrome/browser/extensions/web_contents_browsertest.cc b/chrome/browser/extensions/web_contents_browsertest.cc index 349d88bb..78cce467 100644 --- a/chrome/browser/extensions/web_contents_browsertest.cc +++ b/chrome/browser/extensions/web_contents_browsertest.cc
@@ -22,10 +22,9 @@ #include "extensions/browser/extension_api_frame_id_map.h" #include "extensions/browser/extension_navigation_ui_data.h" +namespace extensions { namespace { -using ExtensionApiFrameIdMap = extensions::ExtensionApiFrameIdMap; - content::WebContents* GetActiveWebContents(const Browser* browser) { return browser->tab_strip_model()->GetActiveWebContents(); } @@ -37,7 +36,7 @@ explicit ExtensionNavigationUIDataObserver(content::WebContents* web_contents) : WebContentsObserver(web_contents) {} - const extensions::ExtensionNavigationUIData* GetExtensionNavigationUIData( + const ExtensionNavigationUIData* GetExtensionNavigationUIData( content::RenderFrameHost* rfh) const { auto iter = navigation_ui_data_map_.find(rfh); if (iter == navigation_ui_data_map_.end()) @@ -59,7 +58,7 @@ } std::map<content::RenderFrameHost*, - std::unique_ptr<extensions::ExtensionNavigationUIData>> + std::unique_ptr<ExtensionNavigationUIData>> navigation_ui_data_map_; DISALLOW_COPY_AND_ASSIGN(ExtensionNavigationUIDataObserver); @@ -102,7 +101,7 @@ auto test_devtools_main_frame_cached = [](Browser* browser, bool is_docked) { SCOPED_TRACE(base::StringPrintf("Testing a %s devtools window", is_docked ? "docked" : "undocked")); - const auto* api_frame_id_map = extensions::ExtensionApiFrameIdMap::Get(); + const auto* api_frame_id_map = ExtensionApiFrameIdMap::Get(); size_t prior_count = api_frame_id_map->GetFrameDataCountForTesting(); // Open a devtools window. @@ -133,7 +132,7 @@ // Regression test for crbug.com/810614. IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, FrameDataCached) { // Load an extension with a web accessible resource. - const extensions::Extension* extension = + const Extension* extension = LoadExtension(test_data_dir_.AppendASCII("web_accessible_resources")); ASSERT_TRUE(extension); @@ -306,3 +305,5 @@ EXPECT_FALSE(frame_data.pending_main_frame_url); } } + +} // namespace extensions
diff --git a/chrome/browser/extensions/webstore_installer_test.cc b/chrome/browser/extensions/webstore_installer_test.cc index 4d7452c..7bdca8c9 100644 --- a/chrome/browser/extensions/webstore_installer_test.cc +++ b/chrome/browser/extensions/webstore_installer_test.cc
@@ -55,7 +55,7 @@ WebstoreInstallerTest::~WebstoreInstallerTest() {} void WebstoreInstallerTest::SetUpCommandLine(base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); embedded_test_server()->RegisterRequestMonitor(base::Bind( &WebstoreInstallerTest::ProcessServerRequest, base::Unretained(this))); @@ -80,7 +80,7 @@ } void WebstoreInstallerTest::SetUpOnMainThread() { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule(webstore_domain_, "127.0.0.1"); host_resolver()->AddRule(verified_domain_, "127.0.0.1");
diff --git a/chrome/browser/extensions/webstore_installer_test.h b/chrome/browser/extensions/webstore_installer_test.h index d1d9fb6..ccb8514 100644 --- a/chrome/browser/extensions/webstore_installer_test.h +++ b/chrome/browser/extensions/webstore_installer_test.h
@@ -27,7 +27,7 @@ } } -class WebstoreInstallerTest : public ExtensionBrowserTest { +class WebstoreInstallerTest : public extensions::ExtensionBrowserTest { public: WebstoreInstallerTest(const std::string& webstore_domain, const std::string& test_data_path,
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc index f6f9adef..ab8b96f 100644 --- a/chrome/browser/extensions/window_open_apitest.cc +++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -57,6 +57,8 @@ class Window; } +namespace extensions { + class WindowOpenApiTest : public ExtensionApiTest { void SetUpOnMainThread() override { ExtensionApiTest::SetUpOnMainThread(); @@ -524,3 +526,5 @@ extension->install_warnings().front().message); } #endif + +} // namespace extensions
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 9e62e3a..4ef8aae9 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -405,7 +405,8 @@ const char kEnableEmojiContextMenuName[] = "Emoji Context Menu"; const char kEnableEmojiContextMenuDescription[] = - "Enables the Emoji picker item in context menus for editable text areas."; + "Enables the Emoji picker item in context menus for editable text areas, if" + " supported by the operating system."; const char kEnableEnumeratingAudioDevicesName[] = "Experimentally enable enumerating audio devices."; @@ -1193,6 +1194,11 @@ const char kOverscrollStartThreshold166Percent[] = "166%"; const char kOverscrollStartThreshold200Percent[] = "200%"; +const char kTouchpadOverscrollHistoryNavigationName[] = + "Overscroll history navigation on Touchpad"; +const char kTouchpadOverscrollHistoryNavigationDescription[] = + "Allows swipe left/right from touchpad change browser navigation."; + const char kParallelDownloadingName[] = "Parallel downloading"; const char kParallelDownloadingDescription[] = "Enable parallel downloading to accelerate download speed."; @@ -1286,12 +1292,6 @@ "Pull-to-refresh gesture in response to vertical overscroll."; const char kPullToRefreshEnabledTouchscreen[] = "Enabled for touchscreen only"; -const char kPushApiBackgroundModeName[] = "Enable Push API background mode"; -const char kPushApiBackgroundModeDescription[] = - "Enable background mode for the Push API. This allows Chrome to continue " - "running after the last window is closed, and to launch at OS startup, if " - "the Push API needs it."; - const char kQueryInOmniboxName[] = "Query in Omnibox"; const char kQueryInOmniboxDescription[] = "Only display query terms in the omnibox when viewing a search results " @@ -1938,13 +1938,6 @@ "Expand bottom sheet on startup in Chrome Home after a period of" " inactivity."; -const char kChromeHomeMenuItemsName[] = - "Show bookmarks, downloads, and history menu items in Chrome Home"; -const char kChromeHomeMenuItemsDescription[] = - "Shows bookmarks, downloads, and history menu items in the overflow menu" - " when Chrome Home is enabled. These items will open the bottom sheet to" - " show the desired content."; - const char kChromeHomePersistentIphName[] = "Chrome Home Persistent Iph"; const char kChromeHomePersistentIphDescription[] = "Wait to dismiss the Chrome Home IPH until the user inteacts with the " @@ -2976,11 +2969,6 @@ "Enables inspection of native UI elements. For local inspection use " "chrome://inspect#other"; -const char kUseMusName[] = "Mojo UI service (mus)"; -const char kUseMusDescription[] = - "Handles input events, display configuration, and windowing in a mojo " - "service on a thread in the browser process."; - const char kUseMashName[] = "Out-of-process system UI (mash)"; const char kUseMashDescription[] = "Runs the mojo UI service (mus) and the ash window manager and system UI "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 56ec86f..f6d0f353 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -806,9 +806,6 @@ extern const char kPullToRefreshDescription[]; extern const char kPullToRefreshEnabledTouchscreen[]; -extern const char kPushApiBackgroundModeName[]; -extern const char kPushApiBackgroundModeDescription[]; - extern const char kQueryInOmniboxName[]; extern const char kQueryInOmniboxDescription[]; @@ -1023,6 +1020,9 @@ extern const char kTouchEventsName[]; extern const char kTouchEventsDescription[]; +extern const char kTouchpadOverscrollHistoryNavigationName[]; +extern const char kTouchpadOverscrollHistoryNavigationDescription[]; + extern const char kTouchSelectionStrategyName[]; extern const char kTouchSelectionStrategyDescription[]; extern const char kTouchSelectionStrategyCharacter[]; @@ -1184,9 +1184,6 @@ extern const char kChromeHomeInactivitySheetExpansionName[]; extern const char kChromeHomeInactivitySheetExpansionDescription[]; -extern const char kChromeHomeMenuItemsName[]; -extern const char kChromeHomeMenuItemsDescription[]; - extern const char kChromeHomePersistentIphName[]; extern const char kChromeHomePersistentIphDescription[]; @@ -1815,9 +1812,6 @@ extern const char kUiDevToolsName[]; extern const char kUiDevToolsDescription[]; -extern const char kUseMusName[]; -extern const char kUseMusDescription[]; - extern const char kUseMashName[]; extern const char kUseMashDescription[];
diff --git a/chrome/browser/global_keyboard_shortcuts_mac_browsertest.mm b/chrome/browser/global_keyboard_shortcuts_mac_browsertest.mm index 57a68399..43384244 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac_browsertest.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac_browsertest.mm
@@ -17,7 +17,7 @@ using cocoa_test_event_utils::SynthesizeKeyEvent; -using GlobalKeyboardShortcutsTest = ExtensionBrowserTest; +using GlobalKeyboardShortcutsTest = extensions::ExtensionBrowserTest; namespace {
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 9e1f6fb..3fe13ea 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -37,15 +37,10 @@ #include "chrome/browser/net/chrome_network_delegate.h" #include "chrome/browser/net/dns_probe_service.h" #include "chrome/browser/net/proxy_service_factory.h" -#include "chrome/browser/net/sth_distributor_provider.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" -#include "components/certificate_transparency/features.h" -#include "components/certificate_transparency/sth_distributor.h" -#include "components/certificate_transparency/sth_observer.h" -#include "components/certificate_transparency/tree_state_tracker.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" #include "components/data_usage/core/data_use_aggregator.h" #include "components/data_usage/core/data_use_amortizer.h" @@ -72,8 +67,6 @@ #include "net/cert/cert_verify_proc.h" #include "net/cert/ct_known_logs.h" #include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_verifier.h" -#include "net/cert/multi_log_ct_verifier.h" #include "net/cert/multi_threaded_cert_verifier.h" #include "net/dns/host_cache.h" #include "net/dns/host_resolver.h" @@ -419,9 +412,6 @@ ntlm_v2_enabled_.MoveToThread(io_thread_proxy); #endif - chrome_browser_net::SetGlobalSTHDistributor( - std::make_unique<certificate_transparency::STHDistributor>()); - BrowserThread::SetIOThreadDelegate(this); system_network_context_manager->SetUp(&network_context_request_, @@ -435,10 +425,6 @@ BrowserThread::SetIOThreadDelegate(nullptr); DCHECK(!globals_); - - // Destroy the old distributor to check that the observers list it holds is - // empty. - chrome_browser_net::SetGlobalSTHDistributor(nullptr); } IOThread::Globals* IOThread::globals() { @@ -544,17 +530,6 @@ UpdateDnsClientEnabled(); - if (base::FeatureList::IsEnabled(certificate_transparency::kCTLogAuditing)) { - ct_tree_tracker_ = - std::make_unique<certificate_transparency::TreeStateTracker>( - globals_->ct_logs, - globals_->system_request_context->host_resolver(), net_log_); - // Register the ct_tree_tracker_ as observer for new STHs. - RegisterSTHObserver(ct_tree_tracker_.get()); - // Register the ct_tree_tracker_ as observer for verified SCTs. - globals_->system_request_context->cert_transparency_verifier()->SetObserver( - ct_tree_tracker_.get()); - } } void IOThread::CleanUp() { @@ -562,17 +537,6 @@ system_url_request_context_getter_ = nullptr; - if (ct_tree_tracker_) { - // Unlink the ct_tree_tracker_ from the global cert_transparency_verifier - // and unregister it from new STH notifications so it will take no actions - // on anything observed during CleanUp process. - globals() - ->system_request_context->cert_transparency_verifier() - ->SetObserver(nullptr); - UnregisterSTHObserver(ct_tree_tracker_.get()); - ct_tree_tracker_.reset(); - } - globals_->system_request_context->proxy_resolution_service()->OnShutdown(); #if defined(USE_NSS_CERTS) @@ -734,16 +698,6 @@ } } -void IOThread::RegisterSTHObserver( - certificate_transparency::STHObserver* observer) { - chrome_browser_net::GetGlobalSTHDistributor()->RegisterObserver(observer); -} - -void IOThread::UnregisterSTHObserver( - certificate_transparency::STHObserver* observer) { - chrome_browser_net::GetGlobalSTHDistributor()->UnregisterObserver(observer); -} - void IOThread::SetUpProxyService( network::URLRequestContextBuilderMojo* builder) const { #if defined(OS_CHROMEOS) @@ -752,10 +706,6 @@ #endif } -certificate_transparency::TreeStateTracker* IOThread::ct_tree_tracker() const { - return ct_tree_tracker_.get(); -} - void IOThread::ConstructSystemRequestContext() { std::unique_ptr<network::URLRequestContextBuilderMojo> builder = std::make_unique<network::URLRequestContextBuilderMojo>(); @@ -805,12 +755,6 @@ command_line.HasSwitch( network::switches::kIgnoreCertificateErrorsSPKIList)); - std::unique_ptr<net::MultiLogCTVerifier> ct_verifier = - std::make_unique<net::MultiLogCTVerifier>(); - // Add built-in logs - ct_verifier->AddLogs(globals_->ct_logs); - builder->set_ct_verifier(std::move(ct_verifier)); - SetUpProxyService(builder.get()); if (!is_quic_allowed_on_init_)
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index b4c7a49..f4dec02 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -258,8 +258,6 @@ Globals* globals_; - std::unique_ptr<certificate_transparency::TreeStateTracker> ct_tree_tracker_; - BooleanPrefMember system_enable_referrers_; BooleanPrefMember dns_client_enabled_;
diff --git a/chrome/browser/io_thread_browsertest.cc b/chrome/browser/io_thread_browsertest.cc index a9371b1..1785b01 100644 --- a/chrome/browser/io_thread_browsertest.cc +++ b/chrome/browser/io_thread_browsertest.cc
@@ -113,21 +113,6 @@ ->GetEffectiveConnectionType()); } -void CheckSCTsAreSentToTreeTracker(IOThread* io_thread) { - EXPECT_NE(io_thread->ct_tree_tracker(), nullptr); - EXPECT_EQ(io_thread->ct_tree_tracker(), - io_thread->globals() - ->system_request_context->cert_transparency_verifier() - ->GetObserver()); -} - -void CheckSCTsAreNotSentToTreeTracker(IOThread* io_thread) { - EXPECT_EQ(io_thread->globals() - ->system_request_context->cert_transparency_verifier() - ->GetObserver(), - nullptr); -} - class IOThreadBrowserTest : public InProcessBrowserTest { public: IOThreadBrowserTest() {} @@ -212,48 +197,6 @@ base::Unretained(g_browser_process->io_thread()), true, url)); } -class IOThreadCTBrowserTest : public IOThreadBrowserTest { - public: - IOThreadCTBrowserTest() {} - ~IOThreadCTBrowserTest() override {} - - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature( - certificate_transparency::kCTLogAuditing); - IOThreadBrowserTest::SetUp(); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(IOThreadCTBrowserTest, SCTsAreSentToTreeTracker) { - RunOnIOThreadBlocking( - base::BindOnce(&CheckSCTsAreSentToTreeTracker, - base::Unretained(g_browser_process->io_thread()))); -} - -class IOThreadNoCTBrowserTest : public IOThreadBrowserTest { - public: - IOThreadNoCTBrowserTest() {} - ~IOThreadNoCTBrowserTest() override {} - - void SetUp() override { - scoped_feature_list_.InitAndDisableFeature( - certificate_transparency::kCTLogAuditing); - IOThreadBrowserTest::SetUp(); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(IOThreadNoCTBrowserTest, SCTsAreNotSentToTreeTracker) { - RunOnIOThreadBlocking( - base::BindOnce(&CheckSCTsAreNotSentToTreeTracker, - base::Unretained(g_browser_process->io_thread()))); -} - class IOThreadEctCommandLineBrowserTest : public IOThreadBrowserTest { public: IOThreadEctCommandLineBrowserTest() {}
diff --git a/chrome/browser/media/router/issue_manager_unittest.cc b/chrome/browser/media/router/issue_manager_unittest.cc index a0a63f4..50243e5 100644 --- a/chrome/browser/media/router/issue_manager_unittest.cc +++ b/chrome/browser/media/router/issue_manager_unittest.cc
@@ -137,13 +137,12 @@ ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer)); EXPECT_CALL(observer, OnIssuesCleared()).Times(1); + EXPECT_TRUE(task_runner_->HasPendingTask()); manager_.ClearIssue(issue1.id()); EXPECT_CALL(observer, OnIssuesCleared()).Times(0); base::TimeDelta timeout = IssueManager::GetAutoDismissTimeout(issue_info1); EXPECT_FALSE(timeout.is_zero()); - EXPECT_TRUE(task_runner_->HasPendingTask()); - task_runner_->FastForwardBy(timeout); EXPECT_FALSE(task_runner_->HasPendingTask()); }
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc index 015baacd..897acc2 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -198,7 +198,8 @@ } // namespace -class ProcessMemoryMetricsEmitterTest : public ExtensionBrowserTest { +class ProcessMemoryMetricsEmitterTest + : public extensions::ExtensionBrowserTest { public: ProcessMemoryMetricsEmitterTest() { scoped_feature_list_.InitAndEnableFeature(ukm::kUkmFeature); @@ -207,7 +208,7 @@ ~ProcessMemoryMetricsEmitterTest() override {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); }
diff --git a/chrome/browser/net/default_network_context_params.cc b/chrome/browser/net/default_network_context_params.cc index 332c063..1e3ecbd 100644 --- a/chrome/browser/net/default_network_context_params.cc +++ b/chrome/browser/net/default_network_context_params.cc
@@ -10,6 +10,7 @@ #include "base/feature_list.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "chrome/common/channel_info.h" @@ -25,6 +26,7 @@ #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/user_agent.h" +#include "net/cert/ct_known_logs.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams() { @@ -68,6 +70,19 @@ network_context_params->dangerously_allow_pac_access_to_secure_urls = !local_state->GetBoolean(prefs::kPacHttpsUrlStrippingEnabled); +#if !defined(OS_ANDROID) + // CT is only enabled on Desktop platforms for now. + network_context_params->enforce_chrome_ct_policy = true; + for (const auto& ct_log : net::ct::GetKnownLogs()) { + // TODO(rsleevi): https://crbug.com/702062 - Remove this duplication. + network::mojom::CTLogInfoPtr log_info = network::mojom::CTLogInfo::New(); + log_info->public_key = std::string(ct_log.log_key, ct_log.log_key_length); + log_info->name = ct_log.log_name; + log_info->dns_api_endpoint = ct_log.log_dns_domain; + network_context_params->ct_logs.push_back(std::move(log_info)); + } +#endif + bool http_09_on_non_default_ports_enabled = false; const base::Value* value = g_browser_process->policy_service()
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc index c7a37262..1d281b0 100644 --- a/chrome/browser/net/network_context_configuration_browsertest.cc +++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/net/profile_network_context_service_factory.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_switches.h" @@ -80,6 +81,7 @@ enum class NetworkContextType { kSystem, + kSafeBrowsing, kProfile, kIncognitoProfile, }; @@ -171,6 +173,10 @@ case NetworkContextType::kSystem: return g_browser_process->system_network_context_manager() ->GetURLLoaderFactory(); + case NetworkContextType::kSafeBrowsing: + return g_browser_process->safe_browsing_service() + ->GetURLLoaderFactory() + .get(); case NetworkContextType::kProfile: return content::BrowserContext::GetDefaultStoragePartition( browser()->profile()) @@ -192,6 +198,8 @@ case NetworkContextType::kSystem: return g_browser_process->system_network_context_manager() ->GetContext(); + case NetworkContextType::kSafeBrowsing: + return g_browser_process->safe_browsing_service()->GetNetworkContext(); case NetworkContextType::kProfile: return content::BrowserContext::GetDefaultStoragePartition( browser()->profile()) @@ -209,6 +217,7 @@ StorageType GetHttpCacheType() const { switch (GetParam().network_context_type) { case NetworkContextType::kSystem: + case NetworkContextType::kSafeBrowsing: return StorageType::kNone; case NetworkContextType::kProfile: return StorageType::kDisk; @@ -226,6 +235,7 @@ PrefService* pref_service = nullptr; switch (GetParam().network_context_type) { case NetworkContextType::kSystem: + case NetworkContextType::kSafeBrowsing: pref_service = g_browser_process->local_state(); break; case NetworkContextType::kProfile: @@ -247,6 +257,7 @@ // requests are sent on a separate pipe from ProxyConfigs. switch (GetParam().network_context_type) { case NetworkContextType::kSystem: + case NetworkContextType::kSafeBrowsing: g_browser_process->system_network_context_manager() ->FlushProxyConfigMonitorForTesting(); break; @@ -334,6 +345,10 @@ g_browser_process->system_network_context_manager() ->FlushNetworkInterfaceForTesting(); break; + case NetworkContextType::kSafeBrowsing: + g_browser_process->safe_browsing_service() + ->FlushNetworkInterfaceForTesting(); + break; case NetworkContextType::kProfile: content::BrowserContext::GetDefaultStoragePartition( browser()->profile()) @@ -604,10 +619,12 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, UserAgentAndLanguagePrefs) { - // System network context isn't associated with any profile, so changing the - // language settings in the default one doesn't affect what it sends. + // The system and SafeBrowsing network contexts aren't associated with any + // profile, so changing the language settings for the profile's main network + // context won't affect what they send. bool system = - (GetParam().network_context_type == NetworkContextType::kSystem); + (GetParam().network_context_type == NetworkContextType::kSystem || + GetParam().network_context_type == NetworkContextType::kSafeBrowsing); const char kDefaultAcceptLanguage[] = "en-us,en"; std::string accept_language, user_agent; @@ -964,6 +981,11 @@ NetworkContextType::kSystem}))); \ \ INSTANTIATE_TEST_CASE_P( \ + SafeBrowsingNetworkContext, TestFixture, \ + ::testing::Values(TestCase({NetworkServiceState::kDisabled, \ + NetworkContextType::kSafeBrowsing}))); \ + \ + INSTANTIATE_TEST_CASE_P( \ ProfileMainNetworkContext, TestFixture, \ ::testing::Values(TestCase({NetworkServiceState::kDisabled, \ NetworkContextType::kProfile}), \ @@ -981,6 +1003,9 @@ // Instiates tests with a prefix indicating which NetworkContext is being // tested, and a suffix of "/0" if the network service is disabled, "/1" if it's // enabled, and "/2" if it's enabled and restarted. +// +// TODO(mmenke): Enabled tests for the SafeBrowsing NetworkContext, once it +// works with the network service enabled. #define INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(TestFixture) \ INSTANTIATE_TEST_CASE_P( \ SystemNetworkContext, TestFixture, \ @@ -992,6 +1017,11 @@ NetworkContextType::kSystem}))); \ \ INSTANTIATE_TEST_CASE_P( \ + SafeBrowsingNetworkContext, TestFixture, \ + ::testing::Values(TestCase({NetworkServiceState::kDisabled, \ + NetworkContextType::kSafeBrowsing}))); \ + \ + INSTANTIATE_TEST_CASE_P( \ ProfileMainNetworkContext, TestFixture, \ ::testing::Values(TestCase({NetworkServiceState::kDisabled, \ NetworkContextType::kProfile}), \
diff --git a/chrome/browser/net/sth_distributor_provider.cc b/chrome/browser/net/sth_distributor_provider.cc deleted file mode 100644 index a0ecb31b..0000000 --- a/chrome/browser/net/sth_distributor_provider.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/sth_distributor_provider.h" - -#include "base/lazy_instance.h" -#include "components/certificate_transparency/sth_distributor.h" - -namespace chrome_browser_net { - -namespace { -base::LazyInstance<std::unique_ptr<certificate_transparency::STHDistributor>>:: - DestructorAtExit global_sth_distributor = LAZY_INSTANCE_INITIALIZER; -} // namespace - -void SetGlobalSTHDistributor( - std::unique_ptr<certificate_transparency::STHDistributor> distributor) { - global_sth_distributor.Get().swap(distributor); -} - -certificate_transparency::STHDistributor* GetGlobalSTHDistributor() { - CHECK(global_sth_distributor.Get()); - return global_sth_distributor.Get().get(); -} - -} // namespace chrome_browser_net
diff --git a/chrome/browser/net/sth_distributor_provider.h b/chrome/browser/net/sth_distributor_provider.h deleted file mode 100644 index c79f1ba..0000000 --- a/chrome/browser/net/sth_distributor_provider.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_NET_STH_DISTRIBUTOR_PROVIDER_H_ -#define CHROME_BROWSER_NET_STH_DISTRIBUTOR_PROVIDER_H_ - -#include <memory> - -namespace certificate_transparency { -class STHDistributor; -} // namespace certificate_transparency - -namespace chrome_browser_net { - -void SetGlobalSTHDistributor( - std::unique_ptr<certificate_transparency::STHDistributor> distributor); -certificate_transparency::STHDistributor* GetGlobalSTHDistributor(); - -} // namespace chrome_browser_net - -#endif // CHROME_BROWSER_NET_STH_DISTRIBUTOR_PROVIDER_H_
diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h index b051b2df..3538ddf2 100644 --- a/chrome/browser/notifications/message_center_notification_manager.h +++ b/chrome/browser/notifications/message_center_notification_manager.h
@@ -28,7 +28,7 @@ namespace message_center { class Notification; class NotificationBlocker; -FORWARD_DECLARE_TEST(WebNotificationTrayTest, ManuallyCloseMessageCenter); +FORWARD_DECLARE_TEST(NotificationTrayTest, ManuallyCloseMessageCenter); } #if !defined(OS_CHROMEOS) @@ -74,7 +74,7 @@ const std::string& delegate_id, Profile* profile); private: - FRIEND_TEST_ALL_PREFIXES(message_center::WebNotificationTrayTest, + FRIEND_TEST_ALL_PREFIXES(message_center::NotificationTrayTest, ManuallyCloseMessageCenter); std::unique_ptr<message_center::UiDelegate> tray_;
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm index f9e73f78..6254140 100644 --- a/chrome/browser/notifications/notification_platform_bridge_mac.mm +++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm
@@ -21,6 +21,7 @@ #include "base/strings/nullable_string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification_common.h" #include "chrome/browser/notifications/notification_display_service_impl.h"
diff --git a/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc b/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc index baf87d9..8253dc0c 100644 --- a/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc +++ b/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc
@@ -28,6 +28,7 @@ WebFeature::kPaymentHandler, WebFeature::kPaymentRequestShowWithoutGesture, WebFeature::kHTMLImports, WebFeature::kHTMLImportsHasStyleSheets, + WebFeature::kElementCreateShadowRoot, })); return opt_in_features.count(feature); }
diff --git a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc index 6917cf6..122bf70 100644 --- a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc
@@ -8,6 +8,7 @@ #include "services/metrics/public/cpp/ukm_builders.h" #include "base/metrics/histogram_macros.h" +#include "base/rand_util.h" using WebFeature = blink::mojom::WebFeature; using Features = page_load_metrics::mojom::PageLoadFeatures; @@ -53,6 +54,14 @@ UMA_HISTOGRAM_ENUMERATION(internal::kFeaturesHistogramName, feature, WebFeature::kNumberOfFeatures); features_recorded_.set(static_cast<size_t>(feature)); + // TODO(kochi): https://crbug.com/806671 as ElementCreateShadowRoot is + // ~12% as of April, 2018, and to meet the UKM's data volume expectation, + // reduce the data size by sampling. Revisit and remove this code once + // Shadow DOM V0 is removed. + const int kSamplingFactor = 10; + if (feature == WebFeature::kElementCreateShadowRoot && + base::RandGenerator(kSamplingFactor) != 0) + continue; if (IsAllowedUkmFeature(feature)) { ukm::builders::Blink_UseCounter(extra_info.source_id) .SetFeature(static_cast<int64_t>(feature))
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc index 488c8ce..0bf1325 100644 --- a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc +++ b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
@@ -92,13 +92,13 @@ } // namespace -class ComponentCloudPolicyTest : public ExtensionBrowserTest { +class ComponentCloudPolicyTest : public extensions::ExtensionBrowserTest { protected: ComponentCloudPolicyTest() {} ~ComponentCloudPolicyTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); #if defined(OS_CHROMEOS) // ExtensionBrowserTest sets the login users to a non-managed value; // replace it. This is the default username sent in policy blobs from the @@ -122,11 +122,11 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url); - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); } void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service())) << "Pre-existing policies in this machine will make this test fail."; @@ -147,7 +147,7 @@ void TearDownOnMainThread() override { event_listener_.reset(); - ExtensionBrowserTest::TearDownOnMainThread(); + extensions::ExtensionBrowserTest::TearDownOnMainThread(); } scoped_refptr<const extensions::Extension> LoadExtension( @@ -158,7 +158,8 @@ return NULL; } scoped_refptr<const extensions::Extension> extension( - ExtensionBrowserTest::LoadExtension(full_path.Append(path))); + extensions::ExtensionBrowserTest::LoadExtension( + full_path.Append(path))); if (!extension.get()) { ADD_FAILURE(); return NULL;
diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc index 7163747..2063e82d 100644 --- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc +++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -182,7 +182,7 @@ // Based on top of ExtensionBrowserTest to allow easy interaction with the // ExtensionService. class PrefHashBrowserTestBase - : public ExtensionBrowserTest, + : public extensions::ExtensionBrowserTest, public testing::WithParamInterface<std::string> { public: // List of potential protection levels for this test in strict increasing @@ -203,7 +203,7 @@ } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); EXPECT_FALSE(command_line->HasSwitch(switches::kForceFieldTrials)); command_line->AppendSwitchASCII( switches::kForceFieldTrials, @@ -219,7 +219,7 @@ // Do the normal setup in the PRE test and attack preferences in the main // test. if (content::IsPreTest()) - return ExtensionBrowserTest::SetUpUserDataDirectory(); + return extensions::ExtensionBrowserTest::SetUpUserDataDirectory(); #if defined(OS_CHROMEOS) // For some reason, the Preferences file does not exist in the location @@ -284,7 +284,7 @@ } void SetUpInProcessBrowserTestFixture() override { - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); // Bots are on a domain, turn off the domain check for settings hardening in // order to be able to test all SettingsEnforcement groups. @@ -324,14 +324,14 @@ } } #endif - ExtensionBrowserTest::TearDown(); + extensions::ExtensionBrowserTest::TearDown(); } // In the PRE_ test, find the number of tracked preferences that were // initialized and save it to a file to be read back in the main test and used // as the total number of tracked preferences. void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); // File in which the PRE_ test will save the number of tracked preferences // on this platform.
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index 970f22f..d3ba95a0 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -243,7 +243,7 @@ constexpr char IsolateOriginsPrintBrowserTest::kIsolatedSite[]; -class PrintExtensionBrowserTest : public ExtensionBrowserTest { +class PrintExtensionBrowserTest : public extensions::ExtensionBrowserTest { public: PrintExtensionBrowserTest() {} ~PrintExtensionBrowserTest() override {}
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index e5da067..c064617 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -58,7 +58,6 @@ #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_contents.h" #include "extensions/buildflags/buildflags.h" -#include "net/http/http_server_properties.h" #include "net/http/transport_security_state.h" #include "ppapi/buildflags/buildflags.h" #include "services/preferences/public/cpp/in_process_service_factory.h"
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 6c1d26a6..1c483e18 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -66,8 +66,6 @@ #include "net/cookies/cookie_store.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" -#include "net/http/http_server_properties.h" -#include "net/http/http_server_properties_manager.h" #include "net/net_buildflags.h" #include "net/ssl/channel_id_service.h" #include "net/url_request/url_request_context_builder.h"
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index ee51e6f1..bd9dd3e 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -713,12 +713,6 @@ domain_reliability_monitor_unowned_->Shutdown(); if (main_request_context_) { - // Prevent the TreeStateTracker from getting any more notifications by - // severing the link between it and the CTVerifier and unregistering it from - // new STH notifications. - main_request_context_->cert_transparency_verifier()->SetObserver(nullptr); - ct_tree_tracker_unregistration_.Run(); - // Destroy certificate_report_sender_ before main_request_context_, // since the former has a reference to the latter. main_request_context_->transport_security_state()->SetReportSender(nullptr); @@ -1180,23 +1174,6 @@ std::move(profile_params_->new_tab_page_interceptor)); } - std::unique_ptr<net::MultiLogCTVerifier> ct_verifier( - new net::MultiLogCTVerifier()); - ct_verifier->AddLogs(io_thread_globals->ct_logs); - - ct_tree_tracker_.reset(new certificate_transparency::TreeStateTracker( - io_thread_globals->ct_logs, - io_thread_globals->system_request_context->host_resolver(), - io_thread->net_log())); - ct_verifier->SetObserver(ct_tree_tracker_.get()); - - builder->set_ct_verifier(std::move(ct_verifier)); - - io_thread->RegisterSTHObserver(ct_tree_tracker_.get()); - ct_tree_tracker_unregistration_ = - base::Bind(&IOThread::UnregisterSTHObserver, base::Unretained(io_thread), - ct_tree_tracker_.get()); - if (data_reduction_proxy_io_data_.get()) { builder->set_shared_proxy_delegate( data_reduction_proxy_io_data_->proxy_delegate());
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 1f960a2..8591e08b 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -53,10 +53,6 @@ class LoadingPredictorObserver; } -namespace certificate_transparency { -class TreeStateTracker; -} - namespace content_settings { class CookieSettings; } @@ -646,10 +642,6 @@ extension_throttle_manager_; #endif - mutable std::unique_ptr<certificate_transparency::TreeStateTracker> - ct_tree_tracker_; - mutable base::Closure ct_tree_tracker_unregistration_; - // Owned by the ChromeNetworkDelegate, which is owned (possibly with one or // more layers of LayeredNetworkDelegate) by the URLRequestContext, which is // owned by main_network_context_.
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index 83530a7..5696dbaa 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -2388,104 +2388,3 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); ASSERT_EQ("false - not subscribed", script_result); } - -#if BUILDFLAG(ENABLE_BACKGROUND_MODE) -// Push background mode is disabled by default. -IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, - BackgroundModeDisabledByDefault) { - // Initially background mode is inactive. - BackgroundModeManager* background_mode_manager = - g_browser_process->background_mode_manager(); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); - - // Once there is a push subscription background mode is still inactive. - ASSERT_NO_FATAL_FAILURE(SubscribeSuccessfully()); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); - - // After dropping the last subscription it is still inactive. - std::string script_result; - base::RunLoop run_loop; - push_service()->SetUnsubscribeCallbackForTesting(run_loop.QuitClosure()); - ASSERT_TRUE(RunScript("unsubscribePush()", &script_result)); - EXPECT_EQ("unsubscribe result: true", script_result); - // Background mode is only guaranteed to have updated once the unsubscribe - // callback for testing has been run (PushSubscription.unsubscribe() usually - // resolves before that, in order to avoid blocking on network retries etc). - run_loop.Run(); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); -} - -class PushMessagingBackgroundModeEnabledBrowserTest - : public PushMessagingBrowserTest { - public: - ~PushMessagingBackgroundModeEnabledBrowserTest() override {} - - // PushMessagingBrowserTest: - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kEnablePushApiBackgroundMode); - PushMessagingBrowserTest::SetUpCommandLine(command_line); - } -}; - -// In this test the command line enables push background mode. -IN_PROC_BROWSER_TEST_F(PushMessagingBackgroundModeEnabledBrowserTest, - BackgroundModeEnabledWithCommandLine) { - // Initially background mode is inactive. - BackgroundModeManager* background_mode_manager = - g_browser_process->background_mode_manager(); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); - - // Once there is a push subscription background mode is active. - ASSERT_NO_FATAL_FAILURE(SubscribeSuccessfully()); - ASSERT_TRUE(background_mode_manager->IsBackgroundModeActive()); - - // Dropping the last subscription deactivates background mode. - std::string script_result; - base::RunLoop run_loop; - push_service()->SetUnsubscribeCallbackForTesting(run_loop.QuitClosure()); - ASSERT_TRUE(RunScript("unsubscribePush()", &script_result)); - EXPECT_EQ("unsubscribe result: true", script_result); - // Background mode is only guaranteed to have updated once the unsubscribe - // callback for testing has been run (PushSubscription.unsubscribe() usually - // resolves before that, in order to avoid blocking on network retries etc). - run_loop.Run(); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); -} - -class PushMessagingBackgroundModeDisabledBrowserTest - : public PushMessagingBrowserTest { - public: - ~PushMessagingBackgroundModeDisabledBrowserTest() override {} - - // PushMessagingBrowserTest: - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kDisablePushApiBackgroundMode); - PushMessagingBrowserTest::SetUpCommandLine(command_line); - } -}; - -// In this test the command line disables push background mode. -IN_PROC_BROWSER_TEST_F(PushMessagingBackgroundModeDisabledBrowserTest, - BackgroundModeDisabledWithCommandLine) { - // Initially background mode is inactive. - BackgroundModeManager* background_mode_manager = - g_browser_process->background_mode_manager(); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); - - // Once there is a push subscription background mode is still inactive. - ASSERT_NO_FATAL_FAILURE(SubscribeSuccessfully()); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); - - // After dropping the last subscription background mode is still inactive. - std::string script_result; - base::RunLoop run_loop; - push_service()->SetUnsubscribeCallbackForTesting(run_loop.QuitClosure()); - ASSERT_TRUE(RunScript("unsubscribePush()", &script_result)); - EXPECT_EQ("unsubscribe result: true", script_result); - // Background mode is only guaranteed to have updated once the unsubscribe - // callback for testing has been run (PushSubscription.unsubscribe() usually - // resolves before that, in order to avoid blocking on network retries etc). - run_loop.Run(); - ASSERT_FALSE(background_mode_manager->IsBackgroundModeActive()); -} -#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE)
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index 0e7634a..099ffc1 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -128,19 +128,6 @@ closure.Run(); } -#if BUILDFLAG(ENABLE_BACKGROUND_MODE) -bool UseBackgroundMode() { - // Note: if push is ever enabled in incognito, the background mode integration - // should not be enabled for it. - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisablePushApiBackgroundMode)) - return false; - if (command_line->HasSwitch(switches::kEnablePushApiBackgroundMode)) - return true; - return base::FeatureList::IsEnabled(features::kPushMessagingBackgroundMode); -} -#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE) - } // namespace // static @@ -176,21 +163,13 @@ void PushMessagingServiceImpl::IncreasePushSubscriptionCount(int add, bool is_pending) { DCHECK_GT(add, 0); - if (push_subscription_count_ + pending_push_subscription_count_ == 0) { + if (push_subscription_count_ + pending_push_subscription_count_ == 0) GetGCMDriver()->AddAppHandler(kPushMessagingAppIdentifierPrefix, this); - } - if (is_pending) { + + if (is_pending) pending_push_subscription_count_ += add; - } else { -#if BUILDFLAG(ENABLE_BACKGROUND_MODE) - if (UseBackgroundMode() && g_browser_process->background_mode_manager() && - !push_subscription_count_) { - g_browser_process->background_mode_manager()->RegisterTrigger( - profile_, this, false /* should_notify_user */); - } -#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE) + else push_subscription_count_ += add; - } } void PushMessagingServiceImpl::DecreasePushSubscriptionCount(int subtract, @@ -203,16 +182,9 @@ push_subscription_count_ -= subtract; DCHECK_GE(push_subscription_count_, 0); } - if (push_subscription_count_ + pending_push_subscription_count_ == 0) { - GetGCMDriver()->RemoveAppHandler(kPushMessagingAppIdentifierPrefix); -#if BUILDFLAG(ENABLE_BACKGROUND_MODE) - if (UseBackgroundMode() && g_browser_process->background_mode_manager()) { - g_browser_process->background_mode_manager()->UnregisterTrigger(profile_, - this); - } -#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE) - } + if (push_subscription_count_ + pending_push_subscription_count_ == 0) + GetGCMDriver()->RemoveAppHandler(kPushMessagingAppIdentifierPrefix); } bool PushMessagingServiceImpl::CanHandle(const std::string& app_id) const { @@ -1022,23 +994,6 @@ HostContentSettingsMapFactory::GetForProfile(profile_)->RemoveObserver(this); } -// BackgroundTrigger methods --------------------------------------------------- -base::string16 PushMessagingServiceImpl::GetName() { - return l10n_util::GetStringUTF16(IDS_NOTIFICATIONS_BACKGROUND_SERVICE_NAME); -} - -gfx::ImageSkia* PushMessagingServiceImpl::GetIcon() { - return nullptr; -} - -void PushMessagingServiceImpl::OnMenuClick() { -#if BUILDFLAG(ENABLE_BACKGROUND_MODE) - chrome::ShowContentSettings( - BackgroundModeManager::GetBrowserWindowForProfile(profile_), - CONTENT_SETTINGS_TYPE_NOTIFICATIONS); -#endif // BUILDFLAG(ENABLE_BACKGROUND_MODE) -} - // content::NotificationObserver methods --------------------------------------- void PushMessagingServiceImpl::Observe(
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.h b/chrome/browser/push_messaging/push_messaging_service_impl.h index 16dca4d1..0dd1164 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.h +++ b/chrome/browser/push_messaging/push_messaging_service_impl.h
@@ -15,7 +15,6 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/background/background_trigger.h" #include "chrome/browser/push_messaging/push_messaging_notification_manager.h" #include "chrome/common/buildflags.h" #include "components/content_settings/core/browser/content_settings_observer.h" @@ -56,7 +55,6 @@ public gcm::GCMAppHandler, public content_settings::Observer, public KeyedService, - public BackgroundTrigger, public content::NotificationObserver { public: // If any Service Workers are using push, starts GCM and adds an app handler. @@ -120,11 +118,6 @@ // KeyedService implementation. void Shutdown() override; - // BackgroundTrigger implementation. - base::string16 GetName() override; - gfx::ImageSkia* GetIcon() override; - void OnMenuClick() override; - // content::NotificationObserver: void Observe(int type, const content::NotificationSource& source,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index c4817553b7..d9af8bd 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -130,10 +130,12 @@ #include "third_party/metrics_proto/omnibox_input_type.pb.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" +#include "ui/base/emoji/emoji_panel_helper.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/text_elider.h" +#include "ui/strings/grit/ui_strings.h" #if !BUILDFLAG(USE_BROWSER_SPELLCHECKER) #include "chrome/browser/renderer_context_menu/spelling_options_submenu_observer.h" @@ -1406,6 +1408,11 @@ AppendSearchProvider(); menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); } + if (params_.misspelled_word.empty() && ui::IsEmojiPanelSupported()) { + menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_EMOJI, + IDS_CONTENT_CONTEXT_EMOJI); + menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); + } // 'Undo' and 'Redo' for text input with no suggestions and no text selected. // We make an exception for OS X as context clicking will select the closest @@ -1736,6 +1743,9 @@ return !!(params_.media_flags & WebContextMenuData::kMediaCanPictureInPicture); + case IDC_CONTENT_CONTEXT_EMOJI: + return params_.is_editable; + default: NOTREACHED(); return false; @@ -1753,6 +1763,9 @@ if (id == IDC_CONTENT_CONTEXT_CONTROLS) return (params_.media_flags & WebContextMenuData::kMediaControls) != 0; + if (id == IDC_CONTENT_CONTEXT_EMOJI) + return false; + // Extension items. if (ContextMenuMatcher::IsExtensionsCustomCommandId(id)) return extension_items_.IsCommandIdChecked(id); @@ -2025,6 +2038,10 @@ ExecPictureInPicture(); break; + case IDC_CONTENT_CONTEXT_EMOJI: + ui::ShowEmojiPanel(); + break; + default: NOTREACHED(); break;
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 405209d7..e3c6d9d7 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
@@ -73,7 +73,9 @@ #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/platform/web_input_event.h" #include "third_party/blink/public/web/web_context_menu_data.h" +#include "ui/base/emoji/emoji_panel_helper.h" #include "ui/base/models/menu_model.h" +#include "ui/base/ui_base_features.h" #if defined(OS_CHROMEOS) #include "ash/public/cpp/window_properties.h" @@ -490,6 +492,57 @@ ASSERT_TRUE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_COPYIMAGE)); } +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, + ContextMenuForEmojiPanel_Enabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); + + content::ContextMenuParams params; + params.is_editable = true; + + TestRenderViewContextMenu menu( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), + params); + menu.Init(); + + EXPECT_EQ(ui::IsEmojiPanelSupported(), + menu.IsItemPresent(IDC_CONTENT_CONTEXT_EMOJI)); +} + +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, + ContextMenuForEmojiPanel_Enabled_NonEditable) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEnableEmojiContextMenu); + + content::ContextMenuParams params; + params.is_editable = false; + + TestRenderViewContextMenu menu( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), + params); + menu.Init(); + + // Emoji context menu item should never be present on a non-editable field. + EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_EMOJI)); +} + +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, + ContextMenuForEmojiPanel_Disabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kEnableEmojiContextMenu); + + content::ContextMenuParams params; + params.is_editable = true; + + TestRenderViewContextMenu menu( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), + params); + menu.Init(); + + // If the feature is disabled, the emoji context menu should never be present. + EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_EMOJI)); +} + IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, CopyLinkTextMouse) { std::unique_ptr<TestRenderViewContextMenu> menu = CreateContextMenu( GURL("http://www.google.com/"), GURL("http://www.google.com/"),
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc index b568c07..4eac930 100644 --- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc +++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -85,7 +85,7 @@ } // namespace -class ChromeRenderProcessHostTest : public ExtensionBrowserTest { +class ChromeRenderProcessHostTest : public extensions::ExtensionBrowserTest { public: ChromeRenderProcessHostTest() {}
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.cc b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.cc index 53eafce1..fd7b17dc 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.cc +++ b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.cc
@@ -7,7 +7,6 @@ #include <vector> #include "base/bind.h" -#include "base/values.h" #include "build/build_config.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" @@ -27,9 +26,6 @@ constexpr base::TimeDelta kDefaultMeasurementInterval = base::TimeDelta::FromMinutes(10); -base::LazyInstance<ResourceCoordinatorRenderProcessProbe>::DestructorAtExit - g_probe = LAZY_INSTANCE_INITIALIZER; - } // namespace ResourceCoordinatorRenderProcessProbe::RenderProcessInfo::RenderProcessInfo() = @@ -49,7 +45,8 @@ // static ResourceCoordinatorRenderProcessProbe* ResourceCoordinatorRenderProcessProbe::GetInstance() { - return g_probe.Pointer(); + static base::NoDestructor<ResourceCoordinatorRenderProcessProbe> probe; + return probe.get(); } // static @@ -132,16 +129,24 @@ content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&ResourceCoordinatorRenderProcessProbe:: - CollectAndDispatchRenderProcessMetricsOnIOThread, - base::Unretained(this))); + base::BindOnce( + &ResourceCoordinatorRenderProcessProbe:: + CollectRenderProcessMetricsAndStartMemoryDumpOnIOThread, + base::Unretained(this))); } void ResourceCoordinatorRenderProcessProbe:: - CollectAndDispatchRenderProcessMetricsOnIOThread() { + CollectRenderProcessMetricsAndStartMemoryDumpOnIOThread() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(is_gathering_); + // Dispatch the memory collection request. + memory_instrumentation::MemoryInstrumentation::GetInstance() + ->RequestGlobalDump( + base::BindRepeating(&ResourceCoordinatorRenderProcessProbe:: + ProcessGlobalMemoryDumpAndDispatchOnIOThread, + base::Unretained(this))); + RenderProcessInfoMap::iterator iter = render_process_info_map_.begin(); while (iter != render_process_info_map_.end()) { auto& render_process_info = iter->second; @@ -157,12 +162,21 @@ continue; } } +} +void ResourceCoordinatorRenderProcessProbe:: + ProcessGlobalMemoryDumpAndDispatchOnIOThread( + bool global_success, + std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump) { // Create the measurement batch. mojom::ProcessResourceMeasurementBatchPtr batch = mojom::ProcessResourceMeasurementBatch::New(); - for (auto& render_process_info_map_entry : render_process_info_map_) { + // TODO(siggi): Add start/end times. This will need some support from + // the memory_instrumentation code. + + // Start by adding the render process hosts we know about to the batch. + for (const auto& render_process_info_map_entry : render_process_info_map_) { auto& render_process_info = render_process_info_map_entry.second; // TODO(oysteine): Move the multiplier used to avoid precision loss // into a shared location, when this property gets used. @@ -171,13 +185,35 @@ measurement->pid = render_process_info.process.Pid(); measurement->cpu_usage = render_process_info.cpu_usage; - // TODO(siggi): Add the private footprint. batch->measurements.push_back(std::move(measurement)); } - bool should_restart = DispatchMetrics(std::move(batch)); + if (dump) { + // Then amend the ones we have memory metrics for with their private + // footprint. The global dump may contain non-renderer processes, it may + // contain renderer processes we didn't capture at the start of the cycle, + // and it may not contain all the renderer processes we know about. + // This may happen due to the inherent race between the request and + // starting/stopping renderers, or because of other failures + // This may therefore provide incomplete information. + for (const auto& dump_entry : dump->process_dumps()) { + base::ProcessId pid = dump_entry.pid(); + for (const auto& measurement : batch->measurements) { + if (measurement->pid == pid) { + measurement->private_footprint_kb = + dump_entry.os_dump().private_footprint_kb; + break; + } + } + } + } else { + // We should only get a nullptr in case of failure. + DCHECK(!global_success); + } + + bool should_restart = DispatchMetrics(std::move(batch)); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::BindOnce(
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.h b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.h index 7849d48..057ec82 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.h +++ b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe.h
@@ -9,11 +9,12 @@ #include <memory> #include <utility> -#include "base/lazy_instance.h" #include "base/macros.h" +#include "base/no_destructor.h" #include "base/process/process.h" #include "base/process/process_metrics.h" #include "base/timer/timer.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" #include "services/resource_coordinator/public/cpp/system_resource_coordinator.h" namespace resource_coordinator { @@ -41,6 +42,7 @@ void StartSingleGather(); protected: + // Internal state protected for testing. struct RenderProcessInfo { RenderProcessInfo(); ~RenderProcessInfo(); @@ -51,9 +53,7 @@ }; using RenderProcessInfoMap = std::map<int, RenderProcessInfo>; - // Internal state protected for testing. - friend struct base::LazyInstanceTraitsBase< - ResourceCoordinatorRenderProcessProbe>; + friend class base::NoDestructor<ResourceCoordinatorRenderProcessProbe>; ResourceCoordinatorRenderProcessProbe(); virtual ~ResourceCoordinatorRenderProcessProbe(); @@ -61,10 +61,13 @@ // (1) Identify all of the render processes that are active to measure. // Child render processes can only be discovered in the browser's UI thread. void RegisterAliveRenderProcessesOnUIThread(); - // (2) Collect and dispatch the render process metrics to the system - // coordination unit. - void CollectAndDispatchRenderProcessMetricsOnIOThread(); - // (3) Initiate the next render process metrics collection cycle if the + // (2) Collect the render process CPU metrics and initiate a memory dump. + void CollectRenderProcessMetricsAndStartMemoryDumpOnIOThread(); + // (3) Process the results of the memory dump and dispatch the results. + void ProcessGlobalMemoryDumpAndDispatchOnIOThread( + bool success, + std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump); + // (4) Initiate the next render process metrics collection cycle if the // cycle has been started and |restart_cycle| is true, which consists of a // delayed call to perform (1) via a timer. // Virtual for testing.
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc index 80d9718..92cdfe5c 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc +++ b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
@@ -102,6 +102,16 @@ ResourceCoordinatorRenderProcessProbeBrowserTest() = default; ~ResourceCoordinatorRenderProcessProbeBrowserTest() override = default; + static bool AtLeastOneMemoryMeasurementIsNonZero( + const mojom::ProcessResourceMeasurementBatchPtr& batch) { + for (const auto& measurement : batch->measurements) { + if (measurement->private_footprint_kb > 0) + return true; + } + + return false; + } + private: DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorRenderProcessProbeBrowserTest); }; @@ -138,6 +148,11 @@ for (const auto& measurement : probe.last_measurement_batch()->measurements) EXPECT_EQ(0.0, measurement->cpu_usage); + // There is an inherent race in memory measurement that may cause failures + // which will result in zero private footprint returns. To work around this, + // assert that there is at least one non-zero measurement. + AtLeastOneMemoryMeasurementIsNonZero(probe.last_measurement_batch()); + // Open a second tab and complete a navigation. ui_test_utils::NavigateToURLWithDisposition( browser(), embedded_test_server()->GetURL("/title1.html"), @@ -163,10 +178,14 @@ size_t info_map_size = info_map.size(); probe.StartGatherCycleAndWait(); - // The second and subsequent CPU measurements should return some data. + // The second and subsequent CPU measurements should return some data, + // although the measurement granularity on some OSen is such that zero returns + // are almost certain. for (const auto& measurement : probe.last_measurement_batch()->measurements) EXPECT_LE(0.0, measurement->cpu_usage); + AtLeastOneMemoryMeasurementIsNonZero(probe.last_measurement_batch()); + EXPECT_EQ(info_map_size, info_map.size()); for (const auto& entry : probe.render_process_info_map()) { const int key = entry.first;
diff --git a/chrome/browser/resources/PRESUBMIT.py b/chrome/browser/resources/PRESUBMIT.py index 6767998..a8156d4 100644 --- a/chrome/browser/resources/PRESUBMIT.py +++ b/chrome/browser/resources/PRESUBMIT.py
@@ -8,8 +8,6 @@ for more details about the presubmit API built into depot_tools. """ -import os - ACTION_XML_PATH = '../../../tools/metrics/actions/actions.xml' @@ -125,8 +123,8 @@ results += CheckHtml(input_api, output_api) webui_sources = set(['optimize_webui.py', 'unpack_pak.py']) - affected_filenames = set([os.path.basename(f.LocalPath()) for f in affected]) - if webui_sources.intersection(affected_filenames): + affected_files = [input_api.os_path.basename(f.LocalPath()) for f in affected] + if webui_sources.intersection(set(affected_files)): results += RunOptimizeWebUiTests(input_api, output_api) results += _CheckWebDevStyle(input_api, output_api) results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
diff --git a/chrome/browser/resources/chromeos/arc_support/main.html b/chrome/browser/resources/chromeos/arc_support/main.html index ee3b3bb..30ab6322 100644 --- a/chrome/browser/resources/chromeos/arc_support/main.html +++ b/chrome/browser/resources/chromeos/arc_support/main.html
@@ -8,9 +8,9 @@ <link rel="stylesheet" href="chrome://resources/css/controlled_indicator.css"> <link rel="stylesheet" href="chrome://resources/css/overlay.css"> <link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> - <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <style is="custom-style" include="iron-flex iron-flex-alignment"> paper-button { border-radius: 4px; @@ -49,13 +49,6 @@ background-color: rgb(66, 133, 244); /* #4285f4 */ color: white; } - paper-checkbox { - --paper-checkbox-size: 12px; - --paper-checkbox-checked-color: rgb(66, 133, 244); /* #4285f4 */ - --paper-checkbox-ink-size: 36px; - --paper-checkbox-label-spacing: 20px; - --paper-checkbox-vertical-align: top; - } </style> <link rel="stylesheet" href="main.css"> <link rel="stylesheet" href="progressbar.css"> @@ -108,26 +101,26 @@ </div> <div id="metrics-preference"> <label class="layout horizontal section-checkbox-container"> - <paper-checkbox class="checkbox-option"> + <cr-checkbox class="checkbox-option"> <p class="checkbox-text"></p> - </paper-checkbox> + </cr-checkbox> <p class="content-text"></p> </label> </div> <div id="backup-restore-preference"> <label class="layout horizontal section-checkbox-container"> - <paper-checkbox class="checkbox-option"> + <cr-checkbox class="checkbox-option"> <p class="checkbox-text" i18n-values=".innerHTML:textBackupRestore"></p> - </paper-checkbox> + </cr-checkbox> </label> </div> <div id="location-service-preference"> <label class="layout horizontal section-checkbox-container"> - <paper-checkbox class="checkbox-option"> + <cr-checkbox class="checkbox-option"> <p class="checkbox-text" i18n-values=".innerHTML:textLocationService"></p> - </paper-checkbox> + </cr-checkbox> </label> </div> <div id="pai-service-descirption">
diff --git a/chrome/browser/resources/chromeos/emulator/audio_settings.html b/chrome/browser/resources/chromeos/emulator/audio_settings.html index 966f6bd0..91ab575f 100644 --- a/chrome/browser/resources/chromeos/emulator/audio_settings.html +++ b/chrome/browser/resources/chromeos/emulator/audio_settings.html
@@ -1,10 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> @@ -32,13 +33,13 @@ </div> <div class="form-field-section"> <span class="toggle-button-label">Is Input</span> - <paper-checkbox - checked="{{currentEditableObject.isInput}}"></paper-checkbox> + <cr-checkbox + checked="{{currentEditableObject.isInput}}"></cr-checkbox> </div> <div class="form-field-section"> <span class="toggle-button-label">Active</span> - <paper-checkbox - checked="{{currentEditableObject.active}}"></paper-checkbox> + <cr-checkbox + checked="{{currentEditableObject.active}}"></cr-checkbox> </div> <div class="form-field-section"> <div class="form-label">Audio Type</div> @@ -88,12 +89,12 @@ </paper-icon-button> </td> <td class="control-cell"> - <paper-checkbox checked="{{item.isInput}}" - on-change="insertAudioNode"></paper-checkbox> + <cr-checkbox checked="{{item.isInput}}" + on-change="insertAudioNode"></cr-checkbox> </td> <td class="control-cell"> - <paper-checkbox checked="{{item.active}}" - on-change="insertAudioNode"></paper-checkbox> + <cr-checkbox checked="{{item.active}}" + on-change="insertAudioNode"></cr-checkbox> </td> </tr> </template>
diff --git a/chrome/browser/resources/chromeos/emulator/battery_settings.html b/chrome/browser/resources/chromeos/emulator/battery_settings.html index 8454f6b..9c82510 100644 --- a/chrome/browser/resources/chromeos/emulator/battery_settings.html +++ b/chrome/browser/resources/chromeos/emulator/battery_settings.html
@@ -1,9 +1,10 @@ <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> @@ -60,7 +61,7 @@ <tr> <td class="alias-cell">[[item.name]]</td> <td class="control-cell"> - <paper-checkbox checked="{{item.connected}}"></paper-checkbox> + <cr-checkbox checked="{{item.connected}}"></cr-checkbox> </td> <td class="control-cell"> <paper-button on-tap="onSetAsSourceTap"
diff --git a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html index e804c7b..f70afe59 100644 --- a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html +++ b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html
@@ -1,10 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> @@ -38,13 +39,13 @@ </div> <div class="form-field-section"> <span class="toggle-button-label">Trusted</span> - <paper-checkbox - checked="{{currentEditableObject.isTrusted}}"></paper-checkbox> + <cr-checkbox + checked="{{currentEditableObject.isTrusted}}"></cr-checkbox> </div> <div class="form-field-section"> <span class="toggle-button-label">Incoming Connnection</span> - <paper-checkbox - checked="{{currentEditableObject.incoming}}"></paper-checkbox> + <cr-checkbox + checked="{{currentEditableObject.incoming}}"></cr-checkbox> </div> <div class="form-field-section"> <div class="form-label">Class</div> @@ -126,13 +127,13 @@ </paper-icon-button> </td> <td class="control-cell"> - <paper-checkbox checked="{{item.discoverable}}" + <cr-checkbox checked="{{item.discoverable}}" data-predefined="true" - on-change="discoverDevice"></paper-checkbox> + on-change="discoverDevice"></cr-checkbox> </td> <td class="control-cell"> - <paper-checkbox on-change="pairDevice" data-predefined="true" - checked="{{item.paired}}"></paper-checkbox> + <cr-checkbox on-change="pairDevice" data-predefined="true" + checked="{{item.paired}}"></cr-checkbox> </td> </tr> </template> @@ -156,14 +157,14 @@ </paper-icon-button> </td> <td class="control-cell"> - <paper-checkbox checked="{{item.discoverable}}" + <cr-checkbox checked="{{item.discoverable}}" data-predefined="false" - on-change="discoverDevice"></paper-checkbox> + on-change="discoverDevice"></cr-checkbox> </td> <td class="control-cell"> - <paper-checkbox checked="{{item.paired}}" + <cr-checkbox checked="{{item.paired}}" data-predefined="false" - on-change="pairDevice"></paper-checkbox> + on-change="pairDevice"></cr-checkbox> </td> </tr> </template>
diff --git a/chrome/browser/resources/chromeos/emulator/shared_styles.html b/chrome/browser/resources/chromeos/emulator/shared_styles.html index 81b57e8..bdf06ea39 100644 --- a/chrome/browser/resources/chromeos/emulator/shared_styles.html +++ b/chrome/browser/resources/chromeos/emulator/shared_styles.html
@@ -9,10 +9,6 @@ width: 200px; } - #editModal paper-checkbox { - -webkit-margin-start: 15px; - } - paper-radio-button { display: inline-block; }
diff --git a/chrome/browser/resources/chromeos/login/arc_terms_of_service.css b/chrome/browser/resources/chromeos/login/arc_terms_of_service.css index 76ceff1..ad8d4af 100644 --- a/chrome/browser/resources/chromeos/login/arc_terms_of_service.css +++ b/chrome/browser/resources/chromeos/login/arc_terms_of_service.css
@@ -54,14 +54,6 @@ padding: 0 20px 16px 20px; } -#arc-enable-backup-restore, -#arc-enable-location-service { - --paper-checkbox-size: 12px; - --paper-checkbox-checked-color: rgb(66, 133, 244); /* #4285f4 */ - --paper-checkbox-label-spacing: 20px; - --paper-checkbox-vertical-align: top; -} - #arc-policy-link { margin: 0; padding: 16px 0 16px 20px; @@ -71,7 +63,6 @@ color: rgba(0, 0, 0, 0.54); } - #google-service-confirmation-text { font-weight: 600; }
diff --git a/chrome/browser/resources/chromeos/login/arc_terms_of_service.html b/chrome/browser/resources/chromeos/login/arc_terms_of_service.html index e573241c..d493de2 100644 --- a/chrome/browser/resources/chromeos/login/arc_terms_of_service.html +++ b/chrome/browser/resources/chromeos/login/arc_terms_of_service.html
@@ -2,11 +2,10 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> - <dom-module id="arc-tos-root"> <template> <link rel="stylesheet" href="arc_terms_of_service.css"> @@ -31,15 +30,15 @@ <p id="arc-text-metrics"></p> </div> <div class="parameter-section arc-tos-content"> - <paper-checkbox id="arc-enable-backup-restore"> + <cr-checkbox id="arc-enable-backup-restore"> <p i18n-values=".innerHTML:arcTextBackupRestore"></p> - </paper-checkbox> + </cr-checkbox> </div> <div id= "arc-location-service" class="parameter-section arc-tos-content"> - <paper-checkbox id="arc-enable-location-service"> + <cr-checkbox id="arc-enable-location-service"> <p i18n-values=".innerHTML:arcTextLocationService"></p> - </paper-checkbox> + </cr-checkbox> </div> <div id="arc-pai-service" class="parameter-section arc-tos-content"> <p i18n-values=".innerHTML:arcTextPaiService"></p>
diff --git a/chrome/browser/resources/chromeos/login/gaia_input.css b/chrome/browser/resources/chromeos/login/gaia_input.css index 419ac1b..58a371b 100644 --- a/chrome/browser/resources/chromeos/login/gaia_input.css +++ b/chrome/browser/resources/chromeos/login/gaia_input.css
@@ -26,6 +26,10 @@ color: rgba(0, 0, 0, 0.54); } +iron-input input { + @apply --paper-input-container-shared-input-style; +} + :host-context(html[dir=rtl]) input { flex-direction: row-reverse; }
diff --git a/chrome/browser/resources/chromeos/login/gaia_input.html b/chrome/browser/resources/chromeos/login/gaia_input.html index 305be84..460c8a9b 100644 --- a/chrome/browser/resources/chromeos/login/gaia_input.html +++ b/chrome/browser/resources/chromeos/login/gaia_input.html
@@ -44,10 +44,13 @@ <paper-input-container id="decorator" on-tap="onTap" invalid="[[isInvalid]]" disabled$="[[disabled]]"> <label slot="label"><span>[[label]]</span></label> - <input id="input" is="iron-input" on-keydown="onKeyDown" - bind-value="{{value}}" invalid="[[isInvalid]]" slot="input" + <iron-input id="ironInput" slot="input" class="flex" + bind-value="{{value}}"> + <input id="input" on-keydown="onKeyDown" + value="{{value::input}}" invalid="[[isInvalid]]" required$="[[required]]" disabled$="[[disabled]]" - pattern$="[[pattern]]" class="flex"> + pattern$="[[pattern]]"> + </iron-input> <span id="domainLabel" slot="suffix">[[domain]]</span> <template is="dom-if" if="[[error]]"> <paper-input-error slot="add-on">[[error]]</paper-input-error>
diff --git a/chrome/browser/resources/chromeos/login/gaia_input.js b/chrome/browser/resources/chromeos/login/gaia_input.js index f04d94e31..a273b57 100644 --- a/chrome/browser/resources/chromeos/login/gaia_input.js +++ b/chrome/browser/resources/chromeos/login/gaia_input.js
@@ -49,7 +49,7 @@ }, checkValidity: function() { - var valid = this.$.input.validate(); + var valid = this.$.ironInput.validate(); this.isInvalid = !valid; return valid; },
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.css b/chrome/browser/resources/chromeos/login/oobe_a11y_option.css index 4ada0f6..cabd813 100644 --- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.css +++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
@@ -13,7 +13,8 @@ width: inherit; } -paper-toggle-button { +cr-toggle { + align-self: center; width: 36px; }
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.html b/chrome/browser/resources/chromeos/login/oobe_a11y_option.html index b48fcde8..f5b51957 100644 --- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.html +++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <dom-module id="oobe-a11y-option"> <template> @@ -18,9 +19,9 @@ <content select=".unchecked-value"></content> </div> </div> - <paper-toggle-button id="button" checked="{{checked}}" + <cr-toggle id="button" checked="{{checked}}" aria-label$="[[labelForAria]]"> - </paper-toggle-button> + </cr-toggle> </div> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.js b/chrome/browser/resources/chromeos/login/oobe_a11y_option.js index 2596b63e..b76b6480 100644 --- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.js +++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.js
@@ -7,18 +7,14 @@ properties: { /** - * If paper-toggle-button is checked. + * If cr-toggle is checked. */ - checked: { - type: Boolean, - }, + checked: Boolean, /** * Chrome message handling this option. */ - chromeMessage: { - type: String, - }, + chromeMessage: String, /** * ARIA-label for the button.
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.html b/chrome/browser/resources/chromeos/login/oobe_eula.html index 45a1d63..844078c5 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.html +++ b/chrome/browser/resources/chromeos/login/oobe_eula.html
@@ -4,7 +4,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <iron-iconset-svg name="oobe-eula-32" size="32">
diff --git a/chrome/browser/resources/chromeos/login/oobe_hid_detection.html b/chrome/browser/resources/chromeos/login/oobe_hid_detection.html index 61937527..610ae53 100644 --- a/chrome/browser/resources/chromeos/login/oobe_hid_detection.html +++ b/chrome/browser/resources/chromeos/login/oobe_hid_detection.html
@@ -1,6 +1,5 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <iron-iconset-svg name="oobe-hid-detection" size="24">
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.css b/chrome/browser/resources/chromeos/login/oobe_reset.css index a8bcec2a..3455da8 100644 --- a/chrome/browser/resources/chromeos/login/oobe_reset.css +++ b/chrome/browser/resources/chromeos/login/oobe_reset.css
@@ -36,8 +36,6 @@ } #tpmFirmwareUpdateCheckbox { - --paper-checkbox-size: 16px; - --paper-checkbox-checked-color: var(--google-blue-500); margin-top: 2px; size: 16px; }
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.html b/chrome/browser/resources/chromeos/login/oobe_reset.html index db90477..474f227 100644 --- a/chrome/browser/resources/chromeos/login/oobe_reset.html +++ b/chrome/browser/resources/chromeos/login/oobe_reset.html
@@ -2,9 +2,9 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <iron-iconset-svg name="oobe-reset-32" size="32"> <svg> @@ -68,11 +68,11 @@ i18n-values="alt:resetScreenIllustrationTitle"> <div id="tpmFirmwareUpdate" class="layout horizontal" hidden="[[!tpmFirmwareUpdateAvailable_]]"> - <paper-checkbox id="tpmFirmwareUpdateCheckbox" + <cr-checkbox id="tpmFirmwareUpdateCheckbox" checked="{{tpmFirmwareUpdateChecked_}}" - disabled="{{!tpmFirmwareUpdateEditable_}}" + disabled="[[!tpmFirmwareUpdateEditable_]]" on-change="onTPMFirmwareUpdateChanged_"> - </paper-checkbox> + </cr-checkbox> <div id="tpmFirmwareUpdateContainer"> <span i18n-content="resetTPMFirmwareUpdate"></span> <a href="#" hidden="[[isHelpLinkHidden_(uiState_, isOfficial_)]]"
diff --git a/chrome/browser/resources/chromeos/login/recommend_apps.html b/chrome/browser/resources/chromeos/login/recommend_apps.html index 2d30a9669305..15f73ba 100644 --- a/chrome/browser/resources/chromeos/login/recommend_apps.html +++ b/chrome/browser/resources/chromeos/login/recommend_apps.html
@@ -3,8 +3,8 @@ found in the LICENSE file. --> <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <dom-module id="recommend-apps"> <template> @@ -27,12 +27,12 @@ <div id="recommend-apps-container" class="footer flex layout horizontal"> <template is="dom-repeat" items="{{apps}}"> <div class="column"> - <paper-checkbox> + <cr-checkbox> <div class="checkbox-label"> <img class="app-icon" src="{{item.icon}}"> <span class="app-title">{{item.name}}</span> </div> - </paper-checkbox> + </cr-checkbox> </div> </template> </div>
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.css b/chrome/browser/resources/chromeos/login/sync_consent.css index 4e1fe364..1fffd43 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.css +++ b/chrome/browser/resources/chromeos/login/sync_consent.css
@@ -33,9 +33,10 @@ margin-bottom: 4px; } -paper-checkbox { - --paper-checkbox-label-spacing: 12px; - --paper-checkbox-size: 16px; +cr-checkbox { + --cr-checkbox-label-container: { + -webkit-padding-start: 12px; + }; -webkit-padding-start: 8px; padding-top: 28px; /* 40 to label base line => 40 - 16/2 - 13/3 = 28 */ }
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.html b/chrome/browser/resources/chromeos/login/sync_consent.html index 7bceff0..c7da728bd 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.html +++ b/chrome/browser/resources/chromeos/login/sync_consent.html
@@ -2,6 +2,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> @@ -81,9 +82,9 @@ </div> </div> </div> - <paper-checkbox id="reviewSettingsBox"> + <cr-checkbox id="reviewSettingsBox"> [[i18nDynamic(locale, 'syncConsentReviewSyncOptionsText')]] - </paper-checkbox> + </cr-checkbox> </div> <div class="bottom-buttons layout horizontal end-justified"> <oobe-text-button id="acceptAndContinue"
diff --git a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js index bf7ab0b..a5d8368 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js +++ b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js
@@ -7,14 +7,49 @@ var RoleType = chrome.automation.RoleType; var SelectToSpeakState = chrome.accessibilityPrivate.SelectToSpeakState; -// CrosSelectToSpeakStartSpeechMethod enums. -// These values are persited to logs and should not be renumbered or re-used. -// See tools/metrics/histograms/enums.xml. -const START_SPEECH_METHOD_MOUSE = 0; -const START_SPEECH_METHOD_KEYSTROKE = 1; -// The number of enum values in CrosSelectToSpeapStartSpeechMethod. This should -// be kept in sync with the enum count in tools/metrics/histograms/enums.xml. -const START_SPEECH_METHOD_COUNT = 2; +/** + * CrosSelectToSpeakStartSpeechMethod enums. + * These values are persisted to logs and should not be renumbered or re-used. + * See tools/metrics/histograms/enums.xml. + * @enum {number} + */ +const StartSpeechMethod = { + MOUSE: 0, + KEYSTROKE: 1, +}; + +/** + * The number of enum values in CrosSelectToSpeakStartSpeechMethod. This should + * be kept in sync with the enum count in tools/metrics/histograms/enums.xml. + * @type {number} + */ +const START_SPEECH_METHOD_COUNT = Object.keys(StartSpeechMethod).length; + +/** + * CrosSelectToSpeakStateChangeEvent enums. + * These values are persisted to logs and should not be renumbered or re-used. + * See tools/metrics/histograms/enums.xml. + * @enum {number} + */ +const StateChangeEvent = { + START_SELECTION: 0, + CANCEL_SPEECH: 1, + CANCEL_SELECTION: 2, +}; + +/** + * The number of enum values in CrosSelectToSpeakStateChangeEvent. This should + * be kept in sync with the enum count in tools/metrics/histograms/enums.xml. + * @type {number} + */ +const STATE_CHANGE_EVENT_COUNT = Object.keys(StateChangeEvent).length; + +/** + * The name of the state change request metric. + * @type {string} + */ +const STATE_CHANGE_EVENT_METRIC_NAME = + 'Accessibility.CrosSelectToSpeak.SelectToSpeakStateChangeRequested'; // This must be the same as in ash/system/accessibility/select_to_speak_tray.cc: // ash::kSelectToSpeakTrayClassName. @@ -329,7 +364,7 @@ return; } this.startSpeechQueue_(nodes); - this.recordStartEvent_(START_SPEECH_METHOD_MOUSE); + this.recordStartEvent_(StartSpeechMethod.MOUSE); }.bind(this)); }, @@ -541,7 +576,7 @@ return; } this.initializeScrollingToOffscreenNodes_(focusedNode.root); - this.recordStartEvent_(START_SPEECH_METHOD_KEYSTROKE); + this.recordStartEvent_(StartSpeechMethod.KEYSTROKE); }, /** @@ -643,21 +678,26 @@ // We will need to track the current state and toggle from one state to // the next when this function is called, and then call // accessibilityPrivate.onSelectToSpeakStateChanged with the new state. - // TODO(katie): Add metrics for state transition requests. switch (this.state_) { case SelectToSpeakState.INACTIVE: // Start selection. this.trackingMouse_ = true; this.onStateChanged_(SelectToSpeakState.SELECTING); + this.recordSelectToSpeakStateChangeEvent_( + StateChangeEvent.START_SELECTION); break; case SelectToSpeakState.SPEAKING: // Stop speaking. this.cancelIfSpeaking_(true /* clear the focus ring */); + this.recordSelectToSpeakStateChangeEvent_( + StateChangeEvent.CANCEL_SPEECH); break; case SelectToSpeakState.SELECTING: // Cancelled selection. this.trackingMouse_ = false; this.onStateChanged_(SelectToSpeakState.INACTIVE); + this.recordSelectToSpeakStateChangeEvent_( + StateChangeEvent.CANCEL_SELECTION); } }, @@ -947,6 +987,16 @@ }, /** + * Records a user-requested state change event from a given state. + * @param {number} changeType + */ + recordSelectToSpeakStateChangeEvent_: function(changeType) { + chrome.metricsPrivate.recordEnumerationValue( + 'Accessibility.CrosSelectToSpeak.SelectToSpeakStateChangeRequested', + changeType, STATE_CHANGE_EVENT_COUNT); + }, + + /** * Loads preferences from chrome.storage, sets default values if * necessary, and registers a listener to update prefs when they * change.
diff --git a/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css b/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css index dc9dc11..39346f4a 100644 --- a/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css +++ b/chrome/browser/resources/chromeos/zip_archiver/css/passphrase-dialog.css
@@ -3,8 +3,7 @@ * found in the LICENSE file. */ input, -paper-button, -paper-checkbox { +paper-button { -webkit-app-region: no-drag; } @@ -29,11 +28,6 @@ line-height: inherit; } -#remember { - --paper-checkbox-checked-color: rgb(51, 103, 214); - font-size: 13px; -} - #title { color: black; font-size: 14px; @@ -61,10 +55,6 @@ box-shadow: 0 0 0 2px rgba(51, 103, 214, 0.5); } -paper-checkbox { - --paper-checkbox-ink-size: 38px; -} - paper-input-container { --paper-input-container-focus-color: rgb(51, 103, 214); --paper-input-container-underline-focus: {
diff --git a/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html b/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html index 664e146f..c1a5806e5 100644 --- a/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html +++ b/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
@@ -1,6 +1,5 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html"> <dom-module id="passphrase-dialog">
diff --git a/chrome/browser/resources/md_extensions/kiosk_dialog.html b/chrome/browser/resources/md_extensions/kiosk_dialog.html index 5fe53138..0a7a4c8 100644 --- a/chrome/browser/resources/md_extensions/kiosk_dialog.html +++ b/chrome/browser/resources/md_extensions/kiosk_dialog.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> @@ -9,7 +10,6 @@ <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="item_behavior.html"> @@ -120,11 +120,11 @@ $i18n{add} </paper-button> </div> - <paper-checkbox disabled="[[!canEditBailout_]]" - on-pointerdown="onBailoutTap_" checked="[[bailoutDisabled_]]" + <cr-checkbox disabled="[[!canEditBailout_]]" id="bailout" + on-change="onBailoutChanged_" checked="[[bailoutDisabled_]]" hidden="[[!canEditAutoLaunch_]]"> $i18n{kioskDisableBailout} - </paper-checkbox> + </cr-checkbox> </div> <div slot="button-container"> <paper-button class="action-button" on-click="onDoneTap_">
diff --git a/chrome/browser/resources/md_extensions/kiosk_dialog.js b/chrome/browser/resources/md_extensions/kiosk_dialog.js index 66ada3f..49e5056 100644 --- a/chrome/browser/resources/md_extensions/kiosk_dialog.js +++ b/chrome/browser/resources/md_extensions/kiosk_dialog.js
@@ -123,26 +123,25 @@ * @param {!Event} event * @private */ - onBailoutTap_: function(event) { + onBailoutChanged_: function(event) { event.preventDefault(); - if (this.bailoutDisabled_) { - this.kioskBrowserProxy_.setDisableBailoutShortcut(false); - this.bailoutDisabled_ = false; - this.$['confirm-dialog'].close(); - } else { + if (this.$.bailout.checked) { this.$['confirm-dialog'].showModal(); + } else { + this.kioskBrowserProxy_.setDisableBailoutShortcut(false); + this.$['confirm-dialog'].close(); } }, /** @private */ onBailoutDialogCancelTap_: function() { + this.$.bailout.checked = false; this.$['confirm-dialog'].cancel(); }, /** @private */ onBailoutDialogConfirmTap_: function() { this.kioskBrowserProxy_.setDisableBailoutShortcut(true); - this.bailoutDisabled_ = true; this.$['confirm-dialog'].close(); },
diff --git a/chrome/browser/resources/md_user_manager/create_profile.html b/chrome/browser/resources/md_user_manager/create_profile.html index e63aa7a..c2ad589 100644 --- a/chrome/browser/resources/md_user_manager/create_profile.html +++ b/chrome/browser/resources/md_user_manager/create_profile.html
@@ -2,9 +2,9 @@ <link rel="import" href="/profile_browser_proxy.html"> <link rel="import" href="/shared_styles.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_checkbox_style_css.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> @@ -13,14 +13,13 @@ <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <dom-module id="create-profile"> <template> <style - include="shared-styles iron-positioning md-select paper-checkbox-style"> + include="shared-styles iron-positioning md-select"> :host { align-self: center; } @@ -90,18 +89,10 @@ width: 300px; } - paper-checkbox { - --paper-checkbox-checked-color: var(--google-blue-500); - --paper-checkbox-label-spacing: 16px; - --paper-checkbox-size: 16px; - --paper-checkbox-unchecked-color: var(--paper-grey-600); + cr-checkbox { margin-top: 24px; } - paper-checkbox + paper-checkbox { - margin-top: 16px; - } - #actions { bottom: 16px; display: flex; @@ -133,10 +124,10 @@ <cr-profile-avatar-selector avatars="[[availableIcons_]]" selected-avatar="{{selectedAvatar_}}"> </cr-profile-avatar-selector> - <paper-checkbox id="createShortcutCheckbox" checked="{{createShortcut_}}" + <cr-checkbox id="createShortcutCheckbox" checked="{{createShortcut_}}" hidden="[[!isProfileShortcutsEnabled_]]"> $i18n{createDesktopShortcutLabel} - </paper-checkbox> + </cr-checkbox> <div id="actions"> <paper-spinner-lite active="[[isSpinnerActive_(createInProgress_)]]"> </paper-spinner-lite>
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css index 9cc5423..fa2d57b 100644 --- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css +++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
@@ -117,11 +117,10 @@ text-align: center; } -paper-checkbox { - --paper-checkbox-checked-color: white; - --paper-checkbox-checkmark-color: var(--paper-blue-700); - --paper-checkbox-ink-size: 35px; - --paper-checkbox-unchecked-color: white; +cr-checkbox { + --cr-checkbox-checked-box-color: white; + --cr-checkbox-unchecked-box-color: white; + --cr-checkbox-mark-color: var(--paper-blue-700); } paper-item {
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html index 6b606df..fc0008c 100644 --- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html +++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html"> @@ -28,8 +29,7 @@ <div id="first-run-flow-cloud-pref" hidden$="[[!showFirstRunFlowCloudPref]]"> <div> - <paper-checkbox checked id="first-run-cloud-checkbox"> - </paper-checkbox> + <cr-checkbox checked id="first-run-cloud-checkbox"></cr-checkbox> </div> <div> <span>[[getFirstRunFlowCloudPrefText_()]]</span>
diff --git a/chrome/browser/resources/media_router/elements/route_controls/BUILD.gn b/chrome/browser/resources/media_router/elements/route_controls/BUILD.gn index 8ff292f..0b21078 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/BUILD.gn +++ b/chrome/browser/resources/media_router/elements/route_controls/BUILD.gn
@@ -24,6 +24,5 @@ js_library("route_controls_interface") { deps = [ "../..:media_router_data", - "//third_party/polymer/v1_0/components-chromium/paper-checkbox:paper-checkbox-extracted", ] }
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.css b/chrome/browser/resources/media_router/elements/route_controls/route_controls.css index 322ee273..56ee529f 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.css +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.css
@@ -79,10 +79,6 @@ padding: 0.3em 0; } -paper-checkbox { - --paper-checkbox-checked-color: #1976D2; -} - #hangouts-local-present-controls { cursor: pointer; display: inline-block; @@ -91,10 +87,6 @@ white-space: nowrap; } -#hangouts-local-present-checkbox { - --paper-checkbox-vertical-align: top; -}; - #hangouts-local-present-checkbox-subtitle { display: block; font-size: 0.8em;
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 65a26cf..788339f 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
@@ -1,8 +1,9 @@ -<link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> +<link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/av-icons.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html"> <dom-module id="route-controls"> <link rel="import" type="css" href="../../media_router_common.css"> @@ -70,7 +71,7 @@ </span> <div id="hangouts-local-present-controls" hidden="[[!routeStatus.hangoutsExtraData]]"> - <paper-checkbox + <cr-checkbox checked="[[hangoutsLocalPresent_]]" id="hangouts-local-present-checkbox" on-change="onHangoutsLocalPresentChange_" @@ -81,7 +82,7 @@ <span id="hangouts-local-present-checkbox-subtitle"> [[i18n('hangoutsLocalPresentSubtitle')]] </span> - </paper-checkbox> + </cr-checkbox> </div> </div> <div id="mirroring-fullscreen-video-controls"
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 328aa1d..98f15e0 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
@@ -336,7 +336,7 @@ /** * Called when the "smooth motion" box for Hangouts is changed by the user. - * @param {!{target: !PaperCheckboxElement}} e + * @param {!{target: !HTMLElement}} e * @private */ onHangoutsLocalPresentChange_: function(e) {
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html index a2c53b9..3d55cbd8 100644 --- a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html +++ b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
@@ -61,11 +61,17 @@ #pagelength { font-size: 0.81rem; } + + iron-input input { + @apply --paper-input-container-shared-input-style; + } </style> <paper-input-container id="pageselector" no-label-float> - <input id="input" is="iron-input" value="{{pageNo}}" slot="input" - prevent-invalid-input allowed-pattern="\d" on-mouseup="select" - on-change="pageNoCommitted" aria-label$="{{strings.labelPageNumber}}"> + <iron-input slot="input" bind-value="[[pageNo]]" allowed-pattern="\d"> + <input id="input" prevent-invalid-input value="{{value::input}}" + on-mouseup="select" on-change="pageNoCommitted" + aria-label$="{{strings.labelPageNumber}}"> + </iron-input> </paper-input-container> <span id="slash"> / </span> <span id="pagelength-spacer">
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.js b/chrome/browser/resources/print_preview/new/destination_dialog.js index 64e24b2..8500c9f 100644 --- a/chrome/browser/resources/print_preview/new/destination_dialog.js +++ b/chrome/browser/resources/print_preview/new/destination_dialog.js
@@ -237,9 +237,11 @@ .then( response => { this.destinationInConfiguring_ = null; - destination.capabilities = response.capabilities; - listItem.onConfigureComplete(true); - this.selectDestination_(destination); + listItem.onConfigureComplete(response.success); + if (response.success) { + destination.capabilities = response.capabilities; + this.selectDestination_(destination); + } }, () => { this.destinationInConfiguring_ = null;
diff --git a/chrome/browser/resources/print_preview/new/pages_settings.html b/chrome/browser/resources/print_preview/new/pages_settings.html index 3b27059..4c4bc5a 100644 --- a/chrome/browser/resources/print_preview/new/pages_settings.html +++ b/chrome/browser/resources/print_preview/new/pages_settings.html
@@ -44,7 +44,7 @@ <input id="pageSettingsCustomInput" class="user-value" type="text" checked="{{customSelected_::change}}" data-timeout-delay="500" disabled$="[[getDisabled_(disabled, settings.pages.valid)]]" - pattern="([0-9]*(-)?[0-9]*(,)( )?)*([0-9]*(-)?[0-9]*(,)?( )?)?" + pattern="[[inputPattern_]]" on-focus="onCustomInputFocus_" on-blur="onCustomInputBlur_" placeholder="$i18n{examplePageRangeText}" aria-label="$i18n{examplePageRangeText}">
diff --git a/chrome/browser/resources/print_preview/new/pages_settings.js b/chrome/browser/resources/print_preview/new/pages_settings.js index 616a365..741fa2d 100644 --- a/chrome/browser/resources/print_preview/new/pages_settings.js +++ b/chrome/browser/resources/print_preview/new/pages_settings.js
@@ -68,6 +68,14 @@ type: Array, computed: 'computeRangesToPrint_(pagesToPrint_, allPagesArray_)', }, + + /** @private {string} */ + inputPattern_: { + type: String, + notify: true, + value: + '([0-9]*(-)?[0-9]*(,|\u3001)( )?)*([0-9]*(-)?[0-9]*(,|\u3001)?( )?)?', + }, }, observers: [ @@ -129,16 +137,18 @@ const pages = []; const added = {}; - const ranges = this.inputString_.split(','); + const ranges = this.inputString_.split(/,|\u3001/); const maxPage = this.allPagesArray_.length; for (let range of ranges) { range = range.trim(); - if (range == '') - continue; + if (range == '') { + this.errorState_ = PagesInputErrorState.INVALID_SYNTAX; + return this.pagesToPrint_; + } const limits = range.split('-'); let min = parseInt(limits[0], 10); if (min < 1) { - this.errorState_ = PagesInputErrorState.OUT_OF_BOUNDS; + this.errorState_ = PagesInputErrorState.INVALID_SYNTAX; return this.pagesToPrint_; } if (limits.length == 1) {
diff --git a/chrome/browser/resources/settings/controls/important_site_checkbox.html b/chrome/browser/resources/settings/controls/important_site_checkbox.html index 20e0d91..982e4d6 100644 --- a/chrome/browser/resources/settings/controls/important_site_checkbox.html +++ b/chrome/browser/resources/settings/controls/important_site_checkbox.html
@@ -1,7 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="settings_boolean_control_behavior.html"> <link rel="import" href="../settings_shared_css.html"> @@ -15,24 +15,16 @@ width: 100%; } - paper-checkbox { + cr-checkbox { width: 100%; } - paper-checkbox:not([checked]) .secondary { - @apply --settings-secondary-unchecked; - } - .middot { padding: 0 4px; } - - .label { - @apply --settings-checkbox-label; - } </style> <div id="outerRow"> - <paper-checkbox id="checkbox" checked="{{site.isChecked}}" + <cr-checkbox id="checkbox" checked="{{site.isChecked}}" disabled="[[disabled]]"> <div class="label">[[site.registerableDomain]]</div> <div class="secondary label"> @@ -45,7 +37,7 @@ $i18n{notificationWarning} </span> </div> - </paper-checkbox> + </cr-checkbox> </div> </template> <script src="important_site_checkbox.js"></script>
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.html b/chrome/browser/resources/settings/controls/settings_checkbox.html index 5ea38bc..ec8f7cfe 100644 --- a/chrome/browser/resources/settings/controls/settings_checkbox.html +++ b/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -1,7 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="settings_boolean_control_behavior.html"> <link rel="import" href="../settings_shared_css.html"> @@ -19,30 +19,19 @@ min-height: var(--settings-row-min-height); } - paper-checkbox { - /* Handle overflow of subLabel when it is larger than one line. */ - align-items: center; - display: flex; + cr-checkbox { /* Additional margin in case subLabel needs more than one line. */ margin-bottom: 4px; margin-top: var(--settings-checkbox-margin-top, 4px); width: 100%; } - paper-checkbox:not([checked]) .secondary { - @apply --settings-secondary-unchecked; - } - cr-policy-pref-indicator { -webkit-margin-start: var(--settings-controlled-by-spacing); } - - .label { - @apply --settings-checkbox-label; - } </style> <div id="outerRow" noSubLabel$="[[!hasSubLabel_(subLabel, subLabelHtml)]]"> - <paper-checkbox id="checkbox" checked="{{checked}}" + <cr-checkbox id="checkbox" checked="{{checked}}" on-change="notifyChangedByUserInteraction" disabled="[[controlDisabled(disabled, pref.*)]]"> <div class="label">[[label]] <slot></slot></div> @@ -50,7 +39,7 @@ <div inner-h-t-m-l="[[subLabelHtml]]"></div> [[subLabel]] </div> - </paper-checkbox> + </cr-checkbox> <template is="dom-if" if="[[pref.controlledBy]]"> <cr-policy-pref-indicator pref="[[pref]]" icon-aria-label="[[label]]"> </cr-policy-pref-indicator>
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html index acd9ad6a..ee1fa3a 100644 --- a/chrome/browser/resources/settings/device_page/display.html +++ b/chrome/browser/resources/settings/device_page/display.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/assert.html"> @@ -82,11 +83,11 @@ <template is="dom-if" if="[[showMirror_(unifiedDesktopMode_, displays)]]" restamp> <div class="secondary self-start"> - <paper-checkbox checked="[[isMirrored_(displays)]]" + <cr-checkbox checked="[[isMirrored_(displays)]]" on-click="onMirroredTap_" aria-label="[[getDisplayMirrorText_(displays)]]"> <div class="text-area">[[getDisplayMirrorText_(displays)]]</div> - </paper-checkbox> + </cr-checkbox> </div> </template>
diff --git a/chrome/browser/resources/settings/languages_page/BUILD.gn b/chrome/browser/resources/settings/languages_page/BUILD.gn index b17b775..6784e76 100644 --- a/chrome/browser/resources/settings/languages_page/BUILD.gn +++ b/chrome/browser/resources/settings/languages_page/BUILD.gn
@@ -57,7 +57,6 @@ "..:lifetime_browser_proxy", "..:route", "../settings_page:settings_animated_pages", - "//third_party/polymer/v1_0/components-chromium/paper-checkbox:paper-checkbox-extracted", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu", "//ui/webui/resources/cr_elements/cr_expand_button:cr_expand_button", "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render", @@ -80,7 +79,6 @@ ":languages", ":languages_types", "../prefs:prefs", - "//third_party/polymer/v1_0/components-chromium/paper-checkbox:paper-checkbox-extracted", ] externs_list = [ "$externs_path/language_settings_private.js" ] } @@ -89,7 +87,6 @@ deps = [ ":languages", ":languages_types", - "//third_party/polymer/v1_0/components-chromium/paper-checkbox:paper-checkbox-extracted", "//ui/webui/resources/cr_elements:cr_scrollable_behavior", ] }
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html index 1e6b863..b6e5f6c 100644 --- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html +++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
@@ -1,9 +1,9 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="languages.html"> <link rel="import" href="../settings_page/settings_subpage_search.html"> @@ -33,10 +33,10 @@ -webkit-padding-start: 20px; } - paper-checkbox { - --paper-checkbox-label: { + cr-checkbox { + --cr-checkbox-label-container: { white-space: nowrap; - } + }; } </style> <cr-dialog id="dialog" close-text="$i18n{close}"> @@ -49,12 +49,12 @@ items="[[getLanguages_( languages.supported, languages.enabled.*, filterValue_)]]"> <template> - <paper-checkbox class="list-item no-outline" + <cr-checkbox class="list-item no-outline" checked="[[willAdd_(item.code)]]" tabindex$="[[tabIndex]]" title$="[[item.nativeDisplayName]]" on-change="onLanguageCheckboxChange_"> [[getDisplayText_(item)]] - </paper-checkbox> + </cr-checkbox> </template> </iron-list> </div>
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.js b/chrome/browser/resources/settings/languages_page/add_languages_dialog.js index 30f4cfa2..81e3bf5 100644 --- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.js +++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
@@ -106,7 +106,7 @@ /** * Handler for checking or unchecking a language item. * @param {!{model: !{item: !chrome.languageSettingsPrivate.Language}, - * target: !PaperCheckboxElement}} e + * target: !Element}} e * @private */ onLanguageCheckboxChange_: function(e) {
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index 1b67fd0..b709740 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> @@ -9,7 +10,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> @@ -64,7 +64,8 @@ margin: 6px 0 0 0; } - paper-checkbox.dropdown-item { + cr-checkbox.dropdown-item { + --cr-action-menu-disabled-item-opacity: 0.38; -webkit-margin-start: 0; } @@ -318,7 +319,7 @@ <cr-action-menu class$="[[getMenuClass_(prefs.translate.enabled.value)]]"> <if expr="chromeos or is_win"> - <paper-checkbox id="uiLanguageItem" slot="item" + <cr-checkbox id="uiLanguageItem" slot="item" class="dropdown-item" checked="[[isProspectiveUILanguage_( detailLanguage_.language.code, @@ -326,14 +327,14 @@ on-change="onUILanguageChange_" disabled="[[disableUILanguageCheckbox_( detailLanguage_, languages.prospectiveUILanguage)]]"> - <span>$i18n{displayInThisLanguage}</span> - <cr-policy-indicator indicator-type="[[ - getPolicyIndicatorStatus_( - detailLanguage_.language)]]"> - </cr-policy-indicator> - </paper-checkbox> + <span>$i18n{displayInThisLanguage}</span> + <cr-policy-indicator indicator-type="[[ + getPolicyIndicatorStatus_( + detailLanguage_.language)]]"> + </cr-policy-indicator> + </cr-checkbox> </if> - <paper-checkbox id="offerTranslations" slot="item" + <cr-checkbox id="offerTranslations" slot="item" class="dropdown-item" checked="[[detailLanguage_.translateEnabled]]" on-change="onTranslateCheckboxChange_" @@ -341,7 +342,7 @@ disabled="[[disableTranslateCheckbox_( detailLanguage_.language, languages.translateTarget)]]"> $i18n{offerToTranslateInThisLanguage} - </paper-checkbox> + </cr-checkbox> <hr slot="item"> <button slot="item" class="dropdown-item" role="menuitem" on-click="onMoveToTopTap_"
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.js b/chrome/browser/resources/settings/languages_page/languages_page.js index 7dbbaad..3a90fdc20 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.js +++ b/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -323,7 +323,7 @@ /** * Handler for changes to the UI language checkbox. - * @param {!{target: !PaperCheckboxElement}} e + * @param {!{target: !Element}} e * @private */ onUILanguageChange_: function(e) { @@ -353,7 +353,7 @@ /** * Handler for changes to the translate checkbox. - * @param {!{target: !PaperCheckboxElement}} e + * @param {!{target: !Element}} e * @private */ onTranslateCheckboxChange_: function(e) {
diff --git a/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html b/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html index e877d37..520e612b 100644 --- a/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html +++ b/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html
@@ -1,8 +1,8 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="languages.html"> @@ -16,12 +16,12 @@ <template is="dom-repeat" items="[[item.inputMethods]]"> <div class="list-item"> <div class="language-name"> - <paper-checkbox checked="[[item.enabled]]" + <cr-checkbox checked="[[item.enabled]]" on-change="onCheckboxChange_" disabled="[[!enableInputMethodCheckbox_( item, languages.inputMethods.enabled.*)]]"> <span>[[item.displayName]]</span> - </paper-checkbox> + </cr-checkbox> </div> </div> </template>
diff --git a/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js b/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js index bef3106..2c3ede7 100644 --- a/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js +++ b/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js
@@ -57,7 +57,7 @@ /** * Handler for an input method checkbox. * @param {!{model: !{item: chrome.languageSettingsPrivate.InputMethod}, - * target: !PaperCheckboxElement}} e + * target: !Element}} e * @private */ onCheckboxChange_: function(e) {
diff --git a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js index 34577fe..437d94d4 100644 --- a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js +++ b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
@@ -118,7 +118,7 @@ // Select the whole password if user entered an incorrect password. // Return focus to the password input if it lost focus while being // checked (user pressed confirm button). - this.$.passwordInput.inputElement.select(); + this.$.passwordInput.inputElement.inputElement.select(); if (!this.$.passwordInput.focused) this.$.passwordInput.focus(); return;
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html index d826f5e..7b84491 100644 --- a/chrome/browser/resources/settings/people_page/people_page.html +++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> @@ -13,7 +14,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="sync_page.html"> @@ -407,10 +407,10 @@ <template is="dom-if" if="[[!syncStatus.domain]]"> <div id="wideFooter" slot="footer"> <div class="settings-box first"> - <paper-checkbox id="deleteProfile" class="start" + <cr-checkbox id="deleteProfile" class="start" checked="{{deleteProfile_}}"> $i18n{syncDisconnectDeleteProfile} - </paper-checkbox> + </cr-checkbox> <cr-expand-button expanded="{{deleteProfileWarningVisible_}}" alt="$i18n{deleteProfileWarningExpandA11yLabel}"> </cr-expand-button>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js index 7fe57e01..d17d5cd 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.js +++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -265,7 +265,7 @@ listenOnce(document, 'show-container', () => { const input = /** @type {!PaperInputElement} */ ( this.$$('#existingPassphraseInput')); - input.inputElement.focus(); + input.focus(); }); } },
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html index 70ae6da0..0b7ecc7 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
@@ -59,11 +59,16 @@ #dropdownIcon { background-size: 24px; } + + iron-input input { + @apply --paper-input-container-shared-input-style; + } </style> <paper-input-container no-label-float on-click="onTap_"> - <input is="iron-input" type="search" bind-value="{{selectedItem}}" - on-search="onInputValueChanged_" on-change="onChange_" incremental - slot="input"> + <iron-input id="search" slot="input" bind-value="{{selectedItem}}"> + <input type="search" on-search="onInputValueChanged_" + value="{{value::input}}" on-change="onChange_" incremental> + </iron-input> <paper-icon-button-light id="searchIcon" class="icon-search" hidden slot="suffix"> <button></button>
diff --git a/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html b/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html index 026ed96e..451ef9faf 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html +++ b/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html
@@ -97,11 +97,9 @@ outline: none; } - paper-input-container { - --paper-input-container-input: { - font: inherit; - }; - --paper-input-container-input-color: inherit; + #search input[type='search'] { + @apply --paper-input-container-shared-input-style; + font: inherit; } </style> </template>
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers.js b/chrome/browser/resources/settings/printing_page/cups_printers.js index b0ee57c8..593a477b 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers.js +++ b/chrome/browser/resources/settings/printing_page/cups_printers.js
@@ -59,6 +59,8 @@ /** @override */ attached: function() { this.addWebUIListener('on-add-cups-printer', this.onAddPrinter_.bind(this)); + this.addWebUIListener( + 'on-printers-changed', this.printersChanged_.bind(this)); this.networksChangedListener_ = this.refreshNetworks_.bind(this); chrome.networkingPrivate.onNetworksChanged.addListener( this.networksChangedListener_);
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js index 1e2080b..1ba1e5b6 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
@@ -78,7 +78,7 @@ /** @override */ attached: function() { - this.updateActionButtonState_(); + this.async(this.updateActionButtonState_.bind(this)); this.browserProxy_.searchEngineEditStarted( this.model ? this.model.modelIndex : this.DEFAULT_MODEL_INDEX); this.$.dialog.showModal();
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index c0d1c124..3117c29 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -1,5 +1,4 @@ <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_checkbox_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/search_highlight_style_css.html"> @@ -12,7 +11,7 @@ <!-- Common styles for Material Design settings. --> <dom-module id="settings-shared"> <template> - <style include="settings-icons paper-button-style paper-checkbox-style paper-input-style paper-toggle-style cr-shared-style search-highlight-style"> + <style include="settings-icons paper-button-style paper-input-style paper-toggle-style cr-shared-style search-highlight-style"> /* Prevent action-links from being selected to avoid accidental * selection when trying to click it. */ a[is=action-link] {
diff --git a/chrome/browser/resources/settings/site_settings/add_site_dialog.html b/chrome/browser/resources/settings/site_settings/add_site_dialog.html index 9d78be71..87c2439 100644 --- a/chrome/browser/resources/settings/site_settings/add_site_dialog.html +++ b/chrome/browser/resources/settings/site_settings/add_site_dialog.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> @@ -29,10 +30,10 @@ value="{{site_}}" on-input="validate_" error-message="$i18n{notValidWebAddress}" spellcheck="false" autofocus></paper-input> - <paper-checkbox id="incognito" + <cr-checkbox id="incognito" invisible$="[[!showIncognitoSessionOnly_]]"> $i18n{incognitoSiteOnly} - </paper-checkbox> + </cr-checkbox> </div> <div slot="button-container"> <paper-button class="cancel-button" on-click="onCancelTap_">
diff --git a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js index 654d24642..be6faee4 100644 --- a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js +++ b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js
@@ -13,7 +13,10 @@ /** * @type {!SiteException} */ - model: Object, + model: { + type: Object, + observer: 'modelChanged_', + }, /** @private */ origin_: String, @@ -72,4 +75,10 @@ this.invalid_ = !isValid; }); }, + + /** @private */ + modelChanged_: function() { + if (!this.model) + this.$.dialog.cancel(); + }, });
diff --git a/chrome/browser/resources/settings/site_settings/site_list.js b/chrome/browser/resources/settings/site_settings/site_list.js index 650f86c..29c4646 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.js +++ b/chrome/browser/resources/settings/site_settings/site_list.js
@@ -370,8 +370,10 @@ onEditExceptionDialogClosed_: function() { this.showEditExceptionDialog_ = false; this.actionMenuSite_ = null; - this.activeDialogAnchor_.focus(); - this.activeDialogAnchor_ = null; + if (this.activeDialogAnchor_) { + this.activeDialogAnchor_.focus(); + this.activeDialogAnchor_ = null; + } }, /** @private */
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index adffd16..c7a5198e 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -240,6 +240,11 @@ return network_context_->GetURLLoaderFactory(); } +void SafeBrowsingService::FlushNetworkInterfaceForTesting() { + if (network_context_) + network_context_->FlushForTesting(); +} + scoped_refptr<network::SharedURLLoaderFactory> SafeBrowsingService::GetURLLoaderFactoryOnIOThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index a2c1b8a..481e357 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -156,6 +156,9 @@ network::mojom::NetworkContext* GetNetworkContext(); virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory(); + // Flushes above two interfaces to avoid races in tests. + void FlushNetworkInterfaceForTesting(); + // Called to get a SharedURLLoaderFactory that can be used on the IO thread. scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactoryOnIOThread();
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index f1294054..2ba92d4 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -1826,8 +1826,8 @@ public: void SetUp() override { JsRequestTestParam param = GetParam(); - if (param.request_type == JsRequestType::kOffMainThreadWebSocket) { - scoped_feature_list_.InitAndEnableFeature( + if (param.request_type == JsRequestType::kWebSocket) { + scoped_feature_list_.InitAndDisableFeature( features::kOffMainThreadWebSocket); } SafeBrowsingServiceTest::SetUp();
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc index 8f39d80..21f860e 100644 --- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc +++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc
@@ -97,7 +97,7 @@ " }" "}"; -class SettingsResetPromptModelBrowserTest : public ExtensionBrowserTest { +class SettingsResetPromptModelBrowserTest : public extensions::ExtensionBrowserTest { public: virtual void OnResetDone() { ++reset_callbacks_; } @@ -108,7 +108,7 @@ : startup_pref_(SessionStartupPref::URLS) {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); // Set up an active homepage with visible homepage button. PrefService* prefs = profile()->GetPrefs();
diff --git a/chrome/browser/search_engines/template_url_android.cc b/chrome/browser/search_engines/template_url_android.cc new file mode 100644 index 0000000..9acf79d9c --- /dev/null +++ b/chrome/browser/search_engines/template_url_android.cc
@@ -0,0 +1,64 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/search_engines/template_url_android.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "components/search_engines/template_url.h" + +#include "jni/TemplateUrl_jni.h" + +using base::android::JavaParamRef; +using base::android::ScopedJavaLocalRef; + +TemplateURL* ToTemplateURL(jlong j_template_url) { + return reinterpret_cast<TemplateURL*>(j_template_url); +} + +ScopedJavaLocalRef<jstring> JNI_TemplateUrl_GetShortName( + JNIEnv* env, + const JavaParamRef<jclass>& jcaller, + jlong template_url_ptr) { + TemplateURL* template_url = ToTemplateURL(template_url_ptr); + return base::android::ConvertUTF16ToJavaString(env, + template_url->short_name()); +} + +ScopedJavaLocalRef<jstring> JNI_TemplateUrl_GetKeyword( + JNIEnv* env, + const JavaParamRef<jclass>& jcaller, + jlong template_url_ptr) { + TemplateURL* template_url = ToTemplateURL(template_url_ptr); + return base::android::ConvertUTF16ToJavaString(env, template_url->keyword()); +} + +jboolean JNI_TemplateUrl_IsPrepopulatedOrCreatedByPolicy( + JNIEnv* env, + const JavaParamRef<jclass>& jcaller, + jlong template_url_ptr) { + TemplateURL* template_url = ToTemplateURL(template_url_ptr); + return template_url->prepopulate_id() > 0 || + template_url->created_by_policy(); +} + +jlong JNI_TemplateUrl_GetLastVisitedTime(JNIEnv* env, + const JavaParamRef<jclass>& jcaller, + jlong template_url_ptr) { + TemplateURL* template_url = ToTemplateURL(template_url_ptr); + return template_url->last_visited().ToJavaTime(); +} + +jint JNI_TemplateUrl_GetPrepopulatedId(JNIEnv* env, + const JavaParamRef<jclass>& jcaller, + jlong template_url_ptr) { + TemplateURL* template_url = ToTemplateURL(template_url_ptr); + return template_url->prepopulate_id(); +} + +ScopedJavaLocalRef<jobject> CreateTemplateUrlAndroid( + JNIEnv* env, + const TemplateURL* template_url) { + return Java_TemplateUrl_create(env, reinterpret_cast<intptr_t>(template_url)); +}
diff --git a/chrome/browser/search_engines/template_url_android.h b/chrome/browser/search_engines/template_url_android.h new file mode 100644 index 0000000..61bf2e8 --- /dev/null +++ b/chrome/browser/search_engines/template_url_android.h
@@ -0,0 +1,20 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_ANDROID_H_ +#define CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_ANDROID_H_ + +#include "base/android/jni_weak_ref.h" +#include "base/android/scoped_java_ref.h" +#include "components/search_engines/template_url.h" + +// Android wrapper of the TemplateUrl which provides access for the Java +// layer. +class TemplateUrlAndroid; + +base::android::ScopedJavaLocalRef<jobject> CreateTemplateUrlAndroid( + JNIEnv* env, + const TemplateURL* template_url); + +#endif // CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_ANDROID_H_
diff --git a/chrome/browser/search_engines/template_url_service_android.cc b/chrome/browser/search_engines/template_url_service_android.cc index 927aa93..3800024 100644 --- a/chrome/browser/search_engines/template_url_service_android.cc +++ b/chrome/browser/search_engines/template_url_service_android.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/bind.h" #include "base/command_line.h" @@ -14,6 +15,7 @@ #include "base/metrics/field_trial_params.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/search_engines/template_url_android.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "components/google/core/browser/google_util.h" #include "components/search_engines/search_terms_data.h" @@ -47,8 +49,6 @@ base::Bind(&TemplateUrlServiceAndroid::OnTemplateURLServiceLoaded, base::Unretained(this))); template_url_service_->AddObserver(this); - if (template_url_service_->loaded() && template_urls_.empty()) - LoadTemplateURLs(); } TemplateUrlServiceAndroid::~TemplateUrlServiceAndroid() { @@ -71,30 +71,12 @@ template_url_service_->SetUserSelectedDefaultSearchProvider(template_url); } -jint TemplateUrlServiceAndroid::GetDefaultSearchProviderIndex( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) const { - const TemplateURL* default_search_provider = - template_url_service_->GetDefaultSearchProvider(); - auto it = std::find(template_urls_.begin(), template_urls_.end(), - default_search_provider); - size_t default_search_provider_index_ = - (it == template_urls_.end()) ? -1 : (it - template_urls_.begin()); - return default_search_provider_index_; -} - jboolean TemplateUrlServiceAndroid::IsLoaded( JNIEnv* env, const JavaParamRef<jobject>& obj) const { return template_url_service_->loaded(); } -jint TemplateUrlServiceAndroid::GetTemplateUrlCount( - JNIEnv* env, - const JavaParamRef<jobject>& obj) const { - return template_urls_.size(); -} - jboolean TemplateUrlServiceAndroid::IsDefaultSearchManaged( JNIEnv* env, const JavaParamRef<jobject>& obj) { @@ -159,81 +141,21 @@ url); } -base::android::ScopedJavaLocalRef<jobject> -TemplateUrlServiceAndroid::GetTemplateUrlAt(JNIEnv* env, - const JavaParamRef<jobject>& obj, - jint index) const { - TemplateURL* template_url = template_urls_[index]; - return Java_TemplateUrl_create( - env, index, - base::android::ConvertUTF16ToJavaString(env, template_url->short_name()), - template_url_service_->IsPrepopulatedOrCreatedByPolicy(template_url), - base::android::ConvertUTF16ToJavaString(env, template_url->keyword())); -} - void TemplateUrlServiceAndroid::OnTemplateURLServiceLoaded() { template_url_subscription_.reset(); JNIEnv* env = base::android::AttachCurrentThread(); auto java_obj = weak_java_obj_.get(env); if (java_obj.is_null()) return; - LoadTemplateURLs(); Java_TemplateUrlService_templateUrlServiceLoaded(env, java_obj); } -void TemplateUrlServiceAndroid::LoadTemplateURLs() { - template_urls_ = template_url_service_->GetTemplateURLs(); - - // Move prepopulated and policy-created engines to the front of list, - // and sort by prepopulated_id. - TemplateURLService* template_url_service = template_url_service_; - auto it = std::partition( - template_urls_.begin(), template_urls_.end(), - [template_url_service](const TemplateURL* t_url) { - return template_url_service->IsPrepopulatedOrCreatedByPolicy(t_url); - }); - std::sort(template_urls_.begin(), it, - [](const TemplateURL* lhs, const TemplateURL* rhs) { - return lhs->prepopulate_id() < rhs->prepopulate_id(); - }); - - // Place any user-selected default engine next. - const TemplateURL* dsp = template_url_service_->GetDefaultSearchProvider(); - it = std::partition(it, template_urls_.end(), - [dsp](const TemplateURL* t_url) { return t_url == dsp; }); - - // Sort the remaining engines to place the three most recently-visited first. - constexpr size_t kMaxRecentUrls = 3; - const size_t recent_url_num = template_urls_.end() - it; - int urls_to_show = filtering_enabled_ - ? std::min(recent_url_num, kMaxRecentUrls) - : recent_url_num; - auto end = it + urls_to_show; - - std::partial_sort(it, end, template_urls_.end(), - [](const TemplateURL* lhs, const TemplateURL* rhs) { - return lhs->last_visited() > rhs->last_visited(); - }); - - if (filtering_enabled_) { - // Limit to those three engines which must also have been visited in the - // last two days. - constexpr base::TimeDelta kMaxVisitAge = base::TimeDelta::FromDays(2); - const base::Time cutoff = base::Time::Now() - kMaxVisitAge; - const auto too_old = [cutoff](const TemplateURL* t_url) { - return t_url->last_visited() < cutoff; - }; - template_urls_.erase(std::find_if(it, end, too_old), template_urls_.end()); - } -} - void TemplateUrlServiceAndroid::OnTemplateURLServiceChanged() { JNIEnv* env = base::android::AttachCurrentThread(); auto java_obj = weak_java_obj_.get(env); if (java_obj.is_null()) return; - LoadTemplateURLs(); Java_TemplateUrlService_onTemplateURLServiceChanged(env, java_obj); } @@ -356,17 +278,6 @@ return base::android::ConvertUTF8ToJavaString(env, url); } -void TemplateUrlServiceAndroid::SetFilteringEnabled( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jboolean filtering_enabled) { - if (filtering_enabled == filtering_enabled_) - return; - - filtering_enabled_ = filtering_enabled; - OnTemplateURLServiceChanged(); -} - base::android::ScopedJavaLocalRef<jstring> TemplateUrlServiceAndroid::AddSearchEngineForTesting( JNIEnv* env, @@ -422,6 +333,32 @@ env, (has_search_terms ? search_terms : base::string16())); } +void TemplateUrlServiceAndroid::GetTemplateUrls( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& template_url_list_obj) { + std::vector<TemplateURL*> template_urls = + template_url_service_->GetTemplateURLs(); + for (TemplateURL* template_url : template_urls) { + base::android::ScopedJavaLocalRef<jobject> j_template_url = + CreateTemplateUrlAndroid(env, template_url); + Java_TemplateUrlService_addTemplateUrlToList(env, template_url_list_obj, + j_template_url); + }; +} + +base::android::ScopedJavaLocalRef<jobject> +TemplateUrlServiceAndroid::GetDefaultSearchEngine( + JNIEnv* env, + const JavaParamRef<jobject>& obj) { + const TemplateURL* default_search_provider = + template_url_service_->GetDefaultSearchProvider(); + if (default_search_provider == nullptr) { + return base::android::ScopedJavaLocalRef<jobject>(env, nullptr); + } + return CreateTemplateUrlAndroid(env, default_search_provider); +} + static jlong JNI_TemplateUrlService_Init(JNIEnv* env, const JavaParamRef<jobject>& obj) { TemplateUrlServiceAndroid* template_url_service_android =
diff --git a/chrome/browser/search_engines/template_url_service_android.h b/chrome/browser/search_engines/template_url_service_android.h index 7cd432fa..e539abc 100644 --- a/chrome/browser/search_engines/template_url_service_android.h +++ b/chrome/browser/search_engines/template_url_service_android.h
@@ -28,21 +28,9 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& jkeyword); - - jint GetDefaultSearchProviderIndex( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) const; - - jint GetTemplateUrlCount( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) const; jboolean IsLoaded( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) const; - base::android::ScopedJavaLocalRef<jobject> GetTemplateUrlAt( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jint index) const; jboolean IsDefaultSearchManaged( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); @@ -83,9 +71,6 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& jkeyword); - void SetFilteringEnabled(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - jboolean filtering_enabled); base::android::ScopedJavaLocalRef<jstring> ExtractSearchTermsFromUrl( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, @@ -106,6 +91,18 @@ const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& jkeyword); + // Get all the available search engines and add them to the + // |template_url_list_obj| list. + void GetTemplateUrls( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& template_url_list_obj); + + // Get current default search engine. + base::android::ScopedJavaLocalRef<jobject> GetDefaultSearchEngine( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + private: ~TemplateUrlServiceAndroid() override; @@ -114,12 +111,6 @@ // TemplateUrlServiceObserver: void OnTemplateURLServiceChanged() override; - // Updates |template_urls_| to contain all TemplateURLs. It sorts this list - // with prepopulated engines first, then any default non-prepopulated engine, - // then other non-prepopulated engines based on last_visited in descending - // order. - void LoadTemplateURLs(); - JavaObjectWeakGlobalRef weak_java_obj_; // Pointer to the TemplateUrlService for the main profile. @@ -127,11 +118,6 @@ std::unique_ptr<TemplateURLService::Subscription> template_url_subscription_; - // Caches the up-to-date TemplateURL list so that calls from Android could - // directly get data from it. - std::vector<TemplateURL*> template_urls_; - bool filtering_enabled_ = true; - DISALLOW_COPY_AND_ASSIGN(TemplateUrlServiceAndroid); };
diff --git a/chrome/browser/site_details_browsertest.cc b/chrome/browser/site_details_browsertest.cc index ca793026..4ec99e0 100644 --- a/chrome/browser/site_details_browsertest.cc +++ b/chrome/browser/site_details_browsertest.cc
@@ -166,13 +166,13 @@ } // namespace -class SiteDetailsBrowserTest : public ExtensionBrowserTest { +class SiteDetailsBrowserTest : public extensions::ExtensionBrowserTest { public: SiteDetailsBrowserTest() {} ~SiteDetailsBrowserTest() override {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); // Add content/test/data so we can use cross_site_iframe_factory.html
diff --git a/chrome/browser/ssl/certificate_transparency_browsertest.cc b/chrome/browser/ssl/certificate_transparency_browsertest.cc deleted file mode 100644 index 190b3ea..0000000 --- a/chrome/browser/ssl/certificate_transparency_browsertest.cc +++ /dev/null
@@ -1,284 +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 "base/base64.h" -#include "base/run_loop.h" -#include "base/test/histogram_tester.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/net/sth_distributor_provider.h" -#include "chrome/browser/net/system_network_context_manager.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ssl/cert_verifier_browser_test.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/certificate_transparency/features.h" -#include "components/certificate_transparency/single_tree_tracker.h" -#include "components/certificate_transparency/sth_distributor.h" -#include "components/certificate_transparency/tree_state_tracker.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/test/browser_test_utils.h" -#include "net/cert/ct_policy_status.h" -#include "net/cert/ct_serialization.h" -#include "net/cert/mock_cert_verifier.h" -#include "net/cert/signed_tree_head.h" -#include "net/dns/mock_host_resolver.h" -#include "net/test/cert_test_util.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/gtest_util.h" -#include "net/test/test_data_directory.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" - -namespace { - -using net::ct::DigitallySigned; -using net::ct::SignedTreeHead; -using net::test::IsOk; - -constexpr base::TimeDelta kZeroTTL; - -// Decodes a base64-encoded "DigitallySigned" TLS struct into |*sig_out|. -// See https://tools.ietf.org/html/rfc5246#section-4.7. -// |sig_out| must not be null. -bool DecodeDigitallySigned(base::StringPiece base64_data, - DigitallySigned* sig_out) { - std::string data; - if (!base::Base64Decode(base64_data, &data)) - return false; - - base::StringPiece data_ptr = data; - if (!net::ct::DecodeDigitallySigned(&data_ptr, sig_out)) - return false; - - return true; -} - -// Populates |*sth_out| with the given information. -// |sth_out| must not be null. -bool BuildSignedTreeHead(base::Time timestamp, - uint64_t tree_size, - base::StringPiece root_hash_base64, - base::StringPiece signature_base64, - base::StringPiece log_id_base64, - net::ct::SignedTreeHead* sth_out) { - sth_out->version = SignedTreeHead::V1; - sth_out->timestamp = timestamp; - sth_out->tree_size = tree_size; - - std::string root_hash; - if (!base::Base64Decode(root_hash_base64, &root_hash)) { - return false; - } - root_hash.copy(sth_out->sha256_root_hash, net::ct::kSthRootHashLength); - - return DecodeDigitallySigned(signature_base64, &sth_out->signature) && - base::Base64Decode(log_id_base64, &sth_out->log_id); -} - -// Runs |closure| on the IO thread and waits until it completes. -void RunOnIOThreadBlocking(base::OnceClosure closure) { - base::RunLoop run_loop; - - content::BrowserThread::PostTaskAndReply(content::BrowserThread::IO, - FROM_HERE, std::move(closure), - run_loop.QuitClosure()); - - run_loop.Run(); -} - -// Adds an entry to the HostCache used by a particular URLRequestContext. -// The entry will map |hostname| to |ip_literal|, as though a DNS lookup had -// been performed and an an A/AAAA record had been found for this mapping. -void AddCacheEntryOnIOThread(net::URLRequestContextGetter* context_getter, - const std::string& hostname, - const std::string& ip_literal) { - ASSERT_TRUE(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - net::HostCache* cache = - context_getter->GetURLRequestContext()->host_resolver()->GetHostCache(); - ASSERT_TRUE(cache); - - net::AddressList address_list; - ASSERT_THAT(net::ParseAddressList(ip_literal, hostname, &address_list), - IsOk()); - - cache->Set(net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0), - net::HostCache::Entry(net::OK, address_list, - net::HostCache::Entry::SOURCE_DNS), - base::TimeTicks::Now(), kZeroTTL); -} - -// A test fixture that can enable Certificate Transparency checks, then initiate -// a connection to a test HTTPS server and intercept certificate verification so -// that those checks can be performed successfully. This involves substituting a -// test certificate for a real certificate containing Signed Certificate -// Timestamps. Certificate verification is hard-coded to succeed, so the real -// certificate will never be treated as expired. -class CertificateTransparencyBrowserTest : public CertVerifierBrowserTest { - public: - CertificateTransparencyBrowserTest() - : CertVerifierBrowserTest(), - https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { - feature_list_.InitWithFeatures({certificate_transparency::kCTLogAuditing}, - {}); - } - - protected: - void TestCTHistogramsArePopulated(bool use_profile) { - net::URLRequestContextGetter* request_context = nullptr; - if (use_profile) { - request_context = browser()->profile()->GetRequestContext(); - } else { - request_context = g_browser_process->system_request_context(); - } - - // Provide an STH from Google's Pilot log that can be used to prove - // inclusion for an SCT later in the test. - SignedTreeHead pilot_sth; - ASSERT_TRUE(BuildSignedTreeHead( - base::Time::FromJsTime(1512419914170), 181871752, - "bvgljSy3Yg32Y6J8qL5WmUA3jn2WnOrEFDqxD0AxUvs=", - "BAMARjBEAiAwEXve2RBk3XkUR+6nACSETTgzKFaEeginxuj5U9BI/" - "wIgBPuQS5ACxsro6TtpY4bQyE6WlMdcSMiMd/SSGraOBOg=", - "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=", &pilot_sth)); - chrome_browser_net::GetGlobalSTHDistributor()->NewSTHObserved(pilot_sth); - - // Provide an STH from Google's Aviator log that is not recent enough to - // prove inclusion for an SCT later in the test. - SignedTreeHead aviator_sth; - ASSERT_TRUE(BuildSignedTreeHead( - base::Time::FromJsTime(1442652106945), 8502329, - "bfG+gWZcHl9fqtNo0Z/uggs8E5YqGOtJQ0Z5zVZDRxI=", - "BAMARjBEAiA6elcNQoShmKLHj/" - "IA649UIbaQtWJEpj0Eot0q7G6fEgIgYChb7U6Reuvt0nO5PionH+3UciOxKV3Cy8/" - "eq59lSYY=", - "aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=", &aviator_sth)); - chrome_browser_net::GetGlobalSTHDistributor()->NewSTHObserved(aviator_sth); - - // TODO(robpercival): Override CT log list to ensure it includes Google's - // Pilot and Aviator CT logs, as well as DigiCert's CT log. - - // Connect to https_server_ using the name "localhost", rather than by IP - // address. CT inclusion checks are skipped if a host was not looked up - // using DNS, so a hostname must be used. - https_server_.SetSSLConfig( - net::test_server::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); - ASSERT_TRUE(https_server_.Start()); - - // Add "localhost" to the HostCache, so that it appears that a DNS lookup - // was performed for this hostname. This will make the SCTs provided by the - // server eligible for inclusion checks. - RunOnIOThreadBlocking(base::BindOnce(&AddCacheEntryOnIOThread, - base::RetainedRef(request_context), - "localhost", "127.0.0.1")); - - // Swap the normal test cert for one that contains 3 SCTs and fulfills - // Chrome's CT policy. To do so, setup the mock_cert_verifier to swap the - // HTTP server's certificate for a different one during the verification - // process, and return a CertVerifyResult that indicates that this - // replacement cert is valid and issued by a known root (CT checks are - // skipped for private roots). - net::CertVerifyResult verify_result; - verify_result.is_issued_by_known_root = true; - verify_result.cert_status = 0; - - { - base::ScopedAllowBlockingForTesting allow_blocking_for_loading_cert; - - verify_result.verified_cert = net::CreateCertificateChainFromFile( - net::GetTestCertsDirectory(), "comodo-chain.pem", - net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE); - ASSERT_TRUE(verify_result.verified_cert); - } - - mock_cert_verifier()->AddResultForCert(https_server_.GetCertificate(), - verify_result, net::OK); - - const int kNumSCTs = 3; // Number of SCTs in verified_cert - base::HistogramTester histograms; - - // Navigate to a test server URL, which should trigger a CT inclusion check - // thanks to the cert mock_cert_verifier swaps in. - GURL url = https_server_.GetURL("/"); - if (use_profile) { - ui_test_utils::NavigateToURL(browser(), url); - } else { - content::LoadBasicRequest( - g_browser_process->system_network_context_manager()->GetContext(), - url); - } - - // Find out how many connections Chrome made (it may make more than one). - const base::HistogramBase::Count connection_count = - histograms.GetBucketCount("Net.SSL_Connection_Error", net::OK); - ASSERT_TRUE(connection_count > 0); - - // Expect 3 SCTs in each connection. - EXPECT_THAT(histograms.GetBucketCount( - "Net.CertificateTransparency.SCTsPerConnection", kNumSCTs), - connection_count); - - // Expect that the SCTs were embedded in the certificate. - EXPECT_THAT(histograms.GetBucketCount( - "Net.CertificateTransparency.SCTOrigin", - static_cast<int>( - net::ct::SignedCertificateTimestamp::SCT_EMBEDDED)), - kNumSCTs * connection_count); - - // The certificate contains a sufficient number and diversity of SCTs. - // 2 from Google CT logs (Pilot, Aviator) and 1 from a non-Google CT log - // (DigiCert). - histograms.ExpectUniqueSample( - "Net.CertificateTransparency.ConnectionComplianceStatus2.SSL", - static_cast<int>( - net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS), - connection_count); - - // The CanInclusionCheckSCT histogram should only have a single sample in - // each bucket, because SCTs should be de-duplicated prior to inclusion - // checks. - - // The Pilot SCT should be eligible for inclusion checking, because a recent - // enough Pilot STH is available. - histograms.ExpectBucketCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", - certificate_transparency::CAN_BE_CHECKED, 1); - // The Aviator SCT should not be eligible for inclusion checking, because - // there is not a recent enough Aviator STH available. - histograms.ExpectBucketCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", - certificate_transparency::NEWER_STH_REQUIRED, 1); - // The DigiCert SCT should not be eligible for inclusion checking, because - // there is no DigiCert STH available. - histograms.ExpectBucketCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", - certificate_transparency::VALID_STH_REQUIRED, 1); - } - - net::EmbeddedTestServer https_server_; - - private: - base::test::ScopedFeatureList feature_list_; - - DISALLOW_COPY_AND_ASSIGN(CertificateTransparencyBrowserTest); -}; - -// Tests that wiring is correctly setup in ProfileIOData to pass Signed -// Certificate Timestamps (SCTs) through from the SSL socket code to the CT -// verification and inclusion checking code. This is assessed by checking that -// histograms are correctly populated. -IN_PROC_BROWSER_TEST_F(CertificateTransparencyBrowserTest, ProfileRequest) { - ASSERT_NO_FATAL_FAILURE(TestCTHistogramsArePopulated(true)); -} - -// Tests that wiring is correctly setup in IOThread to pass Signed Certificate -// Timestamps (SCTs) through from the SSL socket code to the CT verification and -// inclusion checking code. This is assessed by checking that histograms are -// correctly populated. -IN_PROC_BROWSER_TEST_F(CertificateTransparencyBrowserTest, SystemRequest) { - ASSERT_NO_FATAL_FAILURE(TestCTHistogramsArePopulated(false)); -} - -} // namespace
diff --git a/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc b/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc index a7a108d..47983c71 100644 --- a/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc +++ b/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
@@ -17,6 +17,7 @@ #include "base/guid.h" #include "base/logging.h" #include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "base/time/clock.h" #include "base/time/default_clock.h" @@ -38,6 +39,9 @@ namespace { +const char kRecurrentInterstitialThresholdParam[] = "threshold"; +const int kRecurrentInterstitialDefaultThreshold = 3; + // The default expiration is one week, unless overidden by a field trial group. // See https://crbug.com/487270. const uint64_t kDeltaDefaultExpirationInSeconds = UINT64_C(604800); @@ -154,6 +158,9 @@ } // namespace +const base::Feature kRecurrentInterstitialFeature{ + "RecurrentInterstitialFeature", base::FEATURE_DISABLED_BY_DEFAULT}; + // This helper function gets the dictionary of certificate fingerprints to // errors of certificates that have been accepted by the user from the content // dictionary that has been passed in. The returned pointer is owned by the the @@ -488,6 +495,39 @@ NOTREACHED(); return false; } + void ChromeSSLHostStateDelegate::SetClock(std::unique_ptr<base::Clock> clock) { clock_ = std::move(clock); } + +void ChromeSSLHostStateDelegate::DidDisplayErrorPage(int error) { + if (error != net::ERR_CERT_SYMANTEC_LEGACY && + error != net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED) { + return; + } + const auto count_it = recurrent_errors_.find(error); + if (count_it == recurrent_errors_.end()) { + recurrent_errors_[error] = 1; + return; + } + if (count_it->second >= base::GetFieldTrialParamByFeatureAsInt( + kRecurrentInterstitialFeature, + kRecurrentInterstitialThresholdParam, + kRecurrentInterstitialDefaultThreshold)) { + return; + } + recurrent_errors_[error] = count_it->second + 1; +} + +bool ChromeSSLHostStateDelegate::HasSeenRecurrentErrors(int error) const { + if (!base::FeatureList::IsEnabled(kRecurrentInterstitialFeature)) { + return false; + } + const auto count = recurrent_errors_.find(error); + if (count == recurrent_errors_.end()) + return false; + return count->second >= base::GetFieldTrialParamByFeatureAsInt( + kRecurrentInterstitialFeature, + kRecurrentInterstitialThresholdParam, + kRecurrentInterstitialDefaultThreshold); +}
diff --git a/chrome/browser/ssl/chrome_ssl_host_state_delegate.h b/chrome/browser/ssl/chrome_ssl_host_state_delegate.h index 13dc842..893674d9 100644 --- a/chrome/browser/ssl/chrome_ssl_host_state_delegate.h +++ b/chrome/browser/ssl/chrome_ssl_host_state_delegate.h
@@ -8,6 +8,7 @@ #include <memory> #include <set> +#include "base/feature_list.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/time/time.h" @@ -20,10 +21,13 @@ class DictionaryValue; } // namespace base -// Tracks whether the user has allowed a certificate error exception for a -// specific site, SSL fingerprint, and error. Based on command-line flags and -// experimental group, remembers this decision either until end-of-session or -// for a particular length of time. +extern const base::Feature kRecurrentInterstitialFeature; + +// Tracks state related to certificate and SSL errors. This state includes: +// - certificate error exceptions (which are remembered for a particular length +// of time depending on experimental groups) +// - mixed content exceptions +// - when errors have recurred multiple times class ChromeSSLHostStateDelegate : public content::SSLHostStateDelegate { public: explicit ChromeSSLHostStateDelegate(Profile* profile); @@ -63,6 +67,18 @@ // error combination exception is allowed, use QueryPolicy(). bool HasAllowException(const std::string& host) const override; + // Called when an error page is displayed for a given error code |error|. + // Tracks whether an error of interest has recurred over a threshold number of + // times. + void DidDisplayErrorPage(int error); + + // Returns true if DidDisplayErrorPage() has been called over a threshold + // number of times for a particular error. Always returns false if + // |kRecurrentInterstitialFeature| is not enabled. Only certain error codes of + // interest are tracked, so this may return false for an error code that has + // recurred. + bool HasSeenRecurrentErrors(int error) const; + protected: // SetClock takes ownership of the passed in clock. void SetClock(std::unique_ptr<base::Clock> clock); @@ -148,6 +164,10 @@ // https://crbug.com/418631 for more details. const std::string current_expiration_guid_; + // Tracks how many times an error page has been shown for a given error, up + // to a certain threshold value. + std::map<int /* error code */, int /* count */> recurrent_errors_; + DISALLOW_COPY_AND_ASSIGN(ChromeSSLHostStateDelegate); };
diff --git a/chrome/browser/ssl/chrome_ssl_host_state_delegate_test.cc b/chrome/browser/ssl/chrome_ssl_host_state_delegate_test.cc index 10193b9c..00a4120 100644 --- a/chrome/browser/ssl/chrome_ssl_host_state_delegate_test.cc +++ b/chrome/browser/ssl/chrome_ssl_host_state_delegate_test.cc
@@ -345,6 +345,30 @@ EXPECT_EQ(ContentSettingsPattern::Wildcard(), settings[0].secondary_pattern); } +// Tests that ChromeSSLHostStateDelegate::HasSeenRecurrentErrors returns true +// after seeing an error of interest multiple times. +IN_PROC_BROWSER_TEST_F(ChromeSSLHostStateDelegateTest, HasSeenRecurrentErrors) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters(kRecurrentInterstitialFeature, + {{"threshold", "2"}}); + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); + content::SSLHostStateDelegate* state = profile->GetSSLHostStateDelegate(); + ChromeSSLHostStateDelegate* chrome_state = + static_cast<ChromeSSLHostStateDelegate*>(state); + + chrome_state->DidDisplayErrorPage(net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED); + EXPECT_FALSE(chrome_state->HasSeenRecurrentErrors( + net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED)); + chrome_state->DidDisplayErrorPage(net::ERR_CERT_SYMANTEC_LEGACY); + EXPECT_FALSE(chrome_state->HasSeenRecurrentErrors( + net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED)); + chrome_state->DidDisplayErrorPage(net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED); + EXPECT_TRUE(chrome_state->HasSeenRecurrentErrors( + net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED)); +} + class ForgetAtSessionEndSSLHostStateDelegateTest : public ChromeSSLHostStateDelegateTest { protected:
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc index 5a7db50..ceb82253 100644 --- a/chrome/browser/ssl/ssl_blocking_page.cc +++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -18,6 +18,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/renderer_preferences_util.h" #include "chrome/browser/ssl/cert_report_helper.h" +#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" +#include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h" #include "chrome/browser/ssl/ssl_cert_reporter.h" #include "chrome/browser/ssl/ssl_error_controller_client.h" #include "chrome/common/chrome_switches.h" @@ -85,6 +87,11 @@ overridable, is_superfish)); metrics_helper.get()->StartRecordingCaptivePortalMetrics(overridable); + ChromeSSLHostStateDelegate* state = + ChromeSSLHostStateDelegateFactory::GetForProfile( + Profile::FromBrowserContext(web_contents->GetBrowserContext())); + state->DidDisplayErrorPage(cert_error); + return new SSLBlockingPage(web_contents, cert_error, ssl_info, request_url, options_mask, time_triggered, support_url, std::move(ssl_cert_reporter), overridable,
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index 9b046f50..43ca383 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -6,7 +6,6 @@ #include <utility> -#include "base/command_line.h" #include "base/feature_list.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -21,16 +20,11 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_attributes_entry.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/supervised_user/experimental/supervised_user_filtering_switches.h" #include "chrome/browser/supervised_user/permission_request_creator.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_features.h" -#include "chrome/browser/supervised_user/supervised_user_navigation_throttle.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_observer.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" @@ -40,20 +34,14 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/browser_sync/profile_sync_service.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" -#include "components/signin/core/browser/signin_manager.h" -#include "components/signin/core/browser/signin_manager_base.h" -#include "components/signin/core/browser/signin_switches.h" #include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "extensions/buildflags/buildflags.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -78,9 +66,7 @@ #include "extensions/browser/extension_system.h" #endif -using base::DictionaryValue; using base::UserMetricsAction; -using content::BrowserThread; #if BUILDFLAG(ENABLE_EXTENSIONS) using extensions::Extension; @@ -343,14 +329,10 @@ #if !defined(OS_ANDROID) void SupervisedUserService::InitSync(const std::string& refresh_token) { - StartSetupSync(); - ProfileOAuth2TokenService* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); token_service->UpdateCredentials(supervised_users::kSupervisedUserPseudoEmail, refresh_token); - - FinishSetupSyncWhenReady(); } #endif // !defined(OS_ANDROID) @@ -394,7 +376,6 @@ profile_(profile), active_(false), delegate_(NULL), - waiting_for_sync_initialization_(false), is_profile_active_(false), did_init_(false), did_shutdown_(false), @@ -417,19 +398,10 @@ if (!delegate_ || !delegate_->SetActive(active_)) { if (active_) { #if !defined(OS_ANDROID) - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kSupervisedUserSyncToken)) { - InitSync( - command_line->GetSwitchValueASCII( - switches::kSupervisedUserSyncToken)); - } - ProfileOAuth2TokenService* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); token_service->LoadCredentials( supervised_users::kSupervisedUserPseudoEmail); - - SetupSync(); #else NOTREACHED(); #endif @@ -522,9 +494,6 @@ observer.OnURLFilterChanged(); #if !defined(OS_ANDROID) - if (waiting_for_sync_initialization_) - ProfileSyncServiceFactory::GetForProfile(profile_)->RemoveObserver(this); - // TODO(bauerb): Get rid of the platform-specific #ifdef here. // http://crbug.com/313377 BrowserList::RemoveObserver(this); @@ -532,51 +501,6 @@ } } -#if !defined(OS_ANDROID) -void SupervisedUserService::SetupSync() { - StartSetupSync(); - FinishSetupSyncWhenReady(); -} - -void SupervisedUserService::StartSetupSync() { - // Tell the sync service that setup is in progress so we don't start syncing - // until we've finished configuration. - sync_blocker_ = ProfileSyncServiceFactory::GetForProfile(profile_) - ->GetSetupInProgressHandle(); -} - -void SupervisedUserService::FinishSetupSyncWhenReady() { - // If we're already waiting for the sync engine, there's nothing to do here. - if (waiting_for_sync_initialization_) - return; - - // Continue in FinishSetupSync() once the sync engine has been initialized. - browser_sync::ProfileSyncService* service = - ProfileSyncServiceFactory::GetForProfile(profile_); - if (service->IsEngineInitialized()) { - FinishSetupSync(); - } else { - service->AddObserver(this); - waiting_for_sync_initialization_ = true; - } -} - -void SupervisedUserService::FinishSetupSync() { - browser_sync::ProfileSyncService* service = - ProfileSyncServiceFactory::GetForProfile(profile_); - DCHECK(service->IsEngineInitialized()); - - // Sync nothing (except types which are set via GetPreferredDataTypes). - bool sync_everything = false; - syncer::ModelTypeSet synced_datatypes; - service->OnUserChoseDatatypes(sync_everything, synced_datatypes); - - // Notify ProfileSyncService that we are done with configuration. - sync_blocker_.reset(); - service->SetFirstSetupComplete(); -} -#endif - bool SupervisedUserService::ProfileIsSupervised() const { return profile_->IsSupervised(); } @@ -837,11 +761,9 @@ base::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser")); } SetActive(false); - sync_blocker_.reset(); browser_sync::ProfileSyncService* sync_service = ProfileSyncServiceFactory::GetForProfile(profile_); - // Can be null in tests. if (sync_service) sync_service->RemovePreferenceProvider(this); @@ -1121,19 +1043,6 @@ } #if !defined(OS_ANDROID) -void SupervisedUserService::OnStateChanged(syncer::SyncService* sync) { - if (waiting_for_sync_initialization_ && sync->IsEngineInitialized()) { - waiting_for_sync_initialization_ = false; - sync->RemoveObserver(this); - FinishSetupSync(); - return; - } - - DLOG_IF(ERROR, sync->GetAuthError().state() == - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) - << "Credentials rejected"; -} - void SupervisedUserService::OnBrowserSetLastActive(Browser* browser) { bool profile_became_active = profile_->IsSameProfile(browser->profile()); if (!is_profile_active_ && profile_became_active)
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h index 710ac0e6..edf917f 100644 --- a/chrome/browser/supervised_user/supervised_user_service.h +++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -27,7 +27,6 @@ #include "chrome/browser/ui/browser_list_observer.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" -#include "components/sync/driver/sync_service_observer.h" #include "components/sync/driver/sync_type_preference_provider.h" #include "extensions/buildflags/buildflags.h" #include "net/url_request/url_request_context_getter.h" @@ -60,10 +59,6 @@ class ExtensionRegistry; } -namespace syncer { -class SyncSetupInProgressHandle; -} - namespace user_prefs { class PrefRegistrySyncable; } @@ -78,7 +73,6 @@ #endif public syncer::SyncTypePreferenceProvider, #if !defined(OS_ANDROID) - public syncer::SyncServiceObserver, public BrowserListObserver, #endif public SupervisedUserURLFilter::Observer { @@ -200,9 +194,6 @@ syncer::ModelTypeSet GetPreferredDataTypes() const override; #if !defined(OS_ANDROID) - // syncer::SyncServiceObserver implementation: - void OnStateChanged(syncer::SyncService* sync) override; - // BrowserListObserver implementation: void OnBrowserSetLastActive(Browser* browser) override; #endif // !defined(OS_ANDROID) @@ -231,13 +222,6 @@ void SetActive(bool active); -#if !defined(OS_ANDROID) - void SetupSync(); - void StartSetupSync(); - void FinishSetupSyncWhenReady(); - void FinishSetupSync(); -#endif - bool ProfileIsSupervised() const; void OnCustodianInfoChanged(); @@ -361,8 +345,6 @@ PrefChangeRegistrar pref_change_registrar_; - // True iff we're waiting for the Sync service to be initialized. - bool waiting_for_sync_initialization_; bool is_profile_active_; std::vector<NavigationBlockedCallback> navigation_blocked_callbacks_; @@ -406,9 +388,6 @@ base::ObserverList<SupervisedUserServiceObserver> observer_list_; - // Prevents Sync from running until configuration is complete. - std::unique_ptr<syncer::SyncSetupInProgressHandle> sync_blocker_; - base::WeakPtrFactory<SupervisedUserService> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SupervisedUserService);
diff --git a/chrome/browser/task_manager/providers/web_contents/background_contents_tag_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/background_contents_tag_browsertest.cc index bc00df6a..4c144415 100644 --- a/chrome/browser/task_manager/providers/web_contents/background_contents_tag_browsertest.cc +++ b/chrome/browser/task_manager/providers/web_contents/background_contents_tag_browsertest.cc
@@ -19,7 +19,7 @@ // properly and the TagsManager records these tags. It is also used to test that // the WebContentsTaskProvider will be able to provide the appropriate // BackgroundContentsTask. -class BackgroundContentsTagTest : public ExtensionBrowserTest { +class BackgroundContentsTagTest : public extensions::ExtensionBrowserTest { public: BackgroundContentsTagTest() {} ~BackgroundContentsTagTest() override {} @@ -41,10 +41,10 @@ } protected: - // ExtensionBrowserTest: + // extensions::ExtensionBrowserTest: void SetUpCommandLine(base::CommandLine* command_line) override { // Pass flags to make testing apps easier. - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); test_data_dir_ = test_data_dir_.AppendASCII("api_test"); command_line->AppendSwitch(switches::kDisableRendererBackgrounding); command_line->AppendSwitch(switches::kDisablePopupBlocking);
diff --git a/chrome/browser/task_manager/providers/web_contents/extension_tag_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/extension_tag_browsertest.cc index 0a73517..9d0b6be8 100644 --- a/chrome/browser/task_manager/providers/web_contents/extension_tag_browsertest.cc +++ b/chrome/browser/task_manager/providers/web_contents/extension_tag_browsertest.cc
@@ -18,15 +18,15 @@ namespace task_manager { -class ExtensionTagsTest : public ExtensionBrowserTest { +class ExtensionTagsTest : public extensions::ExtensionBrowserTest { public: ExtensionTagsTest() {} ~ExtensionTagsTest() override {} protected: - // ExtensionBrowserTest: + // extensions::ExtensionBrowserTest: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); // Do not launch device discovery process. command_line->AppendSwitch(switches::kDisableDeviceDiscoveryNotifications);
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index b1dc996..4117640 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -77,7 +77,7 @@ } // namespace -class TaskManagerBrowserTest : public ExtensionBrowserTest { +class TaskManagerBrowserTest : public extensions::ExtensionBrowserTest { public: TaskManagerBrowserTest() {} ~TaskManagerBrowserTest() override {} @@ -117,7 +117,7 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); // Do not launch device discovery process. command_line->AppendSwitch(switches::kDisableDeviceDiscoveryNotifications); @@ -125,11 +125,11 @@ void TearDownOnMainThread() override { model_.reset(); - ExtensionBrowserTest::TearDownOnMainThread(); + extensions::ExtensionBrowserTest::TearDownOnMainThread(); } void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); // Add content/test/data so we can use cross_site_iframe_factory.html
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc index 76280b6..ae5065c 100644 --- a/chrome/browser/themes/theme_properties.cc +++ b/chrome/browser/themes/theme_properties.cc
@@ -160,14 +160,16 @@ case ThemeProperties::COLOR_TAB_TEXT: case ThemeProperties::COLOR_BOOKMARK_TEXT: + return incognito ? gfx::kGoogleGrey100 : gfx::kGoogleGrey800; + case ThemeProperties::COLOR_TAB_CLOSE_BUTTON_ACTIVE: case ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON: - return incognito ? gfx::kGoogleGrey100 : gfx::kGoogleGrey800; + return incognito ? gfx::kGoogleGrey100 : gfx::kChromeIconGrey; case ThemeProperties::COLOR_BACKGROUND_TAB_TEXT: case ThemeProperties::COLOR_TAB_CLOSE_BUTTON_INACTIVE: case ThemeProperties::COLOR_TAB_ALERT_AUDIO: - return incognito ? gfx::kGoogleGrey400 : gfx::kGoogleGrey700; + return incognito ? gfx::kGoogleGrey400 : gfx::kChromeIconGrey; case ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_HOVER: return incognito ? gfx::kGoogleGrey700 : gfx::kGoogleGrey200;
diff --git a/chrome/browser/themes/theme_service_browsertest.cc b/chrome/browser/themes/theme_service_browsertest.cc index 4b0a959..4afc9da 100644 --- a/chrome/browser/themes/theme_service_browsertest.cc +++ b/chrome/browser/themes/theme_service_browsertest.cc
@@ -28,7 +28,7 @@ !theme_service.UsingDefaultTheme(); } -class ThemeServiceBrowserTest : public ExtensionBrowserTest { +class ThemeServiceBrowserTest : public extensions::ExtensionBrowserTest { public: ThemeServiceBrowserTest() { } @@ -36,7 +36,7 @@ void SetUp() override { extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); - ExtensionBrowserTest::SetUp(); + extensions::ExtensionBrowserTest::SetUp(); } private:
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 0f14f25..e7da097d 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1389,8 +1389,6 @@ "omnibox/chrome_omnibox_navigation_observer.h", "omnibox/clipboard_utils.cc", "omnibox/clipboard_utils.h", - "omnibox/favicon_cache.cc", - "omnibox/favicon_cache.h", "omnibox/omnibox_theme.cc", "omnibox/omnibox_theme.h", "page_info/page_info_dialog.cc", @@ -1876,8 +1874,6 @@ "views/extensions/request_file_system_dialog_view.h", "views/frame/browser_frame_ash.cc", "views/frame/browser_frame_ash.h", - "views/frame/browser_frame_header_ash.cc", - "views/frame/browser_frame_header_ash.h", "views/frame/browser_non_client_frame_view_ash.cc", "views/frame/browser_non_client_frame_view_ash.h", "views/frame/immersive_context_mus.cc",
diff --git a/chrome/browser/ui/android/infobars/framebust_block_infobar.cc b/chrome/browser/ui/android/infobars/framebust_block_infobar.cc index e79ce61a..dbaa1c1 100644 --- a/chrome/browser/ui/android/infobars/framebust_block_infobar.cc +++ b/chrome/browser/ui/android/infobars/framebust_block_infobar.cc
@@ -34,8 +34,10 @@ if (!owner()) return; // We're closing; don't call anything, it might access the owner. + // Tapping the button means that the user wants to bypass the intervention in + // a sticky way, e.g. via content settings. DCHECK_EQ(action, InfoBarAndroid::ACTION_OK); - delegate_->AcceptIntervention(); + delegate_->DeclineInterventionSticky(); RemoveSelf(); }
diff --git a/chrome/browser/ui/app_list/app_context_menu_unittest.cc b/chrome/browser/ui/app_list/app_context_menu_unittest.cc index 774fbd94..ad4b3123 100644 --- a/chrome/browser/ui/app_list/app_context_menu_unittest.cc +++ b/chrome/browser/ui/app_list/app_context_menu_unittest.cc
@@ -257,6 +257,46 @@ if (!platform_app) { AddToStates(menu, MenuState(app_list::AppContextMenu::LAUNCH_NEW), &states); + if (!features::IsTouchableAppContextMenuEnabled()) { + AddSeparator(&states); + + if (extensions::util::CanHostedAppsOpenInWindows() && + extensions::util::IsNewBookmarkAppsEnabled()) { + bool checked = launch_type == extensions::LAUNCH_TYPE_WINDOW || + launch_type == extensions::LAUNCH_TYPE_FULLSCREEN; + AddToStates( + menu, + MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_WINDOW, true, + checked), + &states); + } else if (!extensions::util::IsNewBookmarkAppsEnabled()) { + bool regular_checked = launch_type == extensions::LAUNCH_TYPE_REGULAR; + + AddToStates( + menu, + MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_REGULAR, true, + regular_checked), + &states); + AddToStates( + menu, + MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_PINNED, true, + launch_type == extensions::LAUNCH_TYPE_PINNED), + &states); + if (extensions::util::CanHostedAppsOpenInWindows()) { + AddToStates( + menu, + MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_WINDOW, + true, launch_type == extensions::LAUNCH_TYPE_WINDOW), + &states); + } + AddToStates( + menu, + MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_FULLSCREEN, + true, + launch_type == extensions::LAUNCH_TYPE_FULLSCREEN), + &states); + } + } } if (pinnable != AppListControllerDelegate::NO_PIN) { AddSeparator(&states); @@ -278,44 +318,6 @@ &states); } - AddSeparator(&states); - - if (!platform_app) { - if (extensions::util::CanHostedAppsOpenInWindows() && - extensions::util::IsNewBookmarkAppsEnabled()) { - bool checked = launch_type == extensions::LAUNCH_TYPE_WINDOW || - launch_type == extensions::LAUNCH_TYPE_FULLSCREEN; - AddToStates(menu, - MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_WINDOW, - true, checked), - &states); - } else if (!extensions::util::IsNewBookmarkAppsEnabled()) { - bool regular_checked = launch_type == extensions::LAUNCH_TYPE_REGULAR; - - AddToStates(menu, - MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_REGULAR, - true, regular_checked), - &states); - AddToStates( - menu, - MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_PINNED, true, - launch_type == extensions::LAUNCH_TYPE_PINNED), - &states); - if (extensions::util::CanHostedAppsOpenInWindows()) { - AddToStates( - menu, - MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_WINDOW, true, - launch_type == extensions::LAUNCH_TYPE_WINDOW), - &states); - } - AddToStates( - menu, - MenuState(app_list::AppContextMenu::USE_LAUNCH_TYPE_FULLSCREEN, - true, launch_type == extensions::LAUNCH_TYPE_FULLSCREEN), - &states); - } - } - ValidateMenuState(menu_model.get(), states); }
diff --git a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc index 79030408..3ddb5b42 100644 --- a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
@@ -49,7 +49,8 @@ } // Browser Test for AppListController that observes search result changes. -using AppListControllerSearchResultsBrowserTest = ExtensionBrowserTest; +using AppListControllerSearchResultsBrowserTest = + extensions::ExtensionBrowserTest; // Test showing search results, and uninstalling one of them while displayed. IN_PROC_BROWSER_TEST_F(AppListControllerSearchResultsBrowserTest,
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc index 1ba9328..e6c2a990 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -903,6 +903,13 @@ return syncer::SyncError(); } +void AppListSyncableService::Shutdown() { + internal_apps_builder_.reset(); + crostini_apps_builder_.reset(); + arc_apps_builder_.reset(); + apps_builder_.reset(); +} + // AppListSyncableService private bool AppListSyncableService::ProcessSyncItemSpecifics(
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.h b/chrome/browser/ui/app_list/app_list_syncable_service.h index 78c5245d..6bc7e33 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.h +++ b/chrome/browser/ui/app_list/app_list_syncable_service.h
@@ -162,6 +162,9 @@ const base::Location& from_here, const syncer::SyncChangeList& change_list) override; + // KeyedService + void Shutdown() override; + private: class ModelUpdaterDelegate;
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc b/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc index 913b104..b909bf8 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
@@ -86,6 +86,19 @@ content::BrowserContext* AppListSyncableServiceFactory::GetBrowserContextToUse( content::BrowserContext* context) const { + Profile* const profile = Profile::FromBrowserContext(context); + // No service if |context| is not a profile. + if (!profile) + return nullptr; + + // No service for system profile. + if (profile->IsSystemProfile()) + return nullptr; + + // Use profile as-is for guest session. + if (profile->IsGuestSession()) + return chrome::GetBrowserContextOwnInstanceInIncognito(context); + // This matches the logic in ExtensionSyncServiceFactory, which uses the // orginal browser context. return chrome::GetBrowserContextRedirectedInIncognito(context);
diff --git a/chrome/browser/ui/app_list/extension_app_context_menu.cc b/chrome/browser/ui/app_list/extension_app_context_menu.cc index 61be1e0e5..e7b9094 100644 --- a/chrome/browser/ui/app_list/extension_app_context_menu.cc +++ b/chrome/browser/ui/app_list/extension_app_context_menu.cc
@@ -89,7 +89,38 @@ // First, add the primary actions. if (!is_platform_app_) { - AddContextMenuOption(menu_model, LAUNCH_NEW, GetLaunchStringId()); + if (features::IsTouchableAppContextMenuEnabled()) { + CreateOpenNewSubmenu(menu_model); + } else { + AddContextMenuOption(menu_model, LAUNCH_NEW, GetLaunchStringId()); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + + // When bookmark apps are enabled, hosted apps can only toggle between + // USE_LAUNCH_TYPE_WINDOW and USE_LAUNCH_TYPE_REGULAR. + if (extensions::util::CanHostedAppsOpenInWindows() && + extensions::util::IsNewBookmarkAppsEnabled()) { + // When both flags are enabled, only allow toggling between + // USE_LAUNCH_TYPE_WINDOW and USE_LAUNCH_TYPE_REGULAR + AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_WINDOW, + IDS_APP_CONTEXT_MENU_OPEN_WINDOW); + } else if (!extensions::util::IsNewBookmarkAppsEnabled()) { + // When new bookmark apps are disabled, add pinned and full screen + // options as well. Add open as window if CanHostedAppsOpenInWindows + // is enabled. + AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_REGULAR, + IDS_APP_CONTEXT_MENU_OPEN_REGULAR); + AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_PINNED, + IDS_APP_CONTEXT_MENU_OPEN_PINNED); + if (extensions::util::CanHostedAppsOpenInWindows()) { + AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_WINDOW, + IDS_APP_CONTEXT_MENU_OPEN_WINDOW); + } + // Even though the launch type is Full Screen it is more accurately + // described as Maximized in Ash. + AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_FULLSCREEN, + IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); + } + } } // Create default items. @@ -118,46 +149,11 @@ is_platform_app_ ? IDS_APP_LIST_UNINSTALL_ITEM : IDS_APP_LIST_EXTENSIONS_UNINSTALL); - if (controller()->CanDoShowAppInfoFlow()) + if (controller()->CanDoShowAppInfoFlow()) { AddContextMenuOption(menu_model, SHOW_APP_INFO, IDS_APP_CONTEXT_MENU_SHOW_INFO); - - if (!features::IsTouchableAppContextMenuEnabled()) - menu_model->AddSeparator(ui::NORMAL_SEPARATOR); - - if (!is_platform_app_) { - // When bookmark apps are enabled, hosted apps can only toggle between - // USE_LAUNCH_TYPE_WINDOW and USE_LAUNCH_TYPE_REGULAR. - if (extensions::util::CanHostedAppsOpenInWindows() && - extensions::util::IsNewBookmarkAppsEnabled()) { - // When both flags are enabled, only allow toggling between - // USE_LAUNCH_TYPE_WINDOW and USE_LAUNCH_TYPE_REGULAR - AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_WINDOW, - IDS_APP_CONTEXT_MENU_OPEN_WINDOW); - } else if (!extensions::util::IsNewBookmarkAppsEnabled()) { - // When new bookmark apps are disabled, add pinned and full screen - // options as well. Add open as window if CanHostedAppsOpenInWindows - // is enabled. - AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_REGULAR, - IDS_APP_CONTEXT_MENU_OPEN_REGULAR); - AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_PINNED, - IDS_APP_CONTEXT_MENU_OPEN_PINNED); - if (extensions::util::CanHostedAppsOpenInWindows()) { - AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_WINDOW, - IDS_APP_CONTEXT_MENU_OPEN_WINDOW); - } - // Even though the launch type is Full Screen it is more accurately - // described as Maximized in Ash. - AddContextMenuOption(menu_model, USE_LAUNCH_TYPE_FULLSCREEN, - IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); - } - } } -} - -bool ExtensionAppContextMenu::IsItemForCommandIdDynamic(int command_id) const { - return command_id == LAUNCH_NEW || - AppContextMenu::IsItemForCommandIdDynamic(command_id); + } } base::string16 ExtensionAppContextMenu::GetLabelForCommandId( @@ -187,6 +183,11 @@ return true; } +bool ExtensionAppContextMenu::IsItemForCommandIdDynamic(int command_id) const { + return command_id == LAUNCH_NEW || + AppContextMenu::IsItemForCommandIdDynamic(command_id); +} + bool ExtensionAppContextMenu::IsCommandIdChecked(int command_id) const { if (command_id >= USE_LAUNCH_TYPE_COMMAND_START && command_id < USE_LAUNCH_TYPE_COMMAND_END) { @@ -255,4 +256,22 @@ } } +void ExtensionAppContextMenu::CreateOpenNewSubmenu( + ui::SimpleMenuModel* menu_model) { + // Touchable extension context menus use an actionable submenu for LAUNCH_NEW. + const int kGroupId = 1; + open_new_submenu_model_ = std::make_unique<ui::SimpleMenuModel>(this); + open_new_submenu_model_->AddRadioItemWithStringId( + USE_LAUNCH_TYPE_REGULAR, IDS_APP_LIST_CONTEXT_MENU_NEW_TAB, kGroupId); + open_new_submenu_model_->AddRadioItemWithStringId( + USE_LAUNCH_TYPE_WINDOW, IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW, kGroupId); + const views::MenuConfig& menu_config = views::MenuConfig::instance(); + const gfx::VectorIcon& icon = + GetMenuItemVectorIcon(LAUNCH_NEW, GetLaunchStringId()); + menu_model->AddActionableSubmenuWithStringIdAndIcon( + LAUNCH_NEW, GetLaunchStringId(), open_new_submenu_model_.get(), + gfx::CreateVectorIcon(icon, menu_config.touchable_icon_size, + menu_config.touchable_icon_color)); +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/extension_app_context_menu.h b/chrome/browser/ui/app_list/extension_app_context_menu.h index 066d4ff..db1603a 100644 --- a/chrome/browser/ui/app_list/extension_app_context_menu.h +++ b/chrome/browser/ui/app_list/extension_app_context_menu.h
@@ -52,8 +52,15 @@ } private: + // Creates the actionable submenu for LAUNCH_NEW. + void CreateOpenNewSubmenu(ui::SimpleMenuModel* menu_model); + bool is_platform_app_ = false; + // The MenuModel used to control LAUNCH_NEW's icon, label, and + // execution when touchable app context menus are enabled. + std::unique_ptr<ui::SimpleMenuModel> open_new_submenu_model_; + std::unique_ptr<extensions::ContextMenuMatcher> extension_menu_items_; DISALLOW_COPY_AND_ASSIGN(ExtensionAppContextMenu);
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index 1e4b685..cc47bbf 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -148,6 +148,8 @@ ash::kCanConsumeSystemKeysKey, ash::mojom::kCanConsumeSystemKeys_Property, aura::PropertyConverter::CreateAcceptAnyValueCallback()); + converter->RegisterImageSkiaProperty( + ash::kFrameImageActiveKey, ash::mojom::kFrameImageActive_Property); converter->RegisterPrimitiveProperty( ash::kHideShelfWhenFullscreenKey, ash::mojom::kHideShelfWhenFullscreen_Property, @@ -180,6 +182,10 @@ ash::kRestoreWindowStateTypeOverrideKey, ash::mojom::kRestoreWindowStateTypeOverride_Property, base::BindRepeating(&ash::IsValidWindowStateType)); + converter->RegisterPrimitiveProperty( + ash::kWindowTitleShownKey, + ui::mojom::WindowManager::kWindowTitleShown_Property, + aura::PropertyConverter::CreateAcceptAnyValueCallback()); mus_client->SetMusPropertyMirror( std::make_unique<ash::MusPropertyMirrorAsh>());
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc index b6b869cb..12890a8 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -154,7 +154,7 @@ } // namespace -class ArcAppLauncherBrowserTest : public ExtensionBrowserTest { +class ArcAppLauncherBrowserTest : public extensions::ExtensionBrowserTest { public: ArcAppLauncherBrowserTest() {} ~ArcAppLauncherBrowserTest() override {} @@ -162,12 +162,12 @@ protected: // content::BrowserTestBase: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); arc::SetArcAvailableCommandLineForTesting(command_line); } void SetUpInProcessBrowserTestFixture() override { - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); arc::ArcSessionManager::SetUiEnabledForTesting(false); }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index 6a4ef1f..fc868a2 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -230,7 +230,7 @@ RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE, }; -class ShelfAppBrowserTest : public ExtensionBrowserTest { +class ShelfAppBrowserTest : public extensions::ExtensionBrowserTest { protected: ShelfAppBrowserTest() {} @@ -244,7 +244,7 @@ controller_ = ChromeLauncherController::instance(); ASSERT_TRUE(controller_); - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); } size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) {
diff --git a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc index 356eb5c..b75c60d 100644 --- a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.cc
@@ -24,6 +24,8 @@ #include "content/public/common/context_menu_params.h" #include "extensions/browser/extension_prefs.h" #include "ui/base/ui_base_features.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/controls/menu/menu_config.h" namespace { @@ -48,84 +50,6 @@ std::move(callback).Run(std::move(menu_model)); } -void ExtensionLauncherContextMenu::BuildMenu(ui::SimpleMenuModel* menu_model) { - extension_items_.reset(new extensions::ContextMenuMatcher( - controller()->profile(), this, menu_model, - base::Bind(MenuItemHasLauncherContext))); - if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { - // V1 apps can be started from the menu - but V2 apps should not. - if (!controller()->IsPlatformApp(item().id)) { - int string_id = (GetLaunchType() == extensions::LAUNCH_TYPE_PINNED || - GetLaunchType() == extensions::LAUNCH_TYPE_REGULAR) - ? IDS_APP_LIST_CONTEXT_MENU_NEW_TAB - : IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW; - AddContextMenuOption(menu_model, MENU_OPEN_NEW, string_id); - if (!features::IsTouchableAppContextMenuEnabled()) - menu_model->AddSeparator(ui::NORMAL_SEPARATOR); - } - - AddPinMenu(menu_model); - - if (controller()->IsOpen(item().id)) { - AddContextMenuOption(menu_model, MENU_CLOSE, - IDS_LAUNCHER_CONTEXT_MENU_CLOSE); - } - - if (!controller()->IsPlatformApp(item().id) && - item().type == ash::TYPE_PINNED_APP) { - if (!features::IsTouchableAppContextMenuEnabled()) - menu_model->AddSeparator(ui::NORMAL_SEPARATOR); - if (extensions::util::IsNewBookmarkAppsEnabled()) { - // With bookmark apps enabled, hosted apps launch in a window by - // default. This menu item is re-interpreted as a single, toggle-able - // option to launch the hosted app as a tab. - AddContextMenuOption(menu_model, LAUNCH_TYPE_WINDOW, - IDS_APP_CONTEXT_MENU_OPEN_WINDOW); - } else { - AddContextMenuOption(menu_model, LAUNCH_TYPE_REGULAR_TAB, - IDS_APP_CONTEXT_MENU_OPEN_REGULAR); - AddContextMenuOption(menu_model, LAUNCH_TYPE_PINNED_TAB, - IDS_APP_CONTEXT_MENU_OPEN_PINNED); - AddContextMenuOption(menu_model, LAUNCH_TYPE_WINDOW, - IDS_APP_CONTEXT_MENU_OPEN_WINDOW); - // Even though the launch type is Full Screen it is more accurately - // described as Maximized in Ash. - AddContextMenuOption(menu_model, LAUNCH_TYPE_FULLSCREEN, - IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); - } - } - } else if (item().type == ash::TYPE_BROWSER_SHORTCUT) { - AddContextMenuOption(menu_model, MENU_NEW_WINDOW, IDS_APP_LIST_NEW_WINDOW); - if (!controller()->profile()->IsGuestSession()) { - AddContextMenuOption(menu_model, MENU_NEW_INCOGNITO_WINDOW, - IDS_APP_LIST_NEW_INCOGNITO_WINDOW); - } - if (!BrowserShortcutLauncherItemController(controller()->shelf_model()) - .IsListOfActiveBrowserEmpty()) { - AddContextMenuOption(menu_model, MENU_CLOSE, - IDS_LAUNCHER_CONTEXT_MENU_CLOSE); - } - } else if (item().type == ash::TYPE_DIALOG) { - AddContextMenuOption(menu_model, MENU_CLOSE, - IDS_LAUNCHER_CONTEXT_MENU_CLOSE); - } else if (controller()->IsOpen(item().id)) { - AddContextMenuOption(menu_model, MENU_CLOSE, - IDS_LAUNCHER_CONTEXT_MENU_CLOSE); - } - if (!features::IsTouchableAppContextMenuEnabled()) - menu_model->AddSeparator(ui::NORMAL_SEPARATOR); - if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { - const extensions::MenuItem::ExtensionKey app_key(item().id.app_id); - if (!app_key.empty()) { - int index = 0; - extension_items_->AppendExtensionItems(app_key, base::string16(), &index, - false); // is_action_menu - if (!features::IsTouchableAppContextMenuEnabled()) - menu_model->AddSeparator(ui::NORMAL_SEPARATOR); - } - } -} - bool ExtensionLauncherContextMenu::IsCommandIdChecked(int command_id) const { switch (command_id) { case LAUNCH_TYPE_PINNED_TAB: @@ -213,6 +137,103 @@ } } +void ExtensionLauncherContextMenu::CreateOpenNewSubmenu( + ui::SimpleMenuModel* menu_model) { + // Touchable extension context menus use an actionable submenu for + // MENU_OPEN_NEW. + const gfx::VectorIcon& icon = + GetMenuItemVectorIcon(MENU_OPEN_NEW, GetLaunchTypeStringId()); + const views::MenuConfig& menu_config = views::MenuConfig::instance(); + const int kGroupId = 1; + open_new_submenu_model_ = std::make_unique<ui::SimpleMenuModel>(this); + open_new_submenu_model_->AddRadioItemWithStringId( + LAUNCH_TYPE_REGULAR_TAB, IDS_APP_LIST_CONTEXT_MENU_NEW_TAB, kGroupId); + open_new_submenu_model_->AddRadioItemWithStringId( + LAUNCH_TYPE_WINDOW, IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW, kGroupId); + menu_model->AddActionableSubmenuWithStringIdAndIcon( + MENU_OPEN_NEW, GetLaunchTypeStringId(), open_new_submenu_model_.get(), + gfx::CreateVectorIcon(icon, menu_config.touchable_icon_size, + menu_config.touchable_icon_color)); +} + +void ExtensionLauncherContextMenu::BuildMenu(ui::SimpleMenuModel* menu_model) { + extension_items_.reset(new extensions::ContextMenuMatcher( + controller()->profile(), this, menu_model, + base::Bind(MenuItemHasLauncherContext))); + if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { + // V1 apps can be started from the menu - but V2 apps should not. + if (!controller()->IsPlatformApp(item().id)) { + if (features::IsTouchableAppContextMenuEnabled()) { + CreateOpenNewSubmenu(menu_model); + } else { + AddContextMenuOption(menu_model, MENU_OPEN_NEW, + GetLaunchTypeStringId()); + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + + // Touchable app context menus do not include these check items, their + // functionality is achieved by an actionable submenu. + if (item().type == ash::TYPE_PINNED_APP) { + if (extensions::util::IsNewBookmarkAppsEnabled()) { + // With bookmark apps enabled, hosted apps launch in a window by + // default. This menu item is re-interpreted as a single, + // toggle-able option to launch the hosted app as a tab. + AddContextMenuOption(menu_model, LAUNCH_TYPE_WINDOW, + IDS_APP_CONTEXT_MENU_OPEN_WINDOW); + } else { + AddContextMenuOption(menu_model, LAUNCH_TYPE_REGULAR_TAB, + IDS_APP_CONTEXT_MENU_OPEN_REGULAR); + AddContextMenuOption(menu_model, LAUNCH_TYPE_PINNED_TAB, + IDS_APP_CONTEXT_MENU_OPEN_PINNED); + AddContextMenuOption(menu_model, LAUNCH_TYPE_WINDOW, + IDS_APP_CONTEXT_MENU_OPEN_WINDOW); + // Even though the launch type is Full Screen it is more accurately + // described as Maximized in Ash. + AddContextMenuOption(menu_model, LAUNCH_TYPE_FULLSCREEN, + IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); + } + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + } + } + } + + AddPinMenu(menu_model); + + if (controller()->IsOpen(item().id)) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } + } else if (item().type == ash::TYPE_BROWSER_SHORTCUT) { + AddContextMenuOption(menu_model, MENU_NEW_WINDOW, IDS_APP_LIST_NEW_WINDOW); + if (!controller()->profile()->IsGuestSession()) { + AddContextMenuOption(menu_model, MENU_NEW_INCOGNITO_WINDOW, + IDS_APP_LIST_NEW_INCOGNITO_WINDOW); + } + if (!BrowserShortcutLauncherItemController(controller()->shelf_model()) + .IsListOfActiveBrowserEmpty()) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } + } else if (item().type == ash::TYPE_DIALOG) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } else if (controller()->IsOpen(item().id)) { + AddContextMenuOption(menu_model, MENU_CLOSE, + IDS_LAUNCHER_CONTEXT_MENU_CLOSE); + } + if (!features::IsTouchableAppContextMenuEnabled()) + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + if (item().type == ash::TYPE_PINNED_APP || item().type == ash::TYPE_APP) { + const extensions::MenuItem::ExtensionKey app_key(item().id.app_id); + if (!app_key.empty()) { + int index = 0; + extension_items_->AppendExtensionItems(app_key, base::string16(), &index, + false); // is_action_menu + if (!features::IsTouchableAppContextMenuEnabled()) + menu_model->AddSeparator(ui::NORMAL_SEPARATOR); + } + } +} + extensions::LaunchType ExtensionLauncherContextMenu::GetLaunchType() const { const extensions::Extension* extension = GetExtensionForAppID(item().id.app_id, controller()->profile()); @@ -228,3 +249,10 @@ void ExtensionLauncherContextMenu::SetLaunchType(extensions::LaunchType type) { extensions::SetLaunchType(controller()->profile(), item().id.app_id, type); } + +int ExtensionLauncherContextMenu::GetLaunchTypeStringId() const { + return (GetLaunchType() == extensions::LAUNCH_TYPE_PINNED || + GetLaunchType() == extensions::LAUNCH_TYPE_REGULAR) + ? IDS_APP_LIST_CONTEXT_MENU_NEW_TAB + : IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW; +}
diff --git a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h index e726c2c9..c76200c 100644 --- a/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h +++ b/chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h
@@ -32,12 +32,22 @@ void ExecuteCommand(int command_id, int event_flags) override; private: + // Creates the actionable submenu for MENU_OPEN_NEW. + void CreateOpenNewSubmenu(ui::SimpleMenuModel* menu_model); + void BuildMenu(ui::SimpleMenuModel* menu_model); // Helpers to get and set the launch type for the extension item. extensions::LaunchType GetLaunchType() const; void SetLaunchType(extensions::LaunchType launch_type); + // Helper to get the launch type string id. + int GetLaunchTypeStringId() const; + + // The MenuModel used to control MENU_OPEN_NEW's icon, label, and + // execution when touchable app context menus are enabled. + std::unique_ptr<ui::SimpleMenuModel> open_new_submenu_model_; + std::unique_ptr<extensions::ContextMenuMatcher> extension_items_; DISALLOW_COPY_AND_ASSIGN(ExtensionLauncherContextMenu);
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc index e424877..1dc36a7 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -171,7 +171,7 @@ menu_config.touchable_icon_color)); return; } - // If the MenuType is a Check item. + // If the MenuType is a check item. if (type == LAUNCH_TYPE_REGULAR_TAB || type == LAUNCH_TYPE_PINNED_TAB || type == LAUNCH_TYPE_WINDOW || type == LAUNCH_TYPE_FULLSCREEN) { menu_model->AddCheckItemWithStringId(type, string_id);
diff --git a/chrome/browser/ui/ash/network/networking_config_delegate_chromeos_browsertest.cc b/chrome/browser/ui/ash/network/networking_config_delegate_chromeos_browsertest.cc index f845609..a6ed816 100644 --- a/chrome/browser/ui/ash/network/networking_config_delegate_chromeos_browsertest.cc +++ b/chrome/browser/ui/ash/network/networking_config_delegate_chromeos_browsertest.cc
@@ -20,7 +20,7 @@ namespace { -using NetworkingConfigDelegateChromeosTest = ExtensionBrowserTest; +using NetworkingConfigDelegateChromeosTest = extensions::ExtensionBrowserTest; // Tests that an extension registering itself as handling a Wi-Fi SSID updates // the ash system tray network item.
diff --git a/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc index f0a42cc..762d3ce 100644 --- a/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc
@@ -41,7 +41,7 @@ #include "chrome/browser/ui/blocked_content/framebust_block_tab_helper.h" #endif -class TabUnderBlockerBrowserTest : public ExtensionBrowserTest { +class TabUnderBlockerBrowserTest : public extensions::ExtensionBrowserTest { public: TabUnderBlockerBrowserTest() { EXPECT_CALL(provider_, IsInitializationComplete(testing::_)) @@ -52,7 +52,7 @@ ~TabUnderBlockerBrowserTest() override {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); scoped_feature_list_.InitAndEnableFeature( TabUnderNavigationThrottle::kBlockTabUnders); host_resolver()->AddRule("*", "127.0.0.1");
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index ee9ce25..5d9550d4 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -62,6 +62,7 @@ #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" #include "chrome/browser/ui/tabs/pinned_tab_codec.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/views_mode_controller.h" #include "chrome/common/buildflags.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -115,6 +116,7 @@ #include "net/test/spawned_test_server/spawned_test_server.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/page_transition_types.h" +#include "ui/base/ui_base_features.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -330,10 +332,10 @@ } // namespace -class BrowserTest : public ExtensionBrowserTest { +class BrowserTest : public extensions::ExtensionBrowserTest { protected: void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); } @@ -2626,6 +2628,12 @@ // Test to ensure the bounds of popup, devtool, and app windows are properly // restored. IN_PROC_BROWSER_TEST_F(BrowserTest, TestPopupBounds) { +#if BUILDFLAG(MAC_VIEWS_BROWSER) + // The size computation on popups is wrong in MacViews: + // https://crbug.com/834908. + if (!views_mode_controller::IsViewsBrowserCocoa()) + return; +#endif // TODO(tdanderson|pkasting): Change this to verify that the contents bounds // set by params.initial_bounds are the same as the contents bounds in the // initialized window. See crbug.com/585856.
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc index b171e8d..53044f1 100644 --- a/chrome/browser/ui/browser_list.cc +++ b/chrome/browser/ui/browser_list.cc
@@ -36,6 +36,15 @@ return browsers_to_close; } +BrowserList::BrowserVector GetIncognitoBrowsersToClose(Profile* profile) { + BrowserList::BrowserVector browsers_to_close; + for (auto* browser : *BrowserList::GetInstance()) { + if (browser->profile() == profile) + browsers_to_close.push_back(browser); + } + return browsers_to_close; +} + } // namespace // static @@ -154,6 +163,18 @@ } // static +void BrowserList::CloseAllBrowsersWithIncognitoProfile( + Profile* profile, + const CloseCallback& on_close_success, + const CloseCallback& on_close_aborted, + bool skip_beforeunload) { + DCHECK(profile->IsOffTheRecord()); + TryToCloseBrowserList(GetIncognitoBrowsersToClose(profile), on_close_success, + on_close_aborted, profile->GetPath(), + skip_beforeunload); +} + +// static void BrowserList::TryToCloseBrowserList(const BrowserVector& browsers_to_close, const CloseCallback& on_close_success, const CloseCallback& on_close_aborted,
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h index 80d883f..31248f31 100644 --- a/chrome/browser/ui/browser_list.h +++ b/chrome/browser/ui/browser_list.h
@@ -108,6 +108,14 @@ const CloseCallback& on_close_aborted, bool skip_beforeunload); + // Similarly to CloseAllBrowsersWithProfile, but DCHECK's that profile is + // Off-the-Record and doesn't close browsers with the original profile. + static void CloseAllBrowsersWithIncognitoProfile( + Profile* profile, + const CloseCallback& on_close_success, + const CloseCallback& on_close_aborted, + bool skip_beforeunload); + // Returns true if at least one incognito session is active across all // desktops. static bool IsIncognitoSessionActive();
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm index 72b15bc..a9370c5 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
@@ -557,15 +557,6 @@ EXPECT_EQ(can_fullscreen, !!([ns_window collectionBehavior] & NSWindowCollectionBehaviorFullScreenPrimary)); - // In OSX 10.10+, the zoom button performs the zoom action rather than the - // fullscreen action. The above check that collectionBehavior does not include - // NSWindowCollectionBehaviorFullScreenPrimary is sufficient to determine that - // the window can't be fullscreened. - if (base::mac::IsOS10_9()) { - EXPECT_EQ(can_fullscreen, - [[ns_window standardWindowButton:NSWindowZoomButton] isEnabled]); - } - // Set a maximum size. app_window->SetContentSizeConstraints(gfx::Size(), gfx::Size(200, 201)); EXPECT_EQ(200, [ns_window contentMaxSize].width);
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm index 4d51205..f54d688 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm
@@ -233,13 +233,13 @@ @end -class BrowserActionButtonUiTest : public ExtensionBrowserTest { +class BrowserActionButtonUiTest : public extensions::ExtensionBrowserTest { protected: BrowserActionButtonUiTest() {} ~BrowserActionButtonUiTest() override {} void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); toolbarController_ = [[BrowserWindowController browserWindowControllerForWindow:browser()-> @@ -251,13 +251,13 @@ } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); ToolbarActionsBar::disable_animations_for_testing_ = true; } void TearDownOnMainThread() override { ToolbarActionsBar::disable_animations_for_testing_ = false; - ExtensionBrowserTest::TearDownOnMainThread(); + extensions::ExtensionBrowserTest::TearDownOnMainThread(); } // Opens the app menu and the context menu of the overflowed action, and
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm index 836a0a41..3cc5324 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
@@ -360,9 +360,7 @@ } - (gfx::Size)preferredSize { - gfx::Size size = toolbarActionsBar_->GetFullSize(); - size.Enlarge(kBrowserActionHorizontalPadding * 2, 0); - return size; + return toolbarActionsBar_->GetFullSize(); } - (NSPoint)popupPointForId:(const std::string&)id {
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm index 722b757..60c6b53 100644 --- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm +++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
@@ -23,7 +23,6 @@ #import "ui/base/cocoa/menu_controller.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/resources/grit/ui_resources.h" #include "ui/strings/grit/ui_strings.h" @@ -197,42 +196,24 @@ } void RenderViewContextMenuMac::ExecuteCommand(int command_id, int event_flags) { - switch (command_id) { - case IDC_CONTENT_CONTEXT_EMOJI: - [NSApp orderFrontCharacterPalette:nil]; - RenderViewContextMenu::RecordUsedItem(command_id); - break; - - case IDC_CONTENT_CONTEXT_LOOK_UP: - LookUpInDictionary(); - break; - - default: - RenderViewContextMenu::ExecuteCommand(command_id, event_flags); - break; - } + if (command_id == IDC_CONTENT_CONTEXT_LOOK_UP) + LookUpInDictionary(); + else + RenderViewContextMenu::ExecuteCommand(command_id, event_flags); } bool RenderViewContextMenuMac::IsCommandIdChecked(int command_id) const { - if (command_id == IDC_CONTENT_CONTEXT_EMOJI || - command_id == IDC_CONTENT_CONTEXT_LOOK_UP) { + if (command_id == IDC_CONTENT_CONTEXT_LOOK_UP) return false; - } return RenderViewContextMenu::IsCommandIdChecked(command_id); } bool RenderViewContextMenuMac::IsCommandIdEnabled(int command_id) const { - switch (command_id) { - case IDC_CONTENT_CONTEXT_EMOJI: - return params_.is_editable; + if (command_id == IDC_CONTENT_CONTEXT_LOOK_UP) + return true; - case IDC_CONTENT_CONTEXT_LOOK_UP: - return true; - - default: - return RenderViewContextMenu::IsCommandIdEnabled(command_id); - } + return RenderViewContextMenu::IsCommandIdEnabled(command_id); } void RenderViewContextMenuMac::Show() { @@ -320,16 +301,17 @@ } void RenderViewContextMenuMac::InitToolkitMenu() { - if (params_.input_field_type == - blink::WebContextMenuData::kInputFieldTypePassword) + if (params_.selection_text.empty() || + params_.input_field_type == + blink::WebContextMenuData::kInputFieldTypePassword) return; - int index = 0; - if (!params_.selection_text.empty() && params_.link_url.is_empty()) { + if (params_.link_url.is_empty()) { // In case the user has selected a word that triggers spelling suggestions, // show the dictionary lookup under the group that contains the command to // “Add to Dictionary.” - index = menu_model_.GetIndexOfCommandId(IDC_SPELLCHECK_ADD_TO_DICTIONARY); + int index = + menu_model_.GetIndexOfCommandId(IDC_SPELLCHECK_ADD_TO_DICTIONARY); if (index < 0) { index = 0; } else { @@ -348,17 +330,6 @@ menu_model_.InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR); } - // The Emoji menu item is available for editable text fields, unless the - // selected text is a misspelling. - if (params_.is_editable && params_.misspelled_word.empty() && - base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu)) { - // The "Emoji" item is available near the top of the context menu, after - // any "Look Up" of selected text. - menu_model_.InsertItemWithStringIdAt(index++, IDC_CONTENT_CONTEXT_EMOJI, - IDS_CONTENT_CONTEXT_EMOJI); - menu_model_.InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR); - } - text_services_context_menu_.AppendToContextMenu(&menu_model_); }
diff --git a/chrome/browser/ui/cocoa/tabbed_browser_window.mm b/chrome/browser/ui/cocoa/tabbed_browser_window.mm index 864789d9..38163a1 100644 --- a/chrome/browser/ui/cocoa/tabbed_browser_window.mm +++ b/chrome/browser/ui/cocoa/tabbed_browser_window.mm
@@ -23,9 +23,6 @@ // window buttons (zoom, close, miniaturize). constexpr NSInteger kWindowButtonsOffsetFromBottom = 9; constexpr NSInteger kWindowButtonsOffsetFromLeft = 11; - -// Offset from the top/right of the window to the Mavericks full screen button. -constexpr NSInteger kFullScreenButtonOffset = 9; } // namespace @interface TabbedBrowserWindow () @@ -115,30 +112,6 @@ @end -@interface MavericksTabbedBrowserWindowFrame : FullSizeTabbedBrowserWindowFrame -@end - -@implementation MavericksTabbedBrowserWindowFrame - -// 10.10+ has no separate fullscreen button. -- (NSPoint)_fullScreenButtonOrigin - __attribute__((availability(macos, obsoleted = 10.10))) { - CGFloat xAdjustment = [static_cast<TabbedBrowserWindow*>(self.window) - fullScreenButtonOriginAdjustment]; - NSSize fullScreenButtonSize = [self fullScreenButton].frame.size; - return NSMakePoint(NSMaxX(self.bounds) - fullScreenButtonSize.width - - kFullScreenButtonOffset - xAdjustment, - NSMaxY(self.bounds) - fullScreenButtonSize.height - - kFullScreenButtonOffset); -} - -// 10.10+ adds the content view below the window controls by default. -- (void)_setContentView:(NSView*)contentView { - [self addSubview:contentView positioned:NSWindowBelow relativeTo:nil]; -} - -@end - @implementation TabbedBrowserWindow // FramedBrowserWindow overrides. @@ -158,12 +131,9 @@ // Because NSThemeFrame is imported weakly, if it's not present at runtime // then it and its subclasses will be nil. if ([TabbedBrowserWindowFrame class]) { - if (@available(macOS 10.10, *)) { - return chrome::ShouldUseFullSizeContentView() - ? [TabbedBrowserWindowFrame class] - : [FullSizeTabbedBrowserWindowFrame class]; - } - return [MavericksTabbedBrowserWindowFrame class]; + return chrome::ShouldUseFullSizeContentView() + ? [TabbedBrowserWindowFrame class] + : [FullSizeTabbedBrowserWindowFrame class]; } return [super frameViewClassForStyleMask:windowStyle]; }
diff --git a/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc b/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc index b2fb954..3ed7091 100644 --- a/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc +++ b/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc
@@ -20,7 +20,7 @@ #include "net/dns/mock_host_resolver.h" class ExtensionBlockedActionsBubbleTest - : public SupportsTestDialog<ExtensionBrowserTest> { + : public SupportsTestDialog<extensions::ExtensionBrowserTest> { public: ExtensionBlockedActionsBubbleTest(); ~ExtensionBlockedActionsBubbleTest() override; @@ -45,13 +45,13 @@ void ExtensionBlockedActionsBubbleTest::SetUpCommandLine( base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); scoped_feature_list_.InitAndEnableFeature( extensions::features::kRuntimeHostPermissions); } void ExtensionBlockedActionsBubbleTest::SetUpOnMainThread() { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); }
diff --git a/chrome/browser/ui/extensions/extension_enable_flow_browsertest.cc b/chrome/browser/ui/extensions/extension_enable_flow_browsertest.cc index 42604d74..e0a076cd 100644 --- a/chrome/browser/ui/extensions/extension_enable_flow_browsertest.cc +++ b/chrome/browser/ui/extensions/extension_enable_flow_browsertest.cc
@@ -74,7 +74,7 @@ } // namespace -using ExtensionEnableFlowBrowserTest = ExtensionBrowserTest; +using ExtensionEnableFlowBrowserTest = extensions::ExtensionBrowserTest; // Test that trying to enable an extension that's blocked by policy fails // gracefully. See https://crbug.com/783831.
diff --git a/chrome/browser/ui/extensions/extension_installed_bubble_browsertest.cc b/chrome/browser/ui/extensions/extension_installed_bubble_browsertest.cc index 7d0ccb65..bd39fd9 100644 --- a/chrome/browser/ui/extensions/extension_installed_bubble_browsertest.cc +++ b/chrome/browser/ui/extensions/extension_installed_bubble_browsertest.cc
@@ -29,7 +29,7 @@ using ActionType = extensions::ExtensionBuilder::ActionType; class ExtensionInstalledBubbleBrowserTest - : public SupportsTestDialog<ExtensionBrowserTest> { + : public SupportsTestDialog<extensions::ExtensionBrowserTest> { public: ExtensionInstalledBubbleBrowserTest() : disable_animations_(&ToolbarActionsBar::disable_animations_for_testing_,
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc index 302d1b2b..5cef54e 100644 --- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc +++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -211,7 +211,7 @@ // is a Hosted or Bookmark app. |desktop_pwa_flag| enables the // kDesktopPWAWindowing flag. class HostedAppTest - : public ExtensionBrowserTest, + : public extensions::ExtensionBrowserTest, public ::testing::WithParamInterface<std::tuple<AppType, bool>> { public: HostedAppTest() @@ -239,7 +239,7 @@ #endif } - ExtensionBrowserTest::SetUp(); + extensions::ExtensionBrowserTest::SetUp(); } protected: @@ -299,24 +299,24 @@ } void SetUpInProcessBrowserTestFixture() override { - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); ProfileIOData::SetCertVerifierForTesting(&mock_cert_verifier_); } void TearDownInProcessBrowserTestFixture() override { - ExtensionBrowserTest::TearDownInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::TearDownInProcessBrowserTestFixture(); ProfileIOData::SetCertVerifierForTesting(nullptr); } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); // Browser will both run and display insecure content. command_line->AppendSwitch(switches::kAllowRunningInsecureContent); command_line->AppendSwitch(switches::kUseMockCertVerifierForTesting); } void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); // By default, all SSL cert checks are valid. Can be overriden in tests. cert_verifier_.set_default_result(net::OK);
diff --git a/chrome/browser/ui/interventions/framebust_block_message_delegate.cc b/chrome/browser/ui/interventions/framebust_block_message_delegate.cc index 32b6d4e..d818ec1 100644 --- a/chrome/browser/ui/interventions/framebust_block_message_delegate.cc +++ b/chrome/browser/ui/interventions/framebust_block_message_delegate.cc
@@ -7,10 +7,16 @@ #include <memory> #include <utility> +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/web_contents.h" #include "content/public/common/referrer.h" #include "ui/base/page_transition_types.h" #include "ui/base/window_open_disposition.h" +#include "url/gurl.h" FramebustBlockMessageDelegate::FramebustBlockMessageDelegate( content::WebContents* web_contents, @@ -40,3 +46,14 @@ blocked_url_, content::Referrer(), WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_LINK, false)); } + +void FramebustBlockMessageDelegate::DeclineInterventionSticky() { + HostContentSettingsMap* settings_map = + HostContentSettingsMapFactory::GetForProfile( + Profile::FromBrowserContext(web_contents_->GetBrowserContext())); + DCHECK(settings_map); + settings_map->SetContentSettingDefaultScope( + web_contents_->GetLastCommittedURL(), GURL(), + CONTENT_SETTINGS_TYPE_POPUPS, std::string(), CONTENT_SETTING_ALLOW); + DeclineIntervention(); +}
diff --git a/chrome/browser/ui/interventions/framebust_block_message_delegate.h b/chrome/browser/ui/interventions/framebust_block_message_delegate.h index 25bb94e..b15b29a 100644 --- a/chrome/browser/ui/interventions/framebust_block_message_delegate.h +++ b/chrome/browser/ui/interventions/framebust_block_message_delegate.h
@@ -39,6 +39,7 @@ // InterventionDelegate: void AcceptIntervention() override; void DeclineIntervention() override; + void DeclineInterventionSticky() override; private: // Callback to be called when the user performs an action regarding this
diff --git a/chrome/browser/ui/interventions/intervention_delegate.h b/chrome/browser/ui/interventions/intervention_delegate.h index fddc5bc..234c596 100644 --- a/chrome/browser/ui/interventions/intervention_delegate.h +++ b/chrome/browser/ui/interventions/intervention_delegate.h
@@ -11,6 +11,10 @@ virtual void AcceptIntervention() = 0; virtual void DeclineIntervention() = 0; + // Called if the user declines the intervention in a sticky way. e.g. by + // indicating they always want to decline the intervention on the site. + virtual void DeclineInterventionSticky() = 0; + protected: virtual ~InterventionDelegate() = default; };
diff --git a/chrome/browser/ui/libgtkui/native_theme_gtk3.cc b/chrome/browser/ui/libgtkui/native_theme_gtk3.cc index 5ad8a7f..840112ad 100644 --- a/chrome/browser/ui/libgtkui/native_theme_gtk3.cc +++ b/chrome/browser/ui/libgtkui/native_theme_gtk3.cc
@@ -133,6 +133,9 @@ "GtkMenu#menu GtkSeparator#separator.horizontal"); } return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem.separator"); + case ui::NativeTheme::kColorId_TouchableMenuItemLabelColor: + case ui::NativeTheme::kColorId_ActionableSubmenuVerticalSeparatorColor: + return kInvalidColorIdColor; // Label case ui::NativeTheme::kColorId_LabelEnabledColor:
diff --git a/chrome/browser/ui/location_bar/location_bar_browsertest.cc b/chrome/browser/ui/location_bar/location_bar_browsertest.cc index 302848b..b0a24b8 100644 --- a/chrome/browser/ui/location_bar/location_bar_browsertest.cc +++ b/chrome/browser/ui/location_bar/location_bar_browsertest.cc
@@ -16,7 +16,7 @@ #include "extensions/common/feature_switch.h" #include "extensions/common/value_builder.h" -class LocationBarBrowserTest : public ExtensionBrowserTest { +class LocationBarBrowserTest : public extensions::ExtensionBrowserTest { public: LocationBarBrowserTest() {} ~LocationBarBrowserTest() override {} @@ -31,7 +31,7 @@ }; void LocationBarBrowserTest::SetUpCommandLine(base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); // In order to let a vanilla extension override the bookmark star, we have to // enable the switch.
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.h b/chrome/browser/ui/omnibox/chrome_omnibox_client.h index 5c42a15..0603ce2 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.h +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
@@ -14,9 +14,9 @@ #include "base/task/cancelable_task_tracker.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" -#include "chrome/browser/ui/omnibox/favicon_cache.h" #include "chrome/common/search/instant_types.h" #include "components/favicon_base/favicon_types.h" +#include "components/omnibox/browser/favicon_cache.h" #include "components/omnibox/browser/omnibox_client.h" class ChromeOmniboxEditController;
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc index 69fcd07..cb99057b6 100644 --- a/chrome/browser/ui/omnibox/omnibox_theme.cc +++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -190,7 +190,7 @@ switch (state) { case OmniboxPartState::CHIP_DEFAULT: - return gfx::kGoogleGrey800; + return gfx::kChromeIconGrey; case OmniboxPartState::CHIP_SECURE: return gfx::kGoogleGreen600; case OmniboxPartState::CHIP_DANGEROUS:
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/chrome/browser/ui/page_info/page_info_ui.cc index 4eb66e24..77c5011 100644 --- a/chrome/browser/ui/page_info/page_info_ui.cc +++ b/chrome/browser/ui/page_info/page_info_ui.cc
@@ -112,7 +112,13 @@ {CONTENT_SETTINGS_TYPE_COOKIES, 0}, {CONTENT_SETTINGS_TYPE_IMAGES, IDS_PAGE_INFO_TYPE_IMAGES}, {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_PAGE_INFO_TYPE_JAVASCRIPT}, +#if defined(OS_ANDROID) + {CONTENT_SETTINGS_TYPE_POPUPS, IDS_PAGE_INFO_TYPE_POPUPS_REDIRECTS}, +#else + // TODO(csharrison,ericrobinson): Use IDS_PAGE_INFO_TYPE_POPUPS_REDIRECTS on + // desktop as well. {CONTENT_SETTINGS_TYPE_POPUPS, IDS_PAGE_INFO_TYPE_POPUPS}, +#endif #if BUILDFLAG(ENABLE_PLUGINS) {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_PAGE_INFO_TYPE_FLASH}, #endif
diff --git a/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.h b/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.h index 3f36d3a..df208dad 100644 --- a/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.h +++ b/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.h
@@ -43,7 +43,7 @@ // Use this class to test on a default window or an app window. Inheriting from // ExtensionBrowserTest allows us to easily load and launch apps, and doesn't // really add any extra work. -class PermissionBubbleBrowserTest : public ExtensionBrowserTest { +class PermissionBubbleBrowserTest : public extensions::ExtensionBrowserTest { public: PermissionBubbleBrowserTest(); ~PermissionBubbleBrowserTest() override;
diff --git a/chrome/browser/ui/search/instant_theme_browsertest.cc b/chrome/browser/ui/search/instant_theme_browsertest.cc index d045d5e3..7f55eb9 100644 --- a/chrome/browser/ui/search/instant_theme_browsertest.cc +++ b/chrome/browser/ui/search/instant_theme_browsertest.cc
@@ -24,7 +24,8 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" -class InstantThemeTest : public ExtensionBrowserTest, public InstantTestBase { +class InstantThemeTest : public extensions::ExtensionBrowserTest, + public InstantTestBase { public: InstantThemeTest() {} @@ -37,7 +38,7 @@ } void SetUpOnMainThread() override { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); content::URLDataSource::Add(profile(), new ThemeSource(profile())); } @@ -58,7 +59,7 @@ content::Source<ThemeService>( ThemeServiceFactory::GetForProfile(profile()))); ASSERT_TRUE(InstallExtensionWithUIAutoConfirm( - theme_path, 1, ExtensionBrowserTest::browser())); + theme_path, 1, extensions::ExtensionBrowserTest::browser())); theme_change_observer.Wait(); size_t num_after = extensions::ExtensionRegistry::Get(profile()) ->enabled_extensions()
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index 87c14a4..c2fa7d20 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -152,16 +152,16 @@ } // namespace -class StartupBrowserCreatorTest : public ExtensionBrowserTest { +class StartupBrowserCreatorTest : public extensions::ExtensionBrowserTest { protected: StartupBrowserCreatorTest() {} bool SetUpUserDataDirectory() override { - return ExtensionBrowserTest::SetUpUserDataDirectory(); + return extensions::ExtensionBrowserTest::SetUpUserDataDirectory(); } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII(switches::kHomePage, url::kAboutBlankURL); #if defined(OS_CHROMEOS) // TODO(nkostylev): Investigate if we can remove this switch.
diff --git a/chrome/browser/ui/tabs/tab_ukm_test_helper.cc b/chrome/browser/ui/tabs/tab_ukm_test_helper.cc index b8e590b..e323235 100644 --- a/chrome/browser/ui/tabs/tab_ukm_test_helper.cc +++ b/chrome/browser/ui/tabs/tab_ukm_test_helper.cc
@@ -81,8 +81,8 @@ ukm_recorder_.GetEntriesByName(entry_name)[first_unexpected_index]; std::ostringstream entry_metrics; - for (const ukm::mojom::UkmMetricPtr& metric : ukm_entry->metrics) - entry_metrics << "\n" << metric->metric_hash << ": " << metric->value; + for (const auto& metric : ukm_entry->metrics) + entry_metrics << "\n" << metric.first << ": " << metric.second; LOG(ERROR) << "First unexpected entry: " << entry_metrics.str(); } }
diff --git a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc index 97e7856e..3e00fdc 100644 --- a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc +++ b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
@@ -67,19 +67,19 @@ void BrowserActionsBarBrowserTest::SetUpCommandLine( base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); ToolbarActionsBar::disable_animations_for_testing_ = true; } void BrowserActionsBarBrowserTest::SetUpOnMainThread() { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); browser_actions_bar_ = BrowserActionTestUtil::Create(browser()); toolbar_model_ = ToolbarActionsModel::Get(profile()); } void BrowserActionsBarBrowserTest::TearDownOnMainThread() { ToolbarActionsBar::disable_animations_for_testing_ = false; - ExtensionBrowserTest::TearDownOnMainThread(); + extensions::ExtensionBrowserTest::TearDownOnMainThread(); } void BrowserActionsBarBrowserTest::LoadExtensions() {
diff --git a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.h b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.h index 08fe6fb..4a8690a9 100644 --- a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.h +++ b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.h
@@ -19,7 +19,7 @@ class ToolbarActionsModel; // A platform-independent browser test class for the browser actions bar. -class BrowserActionsBarBrowserTest : public ExtensionBrowserTest { +class BrowserActionsBarBrowserTest : public extensions::ExtensionBrowserTest { protected: BrowserActionsBarBrowserTest(); ~BrowserActionsBarBrowserTest() override;
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc index c9e15e17..e9f2e213 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -188,6 +188,9 @@ ->mus_properties[ui::mojom::WindowManager::kShelfItemType_Property] = mojo::ConvertTo<std::vector<uint8_t>>( static_cast<int64_t>(ash::TYPE_APP)); + init_params + ->mus_properties[ui::mojom::WindowManager::kWindowTitleShown_Property] = + mojo::ConvertTo<std::vector<uint8_t>>(static_cast<int64_t>(false)); } void ChromeNativeAppWindowViewsAuraAsh::OnBeforePanelWidgetInit(
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc index 16f8c78..1aa3804 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -4,146 +4,65 @@ #include "chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h" +#include <algorithm> + #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/autofill/autofill_popup_controller.h" #include "chrome/browser/ui/autofill/autofill_popup_layout_model.h" +#include "chrome/browser/ui/views/harmony/chrome_typography.h" +#include "chrome/browser/ui/views/harmony/harmony_typography_provider.h" #include "components/autofill/core/browser/popup_item_ids.h" #include "components/autofill/core/browser/suggestion.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/font.h" #include "ui/native_theme/native_theme.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" +#include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" -#include "ui/views/layout/grid_layout.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/style/typography.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" -#include <algorithm> - namespace { -// Padding values for the entire dropdown. -const int kPopupTopBottomPadding = 8; -const int kPopupSidePadding = 0; - -// Padding values and dimensions for rows. -const int kRowHeight = 28; -const int kRowTopBottomPadding = 0; -// Used for padding on sides of rows, as well as minimum spacing between -// items inside of rows. -const int kRowHorizontalSpacing = 16; - -// Padding values specific to the separator row. -const int kSeparatorTopBottomPadding = 4; -const int kSeparatorSidePadding = 0; - // By spec, dropdowns should have a min width of 64, and should always have -// a width which is a multiple of 16. -const int kDropdownWidthMultiple = 16; +// a width which is a multiple of 12. +const int kDropdownWidthMultiple = 12; const int kDropdownMinWidth = 64; +// TODO(crbug.com/768881): Determine how colors should be shared with menus +// and/or omnibox, and how these should interact (if at all) with native +// theme colors. +const SkColor kBackgroundColor = SK_ColorWHITE; +const SkColor kSelectedBackgroundColor = gfx::kGoogleGrey200; +const SkColor kFooterBackgroundColor = gfx::kGoogleGrey050; +const SkColor kSeparatorColor = gfx::kGoogleGrey200; + } // namespace namespace autofill { -AutofillPopupRowView::AutofillPopupRowView(AutofillPopupController* controller, - int line_number) - : controller_(controller), line_number_(line_number) { - int frontend_id = controller_->GetSuggestionAt(line_number_).frontend_id; - is_separator_ = frontend_id == autofill::POPUP_ITEM_ID_SEPARATOR; - is_warning_ = - frontend_id == - autofill::POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE; +namespace { - SetFocusBehavior(is_separator_ ? FocusBehavior::NEVER - : FocusBehavior::ALWAYS); - CreateContent(); -} +// This represents a single selectable item. Subclasses distinguish between +// footer and suggestion rows, which are structurally similar but have +// distinct styling. +class AutofillPopupItemView : public AutofillPopupRowView { + public: + ~AutofillPopupItemView() override = default; -void AutofillPopupRowView::AcceptSelection() { - controller_->AcceptSuggestion(line_number_); -} + // views::View: + void GetAccessibleNodeData(ui::AXNodeData* node_data) override { + node_data->SetName(controller_->GetSuggestionAt(line_number_).value); -void AutofillPopupRowView::SetSelected(bool is_selected) { - if (is_selected == is_selected_) - return; - - is_selected_ = is_selected; - NotifyAccessibilityEvent(ax::mojom::Event::kFocus, true); - RefreshStyle(); -} - -void AutofillPopupRowView::RefreshStyle() { - // Only content rows, not separators, can be highlighted/selected. - DCHECK(!is_separator_); - - SetBackground(views::CreateThemedSolidBackground( - this, is_selected_ - ? ui::NativeTheme::kColorId_ResultsTableSelectedBackground - : ui::NativeTheme::kColorId_ResultsTableNormalBackground)); - - if (text_label_) { - text_label_->SetEnabledColor(is_selected_ ? text_selected_color_ - : text_color_); - } - - if (subtext_label_) { - subtext_label_->SetEnabledColor(is_selected_ ? subtext_selected_color_ - : subtext_color_); - } -} - -void AutofillPopupRowView::OnMouseEntered(const ui::MouseEvent& event) { - controller_->SetSelectedLine(line_number_); -} - -void AutofillPopupRowView::OnMouseReleased(const ui::MouseEvent& event) { - // Clicking a separator should not trigger any events, so we return early. - if (is_separator_) - return; - - if (event.IsOnlyLeftMouseButton() && HitTestPoint(event.location())) - AcceptSelection(); -} - -bool AutofillPopupRowView::OnMouseDragged(const ui::MouseEvent& event) { - return true; -} - -bool AutofillPopupRowView::OnMousePressed(const ui::MouseEvent& event) { - return true; -} - -void AutofillPopupRowView::OnNativeThemeChanged(const ui::NativeTheme* theme) { - if (is_separator_) - return; - - text_color_ = theme->GetSystemColor( - is_warning_ ? ui::NativeTheme::kColorId_ResultsTableNegativeText - : ui::NativeTheme::kColorId_ResultsTableNormalText); - text_selected_color_ = theme->GetSystemColor( - is_warning_ ? ui::NativeTheme::kColorId_ResultsTableNegativeSelectedText - : ui::NativeTheme::kColorId_ResultsTableSelectedText); - - subtext_color_ = theme->GetSystemColor( - ui::NativeTheme::kColorId_ResultsTableNormalDimmedText); - subtext_selected_color_ = theme->GetSystemColor( - ui::NativeTheme::kColorId_ResultsTableSelectedDimmedText); - - RefreshStyle(); -} - -void AutofillPopupRowView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - node_data->SetName(controller_->GetSuggestionAt(line_number_).value); - - if (is_separator_) { - // Separators are not selectable. - node_data->role = ax::mojom::Role::kSplitter; - } else { // Options are selectable. node_data->role = ax::mojom::Role::kMenuItem; node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, @@ -164,60 +83,249 @@ node_data->AddIntAttribute(ax::mojom::IntAttribute::kSetSize, set_size); node_data->AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, pos_in_set); } + + void OnMouseEntered(const ui::MouseEvent& event) override { + controller_->SetSelectedLine(line_number_); + } + + void OnMouseReleased(const ui::MouseEvent& event) override { + if (event.IsOnlyLeftMouseButton() && HitTestPoint(event.location())) + controller_->AcceptSuggestion(line_number_); + } + + protected: + AutofillPopupItemView(AutofillPopupController* controller, int line_number) + : AutofillPopupRowView(controller, line_number) {} + + // AutofillPopupRowView: + void CreateContent() override { + auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, + gfx::Insets(0, views::MenuConfig::instance().item_left_margin))); + + layout->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER); + layout->set_minimum_cross_axis_size( + views::MenuConfig::instance().touchable_menu_height); + + // TODO(crbug.com/831603): Remove elision responsibilities from controller. + text_label_ = new views::Label( + controller_->GetElidedValueAt(line_number_), + {views::style::GetFont(ChromeTextContext::CONTEXT_BODY_TEXT_LARGE, + views::style::TextStyle::STYLE_PRIMARY)}); + + AddChildView(text_label_); + + auto* spacer = new views::View; + spacer->SetPreferredSize(gfx::Size( + views::MenuConfig::instance().label_to_minor_text_padding, 1)); + AddChildView(spacer); + layout->SetFlexForView(spacer, /*flex*/ 1); + + const base::string16& description_text = + controller_->GetElidedLabelAt(line_number_); + if (!description_text.empty()) { + subtext_label_ = new views::Label( + description_text, + {views::style::GetFont(ChromeTextContext::CONTEXT_BODY_TEXT_LARGE, + ChromeTextStyle::STYLE_HINT)}); + + AddChildView(subtext_label_); + } + + const gfx::ImageSkia icon = + controller_->layout_model().GetIconImage(line_number_); + if (!icon.isNull()) { + auto* image_view = new views::ImageView(); + image_view->SetImage(icon); + + image_view->SetBorder(views::CreateEmptyBorder( + 0, views::MenuConfig::instance().icon_to_label_padding, 0, 0)); + AddChildView(image_view); + } + } + + void RefreshStyle() override { + SetBackground(CreateBackground()); + + if (text_label_) { + int text_style = is_warning_ ? ChromeTextStyle::STYLE_RED + : views::style::TextStyle::STYLE_PRIMARY; + + text_label_->SetEnabledColor(views::style::GetColor( + *this, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE, text_style)); + } + + if (subtext_label_) { + SkColor secondary = views::style::GetColor( + *this, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE, + ChromeTextStyle::STYLE_HINT); + subtext_label_->SetEnabledColor(secondary); + } + + SchedulePaint(); + } + + private: + views::Label* text_label_ = nullptr; + views::Label* subtext_label_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(AutofillPopupItemView); +}; + +class AutofillPopupSuggestionView : public AutofillPopupItemView { + public: + ~AutofillPopupSuggestionView() override = default; + + static AutofillPopupSuggestionView* Create( + AutofillPopupController* controller, + int line_number) { + AutofillPopupSuggestionView* result = + new AutofillPopupSuggestionView(controller, line_number); + result->Init(); + return result; + } + + protected: + // AutofillPopupRowView: + std::unique_ptr<views::Background> CreateBackground() override { + return views::CreateSolidBackground(is_selected_ ? kSelectedBackgroundColor + : kBackgroundColor); + } + + private: + AutofillPopupSuggestionView(AutofillPopupController* controller, + int line_number) + : AutofillPopupItemView(controller, line_number) { + SetFocusBehavior(FocusBehavior::ALWAYS); + } + + DISALLOW_COPY_AND_ASSIGN(AutofillPopupSuggestionView); +}; + +class AutofillPopupFooterView : public AutofillPopupItemView { + public: + ~AutofillPopupFooterView() override = default; + + static AutofillPopupFooterView* Create(AutofillPopupController* controller, + int line_number) { + AutofillPopupFooterView* result = + new AutofillPopupFooterView(controller, line_number); + result->Init(); + return result; + } + + protected: + // AutofillPopupRowView: + std::unique_ptr<views::Background> CreateBackground() override { + return views::CreateSolidBackground(is_selected_ ? kSelectedBackgroundColor + : kFooterBackgroundColor); + } + + private: + AutofillPopupFooterView(AutofillPopupController* controller, int line_number) + : AutofillPopupItemView(controller, line_number) { + SetFocusBehavior(FocusBehavior::ALWAYS); + } + + DISALLOW_COPY_AND_ASSIGN(AutofillPopupFooterView); +}; + +class AutofillPopupSeparatorView : public AutofillPopupRowView { + public: + ~AutofillPopupSeparatorView() override = default; + + static AutofillPopupSeparatorView* Create(AutofillPopupController* controller, + int line_number) { + AutofillPopupSeparatorView* result = + new AutofillPopupSeparatorView(controller, line_number); + result->Init(); + return result; + } + + // views::View: + void GetAccessibleNodeData(ui::AXNodeData* node_data) override { + // Separators are not selectable. + node_data->role = ax::mojom::Role::kSplitter; + } + + void OnMouseEntered(const ui::MouseEvent& event) override {} + void OnMouseReleased(const ui::MouseEvent& event) override {} + void OnNativeThemeChanged(const ui::NativeTheme* theme) override { + RefreshStyle(); + } + + protected: + // AutofillPopupRowView: + void CreateContent() override { + SetLayoutManager(std::make_unique<views::FillLayout>()); + + // In order to draw the horizontal line for the separator, create an empty + // view which matches the width of the parent (by using full flex) and has a + // height equal to the desired padding, then paint a border on the bottom. + empty_ = new views::View(); + empty_->SetPreferredSize( + gfx::Size(1, views::MenuConfig::instance().menu_vertical_border_size)); + AddChildView(empty_); + } + + void RefreshStyle() override { + empty_->SetBorder(views::CreateSolidSidedBorder( + /*top=*/0, + /*left=*/0, + /*bottom=*/views::MenuConfig::instance().separator_thickness, + /*right=*/0, + /*color=*/kSeparatorColor)); + SchedulePaint(); + } + + std::unique_ptr<views::Background> CreateBackground() override { + return views::CreateSolidBackground(SK_ColorWHITE); + } + + private: + AutofillPopupSeparatorView(AutofillPopupController* controller, + int line_number) + : AutofillPopupRowView(controller, line_number) { + SetFocusBehavior(FocusBehavior::NEVER); + } + + views::View* empty_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(AutofillPopupSeparatorView); +}; + +} // namespace + +void AutofillPopupRowView::SetSelected(bool is_selected) { + if (is_selected == is_selected_) + return; + + is_selected_ = is_selected; + NotifyAccessibilityEvent(ax::mojom::Event::kFocus, true); + RefreshStyle(); } -void AutofillPopupRowView::CreateContent() { - if (is_separator_) { - views::BoxLayout* layout = - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::kVertical, - gfx::Insets(kSeparatorTopBottomPadding, kSeparatorSidePadding))); - layout->set_main_axis_alignment( - views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); - AddChildView(new views::Separator()); - return; - } +bool AutofillPopupRowView::OnMouseDragged(const ui::MouseEvent& event) { + return true; +} - auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::kHorizontal, - gfx::Insets(kRowTopBottomPadding, kRowHorizontalSpacing))); +bool AutofillPopupRowView::OnMousePressed(const ui::MouseEvent& event) { + return true; +} - layout->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER); - layout->set_minimum_cross_axis_size(kRowHeight); +AutofillPopupRowView::AutofillPopupRowView(AutofillPopupController* controller, + int line_number) + : controller_(controller), line_number_(line_number) { + int frontend_id = controller_->GetSuggestionAt(line_number_).frontend_id; + is_warning_ = + frontend_id == + autofill::POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE; +} - const gfx::ImageSkia icon = - controller_->layout_model().GetIconImage(line_number_); - if (!icon.isNull()) { - auto* image_view = new views::ImageView(); - image_view->SetImage(icon); - image_view->SetBorder( - views::CreateEmptyBorder(0, 0, 0, kRowHorizontalSpacing / 2)); - AddChildView(image_view); - } - - // TODO(tmartino): Remove elision, font list, and font color - // responsibilities from controller. - text_label_ = new views::Label( - controller_->GetElidedValueAt(line_number_), - {controller_->layout_model().GetValueFontListForRow(line_number_)}); - - AddChildView(text_label_); - - auto* spacer = new views::View; - spacer->SetPreferredSize(gfx::Size(kRowHorizontalSpacing, 1)); - AddChildView(spacer); - layout->SetFlexForView(spacer, /*flex*/ 1); - - const base::string16& description_text = - controller_->GetElidedLabelAt(line_number_); - if (!description_text.empty()) { - subtext_label_ = new views::Label( - description_text, - {controller_->layout_model().GetLabelFontListForRow(line_number_)}); - - AddChildView(subtext_label_); - } +void AutofillPopupRowView::Init() { + CreateContent(); + RefreshStyle(); } AutofillPopupViewNativeViews::AutofillPopupViewNativeViews( @@ -225,15 +333,17 @@ views::Widget* parent_widget) : AutofillPopupBaseView(controller, parent_widget), controller_(controller) { + // TODO(crbug.com/768881): kPopupTopBottomPadding is not needed on the bottom + // when a footer is present. views::BoxLayout* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, - gfx::Insets(kPopupTopBottomPadding, kPopupSidePadding))); + gfx::Insets(views::MenuConfig::instance().menu_vertical_border_size, + 0))); layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); CreateChildViews(); - SetBackground(views::CreateThemedSolidBackground( - this, ui::NativeTheme::kColorId_ResultsTableNormalBackground)); + SetBackground(views::CreateSolidBackground(kBackgroundColor)); } AutofillPopupViewNativeViews::~AutofillPopupViewNativeViews() {} @@ -297,7 +407,17 @@ RemoveAllChildViews(true /* delete_children */); rows_.clear(); for (int i = 0; i < controller_->GetLineCount(); ++i) { - rows_.push_back(new AutofillPopupRowView(controller_, i)); + switch (controller_->GetSuggestionAt(i).frontend_id) { + case autofill::PopupItemId::POPUP_ITEM_ID_SEPARATOR: + rows_.push_back(AutofillPopupSeparatorView::Create(controller_, i)); + break; + case autofill::PopupItemId::POPUP_ITEM_ID_CLEAR_FORM: + case autofill::PopupItemId::POPUP_ITEM_ID_AUTOFILL_OPTIONS: + rows_.push_back(AutofillPopupFooterView::Create(controller_, i)); + break; + default: + rows_.push_back(AutofillPopupSuggestionView::Create(controller_, i)); + } AddChildView(rows_.back()); } } @@ -305,11 +425,11 @@ void AutofillPopupViewNativeViews::DoUpdateBoundsAndRedrawPopup() { SizeToPreferredSize(); - // TODO(tmartino): Currently, we rely on the delegate bounds to provide the - // origin. The size included in these bounds, however, is not relevant since - // this Views-based implementation can provide its own appropriate width and - // height. In the future, we should be able to drop the size calculation - // logic from the delegate. + // TODO(crbug.com/831603): Currently, we rely on the delegate bounds to + // provide the origin. The size included in these bounds, however, is not + // relevant since this Views-based implementation can provide its own + // appropriate width and height. In the future, we should be able to drop the + // size calculation logic from the delegate. gfx::Rect bounds(delegate()->popup_bounds().origin(), size()); // The Widget's bounds need to account for the border.
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h index 49f4c55..e3e07b25 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
@@ -9,60 +9,47 @@ #include "base/optional.h" #include "chrome/browser/ui/autofill/autofill_popup_view.h" #include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h" -#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/color_palette.h" +#include "ui/gfx/font_list.h" +#include <memory> #include <vector> -namespace views { -class Label; -} - namespace autofill { class AutofillPopupController; -// Child view representing one row (i.e., one suggestion) in the Autofill -// Popup. +// Child view representing one row in the Autofill Popup. This could represent +// a UI control (e.g., a suggestion which can be autofilled), or decoration like +// separators. class AutofillPopupRowView : public views::View { public: - AutofillPopupRowView(AutofillPopupController* controller, int line_number); - - ~AutofillPopupRowView() override {} - - void AcceptSelection(); + ~AutofillPopupRowView() override = default; void SetSelected(bool is_selected); - void RefreshStyle(); // views::View: - // TODO(tmartino): Consolidate and deprecate code in AutofillPopupBaseView - // where overlap exists with these events. - void OnMouseEntered(const ui::MouseEvent& event) override; - void OnMouseReleased(const ui::MouseEvent& event) override; + // Drags and presses on any row should be a no-op; subclasses instead rely on + // entry/release events. Returns true to indicate that those events have been + // processed (i.e., intentionally ignored). bool OnMouseDragged(const ui::MouseEvent& event) override; bool OnMousePressed(const ui::MouseEvent& event) override; - void OnNativeThemeChanged(const ui::NativeTheme* theme) override; - private: - // views::View: - void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - void CreateContent(); + protected: + AutofillPopupRowView(AutofillPopupController* controller, int line_number); + + // Init handles initialization tasks which require virtual methods. Subclasses + // should have private/protected constructors and implement a static Create + // method which calls Init before returning. + void Init(); + + virtual void CreateContent() = 0; + virtual void RefreshStyle() = 0; + virtual std::unique_ptr<views::Background> CreateBackground() = 0; AutofillPopupController* controller_; const int line_number_; - bool is_separator_ = false; // overwritten in ctor - bool is_warning_ = false; // overwritten in ctor + bool is_warning_ = false; // overwritten in ctor bool is_selected_ = false; - - views::Label* text_label_ = nullptr; - views::Label* subtext_label_ = nullptr; - - SkColor text_color_ = gfx::kPlaceholderColor; - SkColor text_selected_color_ = gfx::kPlaceholderColor; - SkColor subtext_color_ = gfx::kPlaceholderColor; - SkColor subtext_selected_color_ = gfx::kPlaceholderColor; - - DISALLOW_COPY_AND_ASSIGN(AutofillPopupRowView); }; // Views implementation for the autofill and password suggestion. @@ -91,9 +78,9 @@ gfx::Size CalculatePreferredSize() const override; // AutofillPopupBaseView: - // TODO(tmartino): Remove these overrides and the corresponding methods in - // AutofillPopupBaseView once deprecation of AutofillPopupViewViews is - // complete. + // TODO(crbug.com/831603): Remove these overrides and the corresponding + // methods in AutofillPopupBaseView once deprecation of + // AutofillPopupViewViews is complete. void OnMouseExited(const ui::MouseEvent& event) override {} void OnMouseMoved(const ui::MouseEvent& event) override {}
diff --git a/chrome/browser/ui/views/extensions/extension_dialog_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extension_dialog_interactive_uitest.cc index 6ae5fab..c7b7f89b 100644 --- a/chrome/browser/ui/views/extensions/extension_dialog_interactive_uitest.cc +++ b/chrome/browser/ui/views/extensions/extension_dialog_interactive_uitest.cc
@@ -15,7 +15,7 @@ namespace { -class ExtensionDialogUiTest : public ExtensionBrowserTest { +class ExtensionDialogUiTest : public extensions::ExtensionBrowserTest { public: ExtensionDialogUiTest() = default; ~ExtensionDialogUiTest() override = default;
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc index 157755c..4b33dde9 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
@@ -45,7 +45,8 @@ using extensions::PermissionMessage; using extensions::PermissionMessages; -class ExtensionInstallDialogViewTestBase : public ExtensionBrowserTest { +class ExtensionInstallDialogViewTestBase + : public extensions::ExtensionBrowserTest { protected: ExtensionInstallDialogViewTestBase(); @@ -68,9 +69,9 @@ : extension_(nullptr), web_contents_(nullptr) {} void ExtensionInstallDialogViewTestBase::SetUpOnMainThread() { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); - extension_ = ExtensionBrowserTest::LoadExtension(test_data_dir_.AppendASCII( + extension_ = LoadExtension(test_data_dir_.AppendASCII( "install_prompt/permissions_scrollbar_regression")); web_contents_ = browser()->tab_strip_model()->GetWebContentsAt(0);
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc index 8d7793f..1f74adf9 100644 --- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
@@ -308,10 +308,8 @@ void ShowUi(const std::string& name) override { extensions::ExtensionBuilder extension_builder("ExtensionForRemoval"); if (extension_origin_ == EXTENSION_FROM_WEBSTORE) { - extensions::DictionaryBuilder update_url; - update_url.Set("update_url", - extension_urls::GetWebstoreUpdateUrl().spec()); - extension_builder.MergeManifest(update_url.Build()); + extension_builder.SetManifestKey( + "update_url", extension_urls::GetWebstoreUpdateUrl().spec()); } extension_ = extension_builder.Build();
diff --git a/chrome/browser/ui/views/frame/DEPS b/chrome/browser/ui/views/frame/DEPS new file mode 100644 index 0000000..1cad5de --- /dev/null +++ b/chrome/browser/ui/views/frame/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + # This class is only used in classic Ash. + "browser_non_client_frame_view_ash\.*": [ + "+ash", + ], +}
diff --git a/chrome/browser/ui/views/frame/browser_frame_mus.cc b/chrome/browser/ui/views/frame/browser_frame_mus.cc index af8d7e4..936b0a7f 100644 --- a/chrome/browser/ui/views/frame/browser_frame_mus.cc +++ b/chrome/browser/ui/views/frame/browser_frame_mus.cc
@@ -52,7 +52,6 @@ params.delegate = browser_view_; std::map<std::string, std::vector<uint8_t>> properties = views::MusClient::ConfigurePropertiesFromParams(params); - const std::string chrome_app_id(extension_misc::kChromeAppId); // Indicates mash shouldn't handle immersive, rather we will. properties[ui::mojom::WindowManager::kDisableImmersive_InitProperty] = mojo::ConvertTo<std::vector<uint8_t>>(true); @@ -66,6 +65,9 @@ properties[ui::mojom::WindowManager::kShelfItemType_Property] = mojo::ConvertTo<std::vector<uint8_t>>( static_cast<int64_t>(ash::TYPE_BROWSER_SHORTCUT)); + properties[ui::mojom::WindowManager::kWindowTitleShown_Property] = + mojo::ConvertTo<std::vector<uint8_t>>( + static_cast<int64_t>(browser_view_->ShouldShowWindowTitle())); // TODO(estade): to match classic Ash, this property should be toggled to true // for non-popups after the window is initially shown.
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index b5a40a3..f9629a6 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -39,7 +39,6 @@ #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/frame/browser_frame.h" #include "chrome/browser/ui/views/frame/browser_frame_ash.h" -#include "chrome/browser/ui/views/frame/browser_frame_header_ash.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" @@ -439,7 +438,7 @@ } /////////////////////////////////////////////////////////////////////////////// -// BrowserFrameHeaderAsh::AppearanceProvider: +// ash::CustomFrameHeader::AppearanceProvider: SkColor BrowserNonClientFrameViewAsh::GetFrameHeaderColor(bool active) { return GetFrameColor(active); @@ -640,71 +639,72 @@ std::unique_ptr<ash::FrameHeader> BrowserNonClientFrameViewAsh::CreateFrameHeader() { + std::unique_ptr<ash::FrameHeader> header; + Browser* browser = browser_view()->browser(); if (!UsePackagedAppHeaderStyle()) { - auto browser_frame_header = std::make_unique<BrowserFrameHeaderAsh>(); - browser_frame_header->Init( - this, this, !browser_view()->IsRegularOrGuestSession(), window_icon_, - caption_button_container_, back_button_); - return browser_frame_header; - } - std::unique_ptr<ash::DefaultFrameHeader> default_frame_header = - std::make_unique<ash::DefaultFrameHeader>(frame(), this, - caption_button_container_); + auto browser_frame_header = std::make_unique<ash::CustomFrameHeader>(); + browser_frame_header->Init(this, this, + !browser_view()->IsRegularOrGuestSession(), + caption_button_container_); + header = std::move(browser_frame_header); + } else { + std::unique_ptr<ash::DefaultFrameHeader> default_frame_header = + std::make_unique<ash::DefaultFrameHeader>(frame(), this, + caption_button_container_); + // TODO(alancutter): Move this branch into a new HostedAppFrameHeader class. + if (extensions::HostedAppBrowserController:: + IsForExperimentalHostedAppBrowser(browser)) { + SkColor active_color = ash::FrameCaptionButton::GetButtonColor( + ash::FrameCaptionButton::ColorMode::kDefault, + ash::DefaultFrameHeader::GetDefaultFrameColor()); - // TODO(alancutter): Move this branch into a new HostedAppFrameHeader class. - if (extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser( - browser)) { - // Hosted apps apply a theme color if specified by the extension. - base::Optional<SkColor> theme_color = - browser->hosted_app_controller()->GetThemeColor(); - if (theme_color) { - SkColor opaque_theme_color = - SkColorSetA(theme_color.value(), SK_AlphaOPAQUE); - default_frame_header->SetThemeColor(opaque_theme_color); + // Hosted apps apply a theme color if specified by the extension. + base::Optional<SkColor> theme_color = + browser->hosted_app_controller()->GetThemeColor(); + if (theme_color) { + theme_color = SkColorSetA(theme_color.value(), SK_AlphaOPAQUE); + default_frame_header->SetThemeColor(*theme_color); + active_color = ash::FrameCaptionButton::GetButtonColor( + ash::FrameCaptionButton::ColorMode::kThemed, *theme_color); + } + + // Add the container for extra hosted app buttons (e.g app menu button). + const float inactive_alpha_ratio = + ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio(); + SkColor inactive_color = + SkColorSetA(active_color, 255 * inactive_alpha_ratio); + hosted_app_button_container_ = new HostedAppButtonContainer( + browser_view(), active_color, inactive_color); + caption_button_container_->AddChildViewAt(hosted_app_button_container_, + 0); + + // Add the origin text. + frame_header_origin_text_ = + std::make_unique<ash::FrameHeaderOriginText>( + browser->hosted_app_controller()->GetFormattedUrlOrigin(), + active_color, inactive_color) + .release(); + AddChildView(frame_header_origin_text_); + + // Schedule the title bar animation. + constexpr base::TimeDelta kTitlebarAnimationDelay = + base::TimeDelta::FromMilliseconds(750); + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation, + weak_factory_.GetWeakPtr()), + kTitlebarAnimationDelay); + } else if (!browser->is_app()) { + default_frame_header->SetFrameColors(BrowserFrameAsh::kMdWebUiFrameColor, + BrowserFrameAsh::kMdWebUiFrameColor); } - - // Add the container for extra hosted app buttons (e.g app menu button). - SkColor active_color = ash::FrameCaptionButton::GetButtonColor( - theme_color ? ash::FrameCaptionButton::ColorMode::kThemed - : ash::FrameCaptionButton::ColorMode::kDefault, - default_frame_header->GetActiveFrameColor()); - const float inactive_alpha_ratio = - ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio(); - SkColor inactive_color = - SkColorSetA(active_color, 255 * inactive_alpha_ratio); - hosted_app_button_container_ = new HostedAppButtonContainer( - browser_view(), active_color, inactive_color); - caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0); - - // Add the origin text. - frame_header_origin_text_ = - std::make_unique<ash::FrameHeaderOriginText>( - browser->hosted_app_controller()->GetFormattedUrlOrigin(), - active_color, inactive_color) - .release(); - AddChildView(frame_header_origin_text_); - - // Schedule the title bar animation. - constexpr base::TimeDelta kTitlebarAnimationDelay = - base::TimeDelta::FromMilliseconds(750); - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation, - weak_factory_.GetWeakPtr()), - kTitlebarAnimationDelay); - } else if (!browser->is_app()) { - default_frame_header->SetFrameColors(BrowserFrameAsh::kMdWebUiFrameColor, - BrowserFrameAsh::kMdWebUiFrameColor); + header = std::move(default_frame_header); } - if (back_button_) - default_frame_header->set_back_button(back_button_); - - if (window_icon_) - default_frame_header->set_left_header_view(window_icon_); - - return default_frame_header; + header->SetBackButton(back_button_); + header->SetLeftHeaderView(window_icon_); + return header; } void BrowserNonClientFrameViewAsh::StartHostedAppAnimation() {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index 03298041..80dfc1f9 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -7,13 +7,13 @@ #include <memory> +#include "ash/frame/custom_frame_header.h" #include "ash/public/interfaces/split_view.mojom.h" #include "ash/shell_observer.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "chrome/browser/command_observer.h" #include "chrome/browser/ui/ash/tablet_mode_client_observer.h" -#include "chrome/browser/ui/views/frame/browser_frame_header_ash.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/tab_icon_view_model.h" #include "mojo/public/cpp/bindings/binding.h" @@ -35,7 +35,7 @@ // Provides the BrowserNonClientFrameView for Chrome OS. class BrowserNonClientFrameViewAsh : public BrowserNonClientFrameView, - public BrowserFrameHeaderAsh::AppearanceProvider, + public ash::CustomFrameHeader::AppearanceProvider, public ash::ShellObserver, public TabletModeClientObserver, public TabIconViewModel, @@ -79,7 +79,7 @@ gfx::Size GetMinimumSize() const override; void ChildPreferredSizeChanged(views::View* child) override; - // BrowserFrameHeaderAsh::AppearanceProvider: + // ash::CustomFrameHeader::AppearanceProvider: SkColor GetFrameHeaderColor(bool active) override; gfx::ImageSkia GetFrameHeaderImage(bool active) override; gfx::ImageSkia GetFrameHeaderOverlayImage(bool active) override; @@ -138,7 +138,6 @@ FrameLayoutToggleTabletMode); friend class HostedAppNonClientFrameViewAshTest; - friend class BrowserFrameHeaderAsh; friend class ImmersiveModeControllerAshHostedAppBrowserTest; // Distance between the right edge of the NonClientFrameView and the tab
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 4fa8ce4..12ba5cb 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -74,6 +74,7 @@ #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/gfx/color_palette.h" +#include "ui/gfx/vector_icon_types.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/window_util.h" @@ -426,25 +427,30 @@ ash::FrameCaptionButtonContainerView::TestApi test( frame_view->caption_button_container_); widget->Maximize(); - // Restore icon for size button in maximized window state. - EXPECT_EQ(&ash::kWindowControlRestoreIcon, - test.size_button()->icon_definition_for_test()); + + // Restore icon for size button in maximized window state. Compare by name + // because the address may not be the same for different build targets in the + // component build. + EXPECT_EQ(*ash::kWindowControlRestoreIcon.name, + *test.size_button()->icon_definition_for_test()->name); widget->Minimize(); + // When entering tablet mode in minimized window state, size button should not // get updated. TabletModeClient::Get()->OnTabletModeToggled(true); - EXPECT_EQ(&ash::kWindowControlRestoreIcon, - test.size_button()->icon_definition_for_test()); + EXPECT_EQ(*ash::kWindowControlRestoreIcon.name, + *test.size_button()->icon_definition_for_test()->name); // When leaving tablet mode in minimized window state, size button should not // get updated. TabletModeClient::Get()->OnTabletModeToggled(false); - EXPECT_EQ(&ash::kWindowControlRestoreIcon, - test.size_button()->icon_definition_for_test()); + EXPECT_EQ(*ash::kWindowControlRestoreIcon.name, + *test.size_button()->icon_definition_for_test()->name); + // When unminimizing in non-tablet mode, size button should match with // maximized window state, which is restore icon. ::wm::Unminimize(widget->GetNativeWindow()); - EXPECT_EQ(&ash::kWindowControlRestoreIcon, - test.size_button()->icon_definition_for_test()); + EXPECT_EQ(*ash::kWindowControlRestoreIcon.name, + *test.size_button()->icon_definition_for_test()->name); } // This is a regression test that session restore minimized browser should @@ -694,8 +700,8 @@ // Tests that a web app's theme color is set. IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, ThemeColor) { - EXPECT_EQ(GetThemeColor(), frame_header_->GetActiveFrameColor()); - EXPECT_EQ(GetThemeColor(), frame_header_->GetInactiveFrameColor()); + EXPECT_EQ(GetThemeColor(), frame_header_->active_frame_color_for_testing()); + EXPECT_EQ(GetThemeColor(), frame_header_->inactive_frame_color_for_testing()); EXPECT_EQ(SK_ColorWHITE, GetActiveIconColor(hosted_app_button_container_)); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc index 3cb3555..3d39234 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "ui/base/theme_provider.h" -using BrowserNonClientFrameViewBrowserTest = ExtensionBrowserTest; +using BrowserNonClientFrameViewBrowserTest = extensions::ExtensionBrowserTest; // Test is Flaky on Windows see crbug.com/600201. #if defined(OS_WIN)
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc index 213941d..9432f25 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/frame/browser_frame.h" -#include "chrome/browser/ui/views/frame/browser_frame_header_ash.h" #include "chrome/browser/ui/views/frame/browser_frame_mus.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" @@ -39,6 +38,7 @@ #if defined(OS_CHROMEOS) #include "ash/ash_layout_constants.h" +#include "ash/public/cpp/window_properties.h" #endif #if !defined(OS_CHROMEOS) @@ -102,6 +102,8 @@ AddChildView(window_icon_); window_icon_->Update(); } + + OnThemeChanged(); } /////////////////////////////////////////////////////////////////////////////// @@ -350,6 +352,18 @@ return gfx::Size(min_width, min_client_view_size.height()); } +void BrowserNonClientFrameViewMus::OnThemeChanged() { +#if defined(OS_CHROMEOS) + gfx::ImageSkia active_frame_image = GetFrameImage(true); + if (active_frame_image.isNull()) { + frame()->GetNativeWindow()->ClearProperty(ash::kFrameImageActiveKey); + } else { + frame()->GetNativeWindow()->SetProperty( + ash::kFrameImageActiveKey, new gfx::ImageSkia(active_frame_image)); + } +#endif +} + /////////////////////////////////////////////////////////////////////////////// // TabIconViewModel:
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h index 376cfa2a..bac1874 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h
@@ -57,6 +57,7 @@ const char* GetClassName() const override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; gfx::Size GetMinimumSize() const override; + void OnThemeChanged() override; // TabIconViewModel: bool ShouldTabIconViewAnimate() const override;
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc index 949d029..4e16271 100644 --- a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc +++ b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
@@ -41,7 +41,7 @@ #include "extensions/common/extension.h" #include "ui/views/win/hwnd_util.h" -typedef ExtensionBrowserTest BrowserWindowPropertyManagerTest; +typedef extensions::ExtensionBrowserTest BrowserWindowPropertyManagerTest; namespace {
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc index e83285db..3e6a1d6 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
@@ -36,7 +36,7 @@ #include "ui/views/animation/test/ink_drop_host_view_test_api.h" class ImmersiveModeControllerAshHostedAppBrowserTest - : public ExtensionBrowserTest { + : public extensions::ExtensionBrowserTest { public: ImmersiveModeControllerAshHostedAppBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), @@ -81,17 +81,17 @@ } void SetUpInProcessBrowserTestFixture() override { - ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); ProfileIOData::SetCertVerifierForTesting(&mock_cert_verifier_); } void TearDownInProcessBrowserTestFixture() override { ProfileIOData::SetCertVerifierForTesting(nullptr); - ExtensionBrowserTest::TearDownInProcessBrowserTestFixture(); + extensions::ExtensionBrowserTest::TearDownInProcessBrowserTestFixture(); } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitch(switches::kUseMockCertVerifierForTesting); }
diff --git a/chrome/browser/ui/views/harmony/layout_provider_unittest.cc b/chrome/browser/ui/views/harmony/layout_provider_unittest.cc index e5ab434b..5bdc2b5 100644 --- a/chrome/browser/ui/views/harmony/layout_provider_unittest.cc +++ b/chrome/browser/ui/views/harmony/layout_provider_unittest.cc
@@ -70,11 +70,7 @@ // TODO(tapted): Smoke them out and figure out why. #if defined(OS_MACOSX) - if (base::mac::IsOS10_9()) { - EXPECT_EQ(6, label_font.GetExpectedTextWidth(1)); - } else { - EXPECT_EQ(10, label_font.GetExpectedTextWidth(1)); - } + EXPECT_EQ(10, label_font.GetExpectedTextWidth(1)); #else EXPECT_EQ(6, label_font.GetExpectedTextWidth(1)); // Some Windows bots may say 5.
diff --git a/chrome/browser/ui/views/ime/ime_warning_bubble_browsertest.cc b/chrome/browser/ui/views/ime/ime_warning_bubble_browsertest.cc index 1c20dc4..ad9b6e6 100644 --- a/chrome/browser/ui/views/ime/ime_warning_bubble_browsertest.cc +++ b/chrome/browser/ui/views/ime/ime_warning_bubble_browsertest.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/ui/views/ime/ime_warning_bubble_view.h" #include "ui/views/controls/button/checkbox.h" -class ImeWarningBubbleTest : public ExtensionBrowserTest { +class ImeWarningBubbleTest : public extensions::ExtensionBrowserTest { public: ImeWarningBubbleTest(); ~ImeWarningBubbleTest() override {} @@ -40,9 +40,8 @@ void ImeWarningBubbleTest::SetUpOnMainThread() { ToolbarActionsBar::disable_animations_for_testing_ = true; - ExtensionBrowserTest::SetUpOnMainThread(); - extension_ = ExtensionBrowserTest::LoadExtension( - test_data_dir_.AppendASCII("input_ime")); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); + extension_ = LoadExtension(test_data_dir_.AppendASCII("input_ime")); callback_ = base::Bind(&ImeWarningBubbleTest::OnPermissionBubbleFinished, base::Unretained(this));
diff --git a/chrome/browser/ui/views/location_bar/bubble_icon_view.cc b/chrome/browser/ui/views/location_bar/bubble_icon_view.cc index af140ea..4630f97 100644 --- a/chrome/browser/ui/views/location_bar/bubble_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/bubble_icon_view.cc
@@ -175,6 +175,10 @@ UpdateIcon(); } +void BubbleIconView::OnThemeChanged() { + UpdateIcon(); +} + void BubbleIconView::AddInkDropLayer(ui::Layer* ink_drop_layer) { image_->SetPaintToLayer(); image_->layer()->SetFillsBoundsOpaquely(false); @@ -254,10 +258,11 @@ void BubbleIconView::UpdateIcon() { const ui::NativeTheme* theme = GetNativeTheme(); SkColor icon_color = - active_ - ? theme->GetSystemColor( - ui::NativeTheme::kColorId_ProminentButtonColor) - : GetInkDropBaseColor(); + active_ ? theme->GetSystemColor( + ui::NativeTheme::kColorId_ProminentButtonColor) + : GetOmniboxColor(OmniboxPart::LOCATION_BAR_SECURITY_CHIP, + delegate_->GetTint(), + OmniboxPartState::CHIP_DEFAULT); image_->SetImage(gfx::CreateVectorIcon( GetVectorIcon(), GetLayoutConstant(LOCATION_BAR_ICON_SIZE), icon_color)); }
diff --git a/chrome/browser/ui/views/location_bar/bubble_icon_view.h b/chrome/browser/ui/views/location_bar/bubble_icon_view.h index 6eae406..e95e2bc 100644 --- a/chrome/browser/ui/views/location_bar/bubble_icon_view.h +++ b/chrome/browser/ui/views/location_bar/bubble_icon_view.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/scoped_observer.h" +#include "chrome/browser/ui/omnibox/omnibox_theme.h" #include "ui/gfx/image/image_skia.h" #include "ui/views/animation/ink_drop_host_view.h" #include "ui/views/controls/image_view.h" @@ -35,6 +36,7 @@ class Delegate { public: virtual content::WebContents* GetWebContentsForBubbleIconView() = 0; + virtual OmniboxTint GetTint() = 0; }; void Init(); @@ -59,7 +61,7 @@ BubbleIconView(CommandUpdater* command_updater, int command_id, - Delegate* delegate = nullptr); + Delegate* delegate); ~BubbleIconView() override; // Returns true if a related bubble is showing. @@ -98,6 +100,7 @@ void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) override; void OnNativeThemeChanged(const ui::NativeTheme* theme) override; + void OnThemeChanged() override; void AddInkDropLayer(ui::Layer* ink_drop_layer) override; void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override; std::unique_ptr<views::InkDrop> CreateInkDrop() override;
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.cc b/chrome/browser/ui/views/location_bar/find_bar_icon.cc index 0a2b7d1..e46fb4d 100644 --- a/chrome/browser/ui/views/location_bar/find_bar_icon.cc +++ b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
@@ -8,7 +8,8 @@ #include "components/toolbar/vector_icons.h" #include "ui/base/l10n/l10n_util.h" -FindBarIcon::FindBarIcon() : BubbleIconView(nullptr, 0) {} +FindBarIcon::FindBarIcon(BubbleIconView::Delegate* delegate) + : BubbleIconView(nullptr, 0, delegate) {} FindBarIcon::~FindBarIcon() {}
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.h b/chrome/browser/ui/views/location_bar/find_bar_icon.h index adf03b2b..7af0dc9f 100644 --- a/chrome/browser/ui/views/location_bar/find_bar_icon.h +++ b/chrome/browser/ui/views/location_bar/find_bar_icon.h
@@ -11,7 +11,7 @@ // The find icon to show when the find bar is visible. class FindBarIcon : public BubbleIconView { public: - FindBarIcon(); + explicit FindBarIcon(BubbleIconView::Delegate* delegate); ~FindBarIcon() override; void SetActive(bool activate, bool should_animate);
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.cc b/chrome/browser/ui/views/location_bar/intent_picker_view.cc index 320846e..c476d57 100644 --- a/chrome/browser/ui/views/location_bar/intent_picker_view.cc +++ b/chrome/browser/ui/views/location_bar/intent_picker_view.cc
@@ -19,8 +19,9 @@ class WebContents; } -IntentPickerView::IntentPickerView(Browser* browser) - : BubbleIconView(nullptr, 0), browser_(browser) { +IntentPickerView::IntentPickerView(Browser* browser, + BubbleIconView::Delegate* delegate) + : BubbleIconView(nullptr, 0, delegate), browser_(browser) { if (browser_) { intent_picker_controller_ = std::make_unique<arc::IntentPickerController>(browser_);
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.h b/chrome/browser/ui/views/location_bar/intent_picker_view.h index e9f98ace..e01549c8 100644 --- a/chrome/browser/ui/views/location_bar/intent_picker_view.h +++ b/chrome/browser/ui/views/location_bar/intent_picker_view.h
@@ -19,7 +19,7 @@ // The entry point for the intent picker. class IntentPickerView : public BubbleIconView { public: - explicit IntentPickerView(Browser* browser); + IntentPickerView(Browser* browser, BubbleIconView::Delegate* delegate); ~IntentPickerView() override; // BubbleIconView:
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index aaae7a4..0e6a3e6d 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -123,23 +123,6 @@ return ui::MaterialDesignController::IsTouchOptimizedUiEnabled(); } -OmniboxTint GetTintForProfile(Profile* profile) { - ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile); - if (theme_service->UsingDefaultTheme()) { - return profile->GetProfileType() == Profile::INCOGNITO_PROFILE - ? OmniboxTint::DARK - : OmniboxTint::LIGHT; - } - - // Check for GTK on Desktop Linux. - if (theme_service->IsSystemThemeDistinctFromDefaultTheme() && - theme_service->UsingSystemTheme()) - return OmniboxTint::NATIVE; - - // TODO(tapted): Infer a tint from theme colors? - return OmniboxTint::LIGHT; -} - // Returns true when a views::FocusRing should be used. bool ShouldUseFocusRingView(bool show_focus_ring) { return (show_focus_ring && LocationBarView::IsRounded()) || @@ -187,7 +170,7 @@ browser_(browser), delegate_(delegate), is_popup_mode_(is_popup_mode), - tint_(GetTintForProfile(profile)) { + tint_(GetTint()) { edit_bookmarks_enabled_.Init( bookmarks::prefs::kEditBookmarksEnabled, profile->GetPrefs(), base::Bind(&LocationBarView::UpdateWithoutTabRestore, @@ -260,7 +243,7 @@ AddChildView(image_view); } - zoom_view_ = new ZoomView(delegate_); + zoom_view_ = new ZoomView(delegate_, this); bubble_icons_.push_back(zoom_view_); manage_passwords_icon_view_ = new ManagePasswordsIconViews(command_updater(), this); @@ -277,12 +260,13 @@ #if defined(OS_CHROMEOS) if (browser_) bubble_icons_.push_back(intent_picker_view_ = - new IntentPickerView(browser_)); + new IntentPickerView(browser_, this)); #endif - bubble_icons_.push_back(find_bar_icon_ = new FindBarIcon()); - if (browser_) - bubble_icons_.push_back(star_view_ = - new StarView(command_updater(), browser_)); + bubble_icons_.push_back(find_bar_icon_ = new FindBarIcon(this)); + if (browser_) { + bubble_icons_.push_back( + star_view_ = new StarView(command_updater(), browser_, this)); + } std::for_each(bubble_icons_.begin(), bubble_icons_.end(), [this](BubbleIconView* icon_view) -> void { @@ -643,7 +627,7 @@ } void LocationBarView::OnThemeChanged() { - tint_ = GetTintForProfile(profile()); + tint_ = GetTint(); } void LocationBarView::OnNativeThemeChanged(const ui::NativeTheme* theme) { @@ -739,6 +723,23 @@ return GetWebContents(); } +OmniboxTint LocationBarView::GetTint() { + ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile()); + if (theme_service->UsingDefaultTheme()) { + return profile()->GetProfileType() == Profile::INCOGNITO_PROFILE + ? OmniboxTint::DARK + : OmniboxTint::LIGHT; + } + + // Check for GTK on Desktop Linux. + if (theme_service->IsSystemThemeDistinctFromDefaultTheme() && + theme_service->UsingSystemTheme()) + return OmniboxTint::NATIVE; + + // TODO(tapted): Infer a tint from theme colors? + return OmniboxTint::LIGHT; +} + //////////////////////////////////////////////////////////////////////////////// // LocationBarView, public static methods:
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index 77d8183..6154eb7 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -242,9 +242,6 @@ ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate() override; - // BubbleIconView::Delegate: - content::WebContents* GetWebContentsForBubbleIconView() override; - // ZoomEventManagerObserver: // Updates the view for the zoom icon when default zoom levels change. void OnDefaultZoomLevelChanged() override; @@ -374,6 +371,10 @@ const gfx::Point& press_pt, const gfx::Point& p) override; + // BubbleIconView::Delegate: + content::WebContents* GetWebContentsForBubbleIconView() override; + OmniboxTint GetTint() override; + // gfx::AnimationDelegate: void AnimationProgressed(const gfx::Animation* animation) override; void AnimationEnded(const gfx::Animation* animation) override;
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc index ed01ce2..6331dc4 100644 --- a/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/location_bar/selected_keyword_view_interactive_uitest.cc
@@ -22,7 +22,7 @@ } } -class SelectedKeywordViewTest : public ExtensionBrowserTest { +class SelectedKeywordViewTest : public extensions::ExtensionBrowserTest { public: SelectedKeywordViewTest() = default; ~SelectedKeywordViewTest() override = default;
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc index ed11dcb..48fca38 100644 --- a/chrome/browser/ui/views/location_bar/star_view.cc +++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -20,8 +20,10 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/views/widget/widget_observer.h" -StarView::StarView(CommandUpdater* command_updater, Browser* browser) - : BubbleIconView(command_updater, IDC_BOOKMARK_PAGE), +StarView::StarView(CommandUpdater* command_updater, + Browser* browser, + BubbleIconView::Delegate* delegate) + : BubbleIconView(command_updater, IDC_BOOKMARK_PAGE, delegate), browser_(browser), bookmark_promo_observer_(this) { set_id(VIEW_ID_STAR_BUTTON);
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h index a6f6c00..1d4d86fe 100644 --- a/chrome/browser/ui/views/location_bar/star_view.h +++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -15,7 +15,9 @@ // The star icon to show a bookmark bubble. class StarView : public BubbleIconView, public views::WidgetObserver { public: - StarView(CommandUpdater* command_updater, Browser* browser); + StarView(CommandUpdater* command_updater, + Browser* browser, + BubbleIconView::Delegate* delegate); ~StarView() override; // Toggles the star on or off.
diff --git a/chrome/browser/ui/views/location_bar/zoom_view.cc b/chrome/browser/ui/views/location_bar/zoom_view.cc index e2b468de..0b1fc03 100644 --- a/chrome/browser/ui/views/location_bar/zoom_view.cc +++ b/chrome/browser/ui/views/location_bar/zoom_view.cc
@@ -16,8 +16,9 @@ #include "ui/events/event.h" #include "ui/gfx/geometry/size.h" -ZoomView::ZoomView(LocationBarView::Delegate* location_bar_delegate) - : BubbleIconView(nullptr, 0), +ZoomView::ZoomView(LocationBarView::Delegate* location_bar_delegate, + BubbleIconView::Delegate* delegate) + : BubbleIconView(nullptr, 0, delegate), location_bar_delegate_(location_bar_delegate), icon_(&kZoomMinusIcon) { Update(nullptr);
diff --git a/chrome/browser/ui/views/location_bar/zoom_view.h b/chrome/browser/ui/views/location_bar/zoom_view.h index cc2496dd..20694ca 100644 --- a/chrome/browser/ui/views/location_bar/zoom_view.h +++ b/chrome/browser/ui/views/location_bar/zoom_view.h
@@ -20,7 +20,8 @@ // WebContents. Because the current WebContents changes as the user switches // tabs, a LocationBarView::Delegate is supplied to queried for the current // WebContents when needed. - explicit ZoomView(LocationBarView::Delegate* location_bar_delegate); + ZoomView(LocationBarView::Delegate* location_bar_delegate, + BubbleIconView::Delegate* delegate); ~ZoomView() override; // Updates the image and its tooltip appropriately, hiding or showing the icon
diff --git a/chrome/browser/ui/views/menu_controller_interactive_uitest.cc b/chrome/browser/ui/views/menu_controller_interactive_uitest.cc index 276eb16..2c3da9d 100644 --- a/chrome/browser/ui/views/menu_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/menu_controller_interactive_uitest.cc
@@ -4,6 +4,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "chrome/browser/ui/views/menu_test_base.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/submenu_view.h" @@ -55,7 +56,14 @@ typedef MenuControllerMnemonicTest<ui::VKEY_DIVIDE,1> MenuControllerMnemonicTestMnemonicMatch; -VIEW_TEST(MenuControllerMnemonicTestMnemonicMatch, MnemonicMatch); +#if defined(OS_MACOSX) +// Mnemonics aren't used on macOS. +#define MAYBE_MnemonicMatch DISABLED_MnemonicMatch +#else +#define MAYBE_MnemonicMatch MnemonicMatch +#endif + +VIEW_TEST(MenuControllerMnemonicTestMnemonicMatch, MAYBE_MnemonicMatch); // Pressing a key which matches the first letter of the menu item's title // should execute the command for that menu item.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc index 69aa0ab..3ae09a4 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
@@ -24,18 +24,22 @@ // The minimum vertical margin that should be used above and below each // suggestion. -static const int kMinVerticalMargin = 1; +static constexpr int kMinVerticalMargin = 1; // The vertical padding to provide each RenderText in addition to the height of // the font. Where possible, RenderText uses this additional space to vertically // center the cap height of the font instead of centering the entire font. -static const int kVerticalPadding = 4; +static constexpr int kVerticalPadding = 4; // TODO(dschuyler): Perhaps this should be based on the font size // instead of hardcoded to 2 dp (e.g. by adding a space in an // appropriate font to the beginning of the description, then reducing // the additional padding here to zero). -static const int kAnswerIconToTextPadding = 2; +static constexpr int kAnswerIconToTextPadding = 2; + +// The edge length of the rich suggestions images. +static constexpr int kRichImageSize = 32; +static constexpr int kRichImageCornerRadius = 4; // Returns the horizontal offset that ensures icons align vertically with the // Omnibox icon. @@ -127,7 +131,9 @@ flags.setAntiAlias(true); flags.setStyle(cc::PaintFlags::kStrokeAndFill_Style); flags.setColor(color_); - canvas->sk_canvas()->drawOval(gfx::RectToSkRect(gfx::Rect(size_)), flags); + canvas->sk_canvas()->drawRoundRect(gfx::RectToSkRect(gfx::Rect(size_)), + kRichImageCornerRadius, + kRichImageCornerRadius, flags); } } // namespace @@ -208,10 +214,9 @@ extensions::image_util::ParseHexColorString(match.image_dominant_color, &color); color = SkColorSetA(color, 0x40); // 25% transparency (arbitrary). - int image_edge_length = description_view_->GetLineHeight(); image_view_->SetImage( gfx::CanvasImageSource::MakeImageSkia<PlaceholderImageSource>( - gfx::Size(image_edge_length, image_edge_length), color)); + gfx::Size(kRichImageSize, kRichImageSize), color)); } else { // Single-line layout doesn't use the image. image_view_->SetSize(gfx::Size()); @@ -267,10 +272,10 @@ void OmniboxMatchCellView::LayoutRichSuggestion() { int x = GetIconAlignmentOffset() + HorizontalPadding(); int y = GetVerticalInsets(text_height_, /*is_old_style_answer=*/false).top(); - int image_edge_length = text_height_ * 2; - image_view_->SetImageSize(gfx::Size(image_edge_length, image_edge_length)); - image_view_->SetBounds(x, y, image_edge_length, image_edge_length); - x += image_edge_length + HorizontalPadding(); + image_view_->SetImageSize(gfx::Size(kRichImageSize, kRichImageSize)); + image_view_->SetBounds(x, y + (text_height_ * 2 - kRichImageSize) / 2, + kRichImageSize, kRichImageSize); + x += kRichImageSize + HorizontalPadding(); content_view_->SetBounds(x, y, width() - x, text_height_); y += text_height_; description_view_->SetBounds(x, y, width() - x, text_height_); @@ -285,14 +290,15 @@ x += icon_view_->width() + HorizontalPadding(); int content_width = content_view_->CalculatePreferredSize().width(); int description_width = description_view_->CalculatePreferredSize().width(); + gfx::Size separator_size = separator_view_->CalculatePreferredSize(); OmniboxPopupModel::ComputeMatchMaxWidths( - content_width, separator_view_->width(), description_width, width() - x, + content_width, separator_size.width(), description_width, width() - x, /*description_on_separate_line=*/false, !is_search_type_, &content_width, &description_width); content_view_->SetBounds(x, y, content_width, text_height_); if (description_width != 0) { x += content_view_->width(); - separator_view_->SetSize(separator_view_->CalculatePreferredSize()); + separator_view_->SetSize(separator_size); separator_view_->SetBounds(x, y, separator_view_->width(), text_height_); x += separator_view_->width(); description_view_->SetBounds(x, y, description_width, text_height_);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc index c6ae635..b61c371 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
@@ -43,10 +43,6 @@ #include "ui/views/linux_ui/linux_ui.h" #endif -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/ash_config.h" -#endif - namespace { enum PopupType { WIDE, NARROW, ROUNDED }; @@ -324,20 +320,6 @@ loader.LoadExtension(path); } -#if defined(OS_CHROMEOS) - if (chromeos::GetAshConfig() == ash::Config::MASH) { - // http://crbug.com/704942: Incognito frames do not update correctly in - // Mash, so the old values remain. Check here so this is revisited when - // fixed, and bail out of the rest of the test. - if (GetParam() == ROUNDED) - EXPECT_EQ(rounded_selection_color_dark, get_selection_color()); - else - EXPECT_EQ(legacy_dark_color, get_selection_color()); - - return; - } -#endif - // Check the incognito browser first. Everything should now be light and never // GTK. if (GetParam() == ROUNDED) {
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc index fbe5ade0..811c627 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.cc +++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -110,6 +110,7 @@ content::PictureInPictureWindowController* controller) : controller_(controller), video_view_(new views::View()), + controls_background_view_(new views::View()), close_controls_view_(new views::ImageButton(nullptr)), play_pause_controls_view_(new views::ToggleImageButton(nullptr)) { views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); @@ -156,8 +157,7 @@ // Determine the window size by fitting |natural_size_| within // |current_size_|, keeping to |natural_size_|'s aspect ratio. if (!natural_size_.IsEmpty()) - current_size_ = - media::ScaleSizeToFitWithinTarget(natural_size_, current_size_); + UpdateCurrentSizeWithAspectRatio(current_size_); // The initial positioning is on the bottom right quadrant // of the primary display work area. @@ -173,6 +173,14 @@ } void OverlayWindowViews::SetUpViews() { + // Set up views::View that slightly darkens the video so the media controls + // appear more prominently. This is especially important in cases with a + // very light background. + controls_background_view_->SetSize(GetBounds().size()); + controls_background_view_->SetPaintToLayer(ui::LAYER_SOLID_COLOR); + GetControlsBackgroundLayer()->SetColor(SK_ColorBLACK); + GetControlsBackgroundLayer()->SetOpacity(0.2f); + // Set up views::View that closes the window. close_controls_view_->SetSize(kCloseIconSize); close_controls_view_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, @@ -202,10 +210,40 @@ play_pause_controls_view_->SetPaintToLayer(ui::LAYER_TEXTURED); // Don't show the controls until the mouse hovers over the window. + GetControlsBackgroundLayer()->SetVisible(false); GetCloseControlsLayer()->SetVisible(false); GetPlayPauseControlsLayer()->SetVisible(false); } +void OverlayWindowViews::UpdateCurrentSizeWithAspectRatio(gfx::Size new_size) { + // This function will only be called once when this is true -- when the + // window is initially created. + if (current_size_.IsEmpty()) + return; + + // Check whether or not the new size and the video's natural size have the + // same orientation (landscape vs. portrait). Otherwise, the usage of the + // area checks below will flip the orientation of the video. + bool is_natural_size_landscape = + natural_size_.width() > natural_size_.height(); + bool is_new_size_landscape = new_size.width() > new_size.height(); + + // TODO(apacible): Make resizing more strict. Currently, the window may + // resize to not adhere to the aspect ratio while the bounds are being + // dragged. When there is no more drag motion (e.g. mouse lifts), the window + // snaps to adhere to the aspect ratio. Ideally, the window will always + // adhere to the aspect ratio while in drag motion. http://crbug/829677. + if (is_new_size_landscape == is_natural_size_landscape) { + if (natural_size_.GetArea() > new_size.GetArea()) { + current_size_ = + media::ScaleSizeToEncompassTarget(natural_size_, new_size); + } else { + current_size_ = + media::ScaleSizeToFitWithinTarget(natural_size_, new_size); + } + } +} + bool OverlayWindowViews::IsActive() const { return views::Widget::IsActive(); } @@ -250,6 +288,10 @@ return video_view_->layer(); } +ui::Layer* OverlayWindowViews::GetControlsBackgroundLayer() { + return controls_background_view_->layer(); +} + ui::Layer* OverlayWindowViews::GetCloseControlsLayer() { return close_controls_view_->layer(); } @@ -292,11 +334,13 @@ switch (event->type()) { // Only show the media controls when the mouse is hovering over the window. case ui::ET_MOUSE_ENTERED: + GetControlsBackgroundLayer()->SetVisible(true); GetCloseControlsLayer()->SetVisible(true); GetPlayPauseControlsLayer()->SetVisible(true); break; case ui::ET_MOUSE_EXITED: + GetControlsBackgroundLayer()->SetVisible(false); GetCloseControlsLayer()->SetVisible(false); GetPlayPauseControlsLayer()->SetVisible(false); break; @@ -331,5 +375,7 @@ if (controller_) controller_->UpdateLayerBounds(); - views::Widget::OnNativeWidgetSizeChanged(new_size); + UpdateCurrentSizeWithAspectRatio(new_size); + SetBounds(gfx::Rect(GetBounds().origin(), current_size_)); + views::Widget::OnNativeWidgetSizeChanged(current_size_); }
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h index d753df0..0eff5ff 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.h +++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -34,6 +34,7 @@ gfx::Rect GetBounds() const override; void UpdateVideoSize(const gfx::Size& natural_size) override; ui::Layer* GetVideoLayer() override; + ui::Layer* GetControlsBackgroundLayer() override; ui::Layer* GetCloseControlsLayer() override; ui::Layer* GetPlayPauseControlsLayer() override; gfx::Rect GetCloseControlsBounds() override; @@ -58,6 +59,10 @@ // Set up the views::Views that will be shown on the window. void SetUpViews(); + // Update |current_size_| closest to the |new_size| while adhering to the + // aspect ratio of the video, which is retrieved from |natural_size_|. + void UpdateCurrentSizeWithAspectRatio(gfx::Size new_size); + // Not owned; |controller_| owns |this|. content::PictureInPictureWindowController* controller_; @@ -77,6 +82,7 @@ // Views to be shown. std::unique_ptr<views::View> video_view_; + std::unique_ptr<views::View> controls_background_view_; std::unique_ptr<views::ImageButton> close_controls_view_; std::unique_ptr<views::ToggleImageButton> play_pause_controls_view_;
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc index dab1059..f206b4b8 100644 --- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -184,7 +184,7 @@ // time of first layout (nothing has loaded yet). Because of this, set it to. // total_dialog_height - header_height. On the other hand, the width will be // properly set so it can be 0 here. - web_view->SetPreferredSize(gfx::Size(0, kDialogHeight - 68)); + web_view->SetPreferredSize(gfx::Size(0, kDialogHeight - 75)); content_view->AddChildView(web_view.release()); }
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc index d325dbd4..42d5872 100644 --- a/chrome/browser/ui/views/payments/payment_request_views_util.cc +++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -191,12 +191,11 @@ views::GridLayout* layout = container->SetLayoutManager( std::make_unique<views::GridLayout>(container)); - constexpr int kHeaderTopVerticalInset = 14; - constexpr int kHeaderBottomVerticalInset = 8; + constexpr int kVerticalInset = 14; constexpr int kHeaderHorizontalInset = 16; - container->SetBorder(views::CreateEmptyBorder( - kHeaderTopVerticalInset, kHeaderHorizontalInset, - kHeaderBottomVerticalInset, kHeaderHorizontalInset)); + container->SetBorder( + views::CreateEmptyBorder(kVerticalInset, kHeaderHorizontalInset, + kVerticalInset, kHeaderHorizontalInset)); views::ColumnSet* columns = layout->AddColumnSet(0); // A column for the optional back arrow.
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc index f5874f8..7091c8db 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -125,7 +125,7 @@ } // namespace class ProfileChooserViewExtensionsTest - : public SupportsTestDialog<ExtensionBrowserTest> { + : public SupportsTestDialog<extensions::ExtensionBrowserTest> { public: ProfileChooserViewExtensionsTest() {} ~ProfileChooserViewExtensionsTest() override {}
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc index dd1ac5d..1191156 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -93,7 +93,8 @@ DISALLOW_COPY_AND_ASSIGN(MockSelectFileDialogListener); }; -class SelectFileDialogExtensionBrowserTest : public ExtensionBrowserTest { +class SelectFileDialogExtensionBrowserTest + : public extensions::ExtensionBrowserTest { public: enum DialogButtonType { DIALOG_BTN_OK, @@ -116,11 +117,11 @@ base::CreateDirectory(downloads_dir_); // Must run after our setup because it actually runs the test. - ExtensionBrowserTest::SetUp(); + extensions::ExtensionBrowserTest::SetUp(); } void TearDown() override { - ExtensionBrowserTest::TearDown(); + extensions::ExtensionBrowserTest::TearDown(); // Delete the dialog first, as it holds a pointer to the listener. dialog_ = NULL;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 7fbe8795..c43aac9 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -49,6 +49,7 @@ #include "ui/gfx/animation/tween.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_analysis.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/paint_vector_icon.h" @@ -434,6 +435,8 @@ } OnButtonColorMaybeChanged(); alert_indicator_button_->UpdateEnabledForMuteToggle(); + if (MD::GetMode() == MD::MATERIAL_REFRESH) + RepaintSubsequentTab(); Layout(); } @@ -931,6 +934,8 @@ void Tab::OnMouseEntered(const ui::MouseEvent& event) { hover_controller_.Show(views::GlowHoverController::SUBTLE); + if (MD::GetMode() == MD::MATERIAL_REFRESH) + RepaintSubsequentTab(); Layout(); } @@ -941,6 +946,8 @@ void Tab::OnMouseExited(const ui::MouseEvent& event) { hover_controller_.Hide(); + if (MD::GetMode() == MD::MATERIAL_REFRESH) + RepaintSubsequentTab(); Layout(); } @@ -991,6 +998,12 @@ //////////////////////////////////////////////////////////////////////////////// // Tab, private +void Tab::RepaintSubsequentTab() { + Tab* adjacent_tab = controller_->GetAdjacentTab(this, TabController::FORWARD); + if (adjacent_tab) + adjacent_tab->SchedulePaint(); +} + void Tab::MaybeAdjustLeftForPinnedTab(gfx::Rect* bounds, int visual_width) const { if (ShouldRenderAsNormalTab()) @@ -1129,6 +1142,9 @@ canvas->sk_canvas()->clipPath(*clip, SkClipOp::kDifference, true); canvas->sk_canvas()->drawPicture(cache.stroke_record); } + + if (!active) + PaintSeparator(canvas, inactive_color); } void Tab::PaintTabBackgroundFill(gfx::Canvas* canvas, @@ -1188,6 +1204,29 @@ canvas->DrawPath(path, flags); } +void Tab::PaintSeparator(gfx::Canvas* canvas, SkColor inactive_color) { + if (MD::GetMode() != MD::MATERIAL_REFRESH || IsMouseHovered()) + return; + + // If the tab to the left is either active or the mouse is hovered over it, + // the separator on this tab should not be painted. + Tab* previous_tab = + controller_->GetAdjacentTab(this, TabController::BACKWARD); + if (previous_tab && + (previous_tab->IsActive() || previous_tab->IsMouseHovered())) + return; + + const int tab_height = GetContentsBounds().height(); + gfx::RectF separator_bounds; + separator_bounds.set_size(gfx::SizeF(1, 16)); + separator_bounds.set_origin(gfx::PointF( + (tab_height - separator_bounds.height()) / 2, GetTabEndcapWidth() / 2)); + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setColor(color_utils::BlendTowardOppositeLuma(inactive_color, 0x5a)); + canvas->DrawRect(separator_bounds, flags); +} + void Tab::UpdateIconVisibility() { center_favicon_ = false; showing_icon_ = showing_alert_indicator_ = showing_close_button_ = false; @@ -1324,10 +1363,11 @@ button_color_ = new_button_color; title_->SetEnabledColor(title_color); alert_indicator_button_->OnParentTabButtonColorChanged(); - if (!MD::IsTouchOptimizedUiEnabled()) + if (!MD::IsTouchOptimizedUiEnabled()) { close_button_->SetTabColor(button_color_, color_utils::IsDark(theme_provider->GetColor( ThemeProperties::COLOR_TOOLBAR))); + } } if (MD::IsTouchOptimizedUiEnabled()) close_button_->ActiveStateChanged(this);
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index 0b885996..962d61a 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -216,6 +216,9 @@ // ui::EventHandler: void OnGestureEvent(ui::GestureEvent* event) override; + // Forces the tab to the right of this tab to repaint. + void RepaintSubsequentTab(); + // Invoked from Layout to adjust the position of the favicon or alert // indicator for pinned tabs. The visual_width parameter is how wide the // icon looks (rather than how wide the bounds are). @@ -252,6 +255,10 @@ bool active, SkColor color); + // Paints the separator line on the left edge of the tab if in material + // refresh mode. The painted color is derived from the inactive tab color. + void PaintSeparator(gfx::Canvas* canvas, SkColor inactive_color); + // Computes which icons are visible in the tab. Should be called everytime // before layout is performed. void UpdateIconVisibility();
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index 326d6d05c..5fa2cdb 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -29,17 +29,22 @@ // Controller for tabs. class TabController { public: + // Used in GetAdjacentTab to indicate which adjacent tab to retrieve. FORWARD + // will return the adjacent tab to the right. BACKWARD will return the + // adjacent tab to the left of the given tab. + enum Direction { FORWARD, BACKWARD }; + virtual const ui::ListSelectionModel& GetSelectionModel() const = 0; // Returns true if multiple selection is supported. virtual bool SupportsMultipleSelection() = 0; - // Returns true if we should force the close buttons of the inactive tabs - // to be hidden. + // Returns true if the close buttons of the inactive tabs are forced to be + // hidden. virtual bool ShouldHideCloseButtonForInactiveTabs() = 0; - // Returns true if we should show the close button an inactive tab on mouse - // hover. This is predicated on ShouldHideCloseButtonForInactiveTabs() + // Returns true if the close button on an inactive tab should be shown on + // mouse hover. This is predicated on ShouldHideCloseButtonForInactiveTabs() // returning true. virtual bool ShouldShowCloseButtonOnHover() = 0; @@ -100,6 +105,10 @@ virtual Tab* GetTabAt(Tab* tab, const gfx::Point& tab_in_tab_coordinates) = 0; + // Returns the next/previous tab in the model order. Returns nullptr if there + // isn't an adjacent tab in the given direction. + virtual Tab* GetAdjacentTab(Tab* tab, Direction direction) = 0; + // Invoked when a mouse event occurs on |source|. virtual void OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 84845849..7b460a478 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -971,6 +971,15 @@ return view && view->id() == VIEW_ID_TAB ? static_cast<Tab*>(view) : NULL; } +Tab* TabStrip::GetAdjacentTab(Tab* tab, TabController::Direction direction) { + const int index = GetModelIndexOfTab(tab); + if (index < 0) + return nullptr; + const int new_index = index + (direction == TabController::FORWARD ? 1 : -1); + return new_index < 0 || new_index >= tab_count() ? nullptr + : tab_at(new_index); +} + void TabStrip::OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) { UpdateStackedLayoutFromMouseEvent(source, event); @@ -1093,7 +1102,8 @@ // ordering). Additionally we need to paint the tabs that are closing in // |tabs_closing_map_|. bool is_dragging = false; - Tab* active_tab = NULL; + Tab* active_tab = nullptr; + Tab* hovered_tab = nullptr; Tabs tabs_dragging; Tabs selected_tabs; @@ -1119,8 +1129,15 @@ } } else if (!tab->IsActive()) { if (!tab->IsSelected()) { - if (!stacked_layout_) - tab->Paint(paint_info); + if (!stacked_layout_) { + // In Refresh mode, defer the painting of the hovered tab to below. + if (MD::GetMode() == MD::MATERIAL_REFRESH && + tab->IsMouseHovered()) { + hovered_tab = tab; + } else { + tab->Paint(paint_info); + } + } } else { selected_tabs.push_back(tab); } @@ -1150,6 +1167,23 @@ for (size_t i = 0; i < selected_tabs.size(); ++i) selected_tabs[i]->Paint(paint_info); + // If the last hovered tab is still animating and there is no currently + // hovered tab, make sure it still paints in the right order while it's + // animating. + if (!hovered_tab && last_hovered_tab_ && + last_hovered_tab_->hover_controller()->ShouldDraw()) + hovered_tab = last_hovered_tab_; + + // The currently hovered tab or the last tab that was hovered should be + // painted right before the active tab to ensure the highlighted tab shape + // looks reasonable. + if (hovered_tab && !is_dragging) + hovered_tab->Paint(paint_info); + + // Keep track of the last tab that was hovered to that it continues to be + // painted right before the active tab while the animation is running. + last_hovered_tab_ = hovered_tab; + // Next comes the active tab. if (active_tab && !is_dragging) active_tab->Paint(paint_info);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 6ebf93c8..a5f5a05 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -248,6 +248,7 @@ void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override; bool EndDrag(EndDragReason reason) override; Tab* GetTabAt(Tab* tab, const gfx::Point& tab_in_tab_coordinates) override; + Tab* GetAdjacentTab(Tab* tab, TabController::Direction direction) override; void OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) override; bool ShouldPaintTab( @@ -683,6 +684,10 @@ // tab close comes from a touch device. base::OneShotTimer resize_layout_timer_; + // The last tab over which the mouse was hovered which may still have a hover + // animation in progress. + Tab* last_hovered_tab_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(TabStrip); };
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index 8733877..8ff02ce 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -64,7 +64,10 @@ } bool EndDrag(EndDragReason reason) override { return false; } Tab* GetTabAt(Tab* tab, const gfx::Point& tab_in_tab_coordinates) override { - return NULL; + return nullptr; + } + Tab* GetAdjacentTab(Tab* tab, TabController::Direction direction) override { + return nullptr; } void OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) override {}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc index 35869c803..1dba9cd27 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
@@ -134,12 +134,13 @@ } // namespace -class ToolbarActionViewInteractiveUITest : public ExtensionBrowserTest { +class ToolbarActionViewInteractiveUITest + : public extensions::ExtensionBrowserTest { protected: ToolbarActionViewInteractiveUITest(); ~ToolbarActionViewInteractiveUITest() override; - // ExtensionBrowserTest: + // extensions::ExtensionBrowserTest: void SetUpCommandLine(base::CommandLine* command_line) override; void TearDownOnMainThread() override; @@ -154,7 +155,7 @@ void ToolbarActionViewInteractiveUITest::SetUpCommandLine( base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); ToolbarActionsBar::disable_animations_for_testing_ = true; }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc index 0be5de4..6f92356 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
@@ -38,7 +38,7 @@ using bookmarks::BookmarkModel; -class ToolbarViewInteractiveUITest : public ExtensionBrowserTest { +class ToolbarViewInteractiveUITest : public extensions::ExtensionBrowserTest { public: ToolbarViewInteractiveUITest(); ~ToolbarViewInteractiveUITest() override; @@ -135,13 +135,13 @@ void ToolbarViewInteractiveUITest::SetUpCommandLine( base::CommandLine* command_line) { - ExtensionBrowserTest::SetUpCommandLine(command_line); + extensions::ExtensionBrowserTest::SetUpCommandLine(command_line); ToolbarActionsBar::disable_animations_for_testing_ = true; BrowserAppMenuButton::g_open_app_immediately_for_testing = true; } void ToolbarViewInteractiveUITest::SetUpOnMainThread() { - ExtensionBrowserTest::SetUpOnMainThread(); + extensions::ExtensionBrowserTest::SetUpOnMainThread(); ExtensionToolbarMenuView::set_close_menu_delay_for_testing(0); toolbar_view_ = BrowserView::GetBrowserViewForBrowser(browser())->toolbar();
diff --git a/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc index 7c863b5..c317f4f 100644 --- a/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc
@@ -107,7 +107,8 @@ DCHECK(LoginDisplayHost::default_host()); LoginDisplayHost::default_host()->SetDisplayAndGivenName( account_info.display_name(), account_info.given_name()); - UserContext user_context(account_id); + UserContext user_context( + user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, account_id); user_context.SetKey(key); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); user_context.SetIsUsingOAuth(false);
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 479ab976..111345d 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -243,6 +243,16 @@ return is_child ? user_manager::USER_TYPE_CHILD : user_manager::USER_TYPE_REGULAR; } + +user_manager::UserType CalculateUserType(const AccountId& account_id) { + if (user_manager::UserManager::Get()->IsSupervisedAccountId(account_id)) + return user_manager::USER_TYPE_SUPERVISED; + + if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) + return user_manager::USER_TYPE_ACTIVE_DIRECTORY; + + return user_manager::USER_TYPE_REGULAR; +} } // namespace // A class that's used to specify the way how Gaia should be loaded. @@ -659,7 +669,8 @@ username, account_info.account_id(), AccountType::ACTIVE_DIRECTORY)); LoginDisplayHost::default_host()->SetDisplayAndGivenName( account_info.display_name(), account_info.given_name()); - UserContext user_context(account_id); + UserContext user_context( + user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, account_id); user_context.SetKey(key); user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); user_context.SetIsUsingOAuth(false); @@ -840,8 +851,14 @@ DCHECK(!gaia_id.empty()); const std::string sanitized_email = gaia::SanitizeEmail(typed_email); LoginDisplayHost::default_host()->SetDisplayEmail(sanitized_email); - UserContext user_context( - GetAccountId(typed_email, gaia_id, AccountType::GOOGLE)); + const AccountId account_id = + GetAccountId(typed_email, gaia_id, AccountType::GOOGLE); + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + + UserContext user_context = + user ? UserContext(*user) + : UserContext(CalculateUserType(account_id), account_id); user_context.SetKey(Key(password)); user_context.SetAuthFlow(using_saml ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
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 02b21f3..bc51016 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -1215,16 +1215,18 @@ const user_manager::User* user = user_manager::UserManager::Get()->FindUser(account_id); DCHECK(user); - user_manager::UserType user_type = user_manager::UserType::USER_TYPE_REGULAR; + UserContext user_context; if (!user) { LOG(ERROR) << "HandleAuthenticateUser: User not found! account type=" << AccountId::AccountTypeToString(account_id.GetAccountType()); - if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) - user_type = user_manager::USER_TYPE_ACTIVE_DIRECTORY; + const user_manager::UserType user_type = + (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) + ? user_manager::USER_TYPE_ACTIVE_DIRECTORY + : user_manager::UserType::USER_TYPE_REGULAR; + user_context = UserContext(user_type, account_id); } else { - user_type = user->GetType(); + user_context = UserContext(*user); } - UserContext user_context(user_type, account_id); user_context.SetKey(Key(password)); // Only save the password for enterprise users. See https://crbug.com/386606. const bool is_enterprise_managed = g_browser_process->platform_part()
diff --git a/chrome/browser/ui/webui/net_export_ui.cc b/chrome/browser/ui/webui/net_export_ui.cc index 56a0086..0aac4e4a 100644 --- a/chrome/browser/ui/webui/net_export_ui.cc +++ b/chrome/browser/ui/webui/net_export_ui.cc
@@ -137,10 +137,6 @@ // NetLog file. void ShowSelectFileDialog(const base::FilePath& default_path); - // Returns a list of context getters used to retrieve ongoing events when - // logging starts so that net log entries can be added for those events. - URLRequestContextGetterList GetURLRequestContexts() const; - // Cache of g_browser_process->net_log()->net_export_file_writer(). This // is owned by ChromeNetLog which is owned by BrowserProcessImpl. net_log::NetExportFileWriter* file_writer_; @@ -167,8 +163,7 @@ : file_writer_(g_browser_process->net_log()->net_export_file_writer()), state_observer_manager_(this), weak_ptr_factory_(this) { - file_writer_->Initialize( - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); + file_writer_->Initialize(); } NetExportMessageHandler::~NetExportMessageHandler() { @@ -177,7 +172,7 @@ if (select_file_dialog_) select_file_dialog_->ListenerDestroyed(); - file_writer_->StopNetLog(nullptr, nullptr); + file_writer_->StopNetLog(nullptr); } void NetExportMessageHandler::RegisterMessages() { @@ -270,8 +265,7 @@ chrome_browser_net::GetWindowsServiceProviders()); #endif - file_writer_->StopNetLog(std::move(ui_thread_polled_data), - Profile::FromWebUI(web_ui())->GetRequestContext()); + file_writer_->StopNetLog(std::move(ui_thread_polled_data)); } void NetExportMessageHandler::OnSendNetLog(const base::ListValue* list) { @@ -334,7 +328,10 @@ file_writer_->StartNetLog( path, capture_mode_, max_log_file_size_, base::CommandLine::ForCurrentProcess()->GetCommandLineString(), - chrome::GetChannelName(), GetURLRequestContexts()); + chrome::GetChannelName(), + content::BrowserContext::GetDefaultStoragePartition( + Profile::FromWebUI(web_ui())) + ->GetNetworkContext()); } void NetExportMessageHandler::ShowFileInShell(const base::FilePath& path) { @@ -384,24 +381,6 @@ &file_type_info, 0, base::FilePath::StringType(), owning_window, nullptr); } -NetExportMessageHandler::URLRequestContextGetterList -NetExportMessageHandler::GetURLRequestContexts() const { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - URLRequestContextGetterList context_getters; - - Profile* profile = Profile::FromWebUI(web_ui()); - - context_getters.push_back(profile->GetRequestContext()); - context_getters.push_back( - content::BrowserContext::GetDefaultStoragePartition(profile) - ->GetMediaURLRequestContext()); - context_getters.push_back( - g_browser_process->io_thread()->system_url_request_context_getter()); - - return context_getters; -} - } // namespace NetExportUI::NetExportUI(content::WebUI* web_ui) : WebUIController(web_ui) {
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc index c2893076..12c2eb2 100644 --- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -64,7 +64,6 @@ #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" #include "net/http/http_network_session.h" -#include "net/http/http_server_properties.h" #include "net/http/http_stream_factory.h" #include "net/http/transport_security_state.h" #include "net/log/net_log.h"
diff --git a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc index eeddd63..57ba15e1 100644 --- a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc +++ b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
@@ -679,12 +679,19 @@ IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionWithExistingSessionName) { CreateMultipleSessionFiles(3); ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool")); + content::RunAllTasksUntilIdle(); + // Make sure the current session is '2'. EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId")); // Check that a session can not be renamed with a name of another existing // session. RenameSession("2", "1"); + // Wait until the posted tasks are done. After check that name already exist + // the tool displays an error message in the UI. + content::RunAllTasksUntilIdle(); EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed()); + + // Check the names that appear in the session list didn't change. base::ListValue expected; expected.GetList().push_back(base::Value("2")); expected.GetList().push_back(base::Value("1"));
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 8a9836d..6f58ae3 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -107,6 +107,7 @@ PRINT_WITH_CLOUD_PRINT, PRINT_WITH_PRIVET, PRINT_WITH_EXTENSION, + OPEN_IN_MAC_PREVIEW, USERACTION_BUCKET_BOUNDARY }; @@ -144,19 +145,89 @@ PRINT_DOCUMENT_TYPE_BUCKET_BOUNDARY }; -void ReportUserActionHistogram(enum UserActionBuckets event) { +void ReportUserActionHistogram(UserActionBuckets event) { UMA_HISTOGRAM_ENUMERATION("PrintPreview.UserAction", event, USERACTION_BUCKET_BOUNDARY); } -void ReportPrintSettingHistogram(enum PrintSettingsBuckets setting) { +void ReportPrintSettingHistogram(PrintSettingsBuckets setting) { UMA_HISTOGRAM_ENUMERATION("PrintPreview.PrintSettings", setting, PRINT_SETTINGS_BUCKET_BOUNDARY); } -void ReportPrintDocumentTypeHistogram(enum PrintDocumentTypeBuckets doctype) { +void ReportPrintDocumentTypeAndSizeHistograms(PrintDocumentTypeBuckets doctype, + size_t average_page_size_in_kb) { UMA_HISTOGRAM_ENUMERATION("PrintPreview.PrintDocumentType", doctype, PRINT_DOCUMENT_TYPE_BUCKET_BOUNDARY); + switch (doctype) { + case HTML_DOCUMENT: + UMA_HISTOGRAM_MEMORY_KB("PrintPreview.PrintDocumentSize.HTML", + average_page_size_in_kb); + break; + case PDF_DOCUMENT: + UMA_HISTOGRAM_MEMORY_KB("PrintPreview.PrintDocumentSize.PDF", + average_page_size_in_kb); + break; + default: + NOTREACHED(); + break; + } +} + +bool ReportPageCountHistogram(UserActionBuckets user_action, int page_count) { + switch (user_action) { + case PRINT_TO_PRINTER: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count); + return true; + case PRINT_TO_PDF: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPDF", page_count); + return true; + case FALLBACK_TO_ADVANCED_SETTINGS_DIALOG: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.SystemDialog", page_count); + return true; + case PRINT_WITH_CLOUD_PRINT: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToCloudPrint", + page_count); + return true; + case PRINT_WITH_PRIVET: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithPrivet", + page_count); + return true; + case PRINT_WITH_EXTENSION: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithExtension", + page_count); + return true; + case OPEN_IN_MAC_PREVIEW: + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.OpenInMacPreview", + page_count); + return true; + default: + return false; + } +} + +PrinterType GetPrinterTypeForUserAction(UserActionBuckets user_action) { + switch (user_action) { + case PRINT_WITH_PRIVET: + return PrinterType::kPrivetPrinter; + case PRINT_WITH_EXTENSION: + return PrinterType::kExtensionPrinter; + case PRINT_TO_PDF: + return PrinterType::kPdfPrinter; + case PRINT_TO_PRINTER: + case FALLBACK_TO_ADVANCED_SETTINGS_DIALOG: + case OPEN_IN_MAC_PREVIEW: + return PrinterType::kLocalPrinter; + default: + NOTREACHED(); + return PrinterType::kLocalPrinter; + } +} + +base::Value GetErrorValue(UserActionBuckets user_action, + base::StringPiece description) { + return user_action == PRINT_WITH_PRIVET ? base::Value(-1) + : base::Value(description); } // Dictionary Fields for Print Preview initial settings. Keep in sync with @@ -299,6 +370,30 @@ } } +UserActionBuckets DetermineUserAction(const base::DictionaryValue& settings) { + bool value = false; +#if defined(OS_MACOSX) + value = settings.HasKey(printing::kSettingOpenPDFInPreview); +#endif + if (value) + return OPEN_IN_MAC_PREVIEW; + if (settings.HasKey(printing::kSettingCloudPrintId)) + return PRINT_WITH_CLOUD_PRINT; + settings.GetBoolean(printing::kSettingPrintWithPrivet, &value); + if (value) + return PRINT_WITH_PRIVET; + settings.GetBoolean(printing::kSettingPrintWithExtension, &value); + if (value) + return PRINT_WITH_EXTENSION; + settings.GetBoolean(printing::kSettingPrintToPDF, &value); + if (value) + return PRINT_TO_PDF; + settings.GetBoolean(printing::kSettingShowSystemDialog, &value); + if (value) + return FALLBACK_TO_ADVANCED_SETTINGS_DIALOG; + return PRINT_TO_PRINTER; +} + base::LazyInstance<printing::StickySettings>::DestructorAtExit g_sticky_settings = LAZY_INSTANCE_INITIALIZER; @@ -640,109 +735,71 @@ return; } - ReportPrintSettingsStats(*settings); - - // Report whether the user printed a PDF or an HTML document. - ReportPrintDocumentTypeHistogram(print_preview_ui()->source_is_modifiable() ? - HTML_DOCUMENT : PDF_DOCUMENT); - - bool print_to_pdf = false; - bool is_cloud_printer = false; - bool print_with_privet = false; - bool print_with_extension = false; - bool show_system_dialog = false; - bool open_pdf_in_preview = false; -#if defined(OS_MACOSX) - open_pdf_in_preview = settings->HasKey(printing::kSettingOpenPDFInPreview); -#endif - - if (!open_pdf_in_preview) { - settings->GetBoolean(printing::kSettingPrintToPDF, &print_to_pdf); - settings->GetBoolean(printing::kSettingPrintWithPrivet, &print_with_privet); - settings->GetBoolean(printing::kSettingPrintWithExtension, - &print_with_extension); - settings->GetBoolean(printing::kSettingShowSystemDialog, - &show_system_dialog); - is_cloud_printer = settings->HasKey(printing::kSettingCloudPrintId); - } + const UserActionBuckets user_action = DetermineUserAction(*settings); int page_count = 0; if (!settings->GetInteger(printing::kSettingPreviewPageCount, &page_count) || page_count <= 0) { - RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); + RejectJavascriptCallback(base::Value(callback_id), + GetErrorValue(user_action, "NO_PAGE_COUNT")); return; } - if (print_with_privet) { -#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithPrivet", page_count); - ReportUserActionHistogram(PRINT_WITH_PRIVET); -#endif - } else if (print_with_extension) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithExtension", - page_count); - ReportUserActionHistogram(PRINT_WITH_EXTENSION); - } else if (print_to_pdf) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPDF", page_count); - ReportUserActionHistogram(PRINT_TO_PDF); - } else if (show_system_dialog) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.SystemDialog", page_count); - ReportUserActionHistogram(FALLBACK_TO_ADVANCED_SETTINGS_DIALOG); - } else if (!open_pdf_in_preview) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count); - ReportUserActionHistogram(PRINT_TO_PRINTER); - } else if (is_cloud_printer) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToCloudPrint", - page_count); - ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT); - } - scoped_refptr<base::RefCountedMemory> data; print_preview_ui()->GetPrintPreviewDataForIndex( printing::COMPLETE_PREVIEW_DOCUMENT_INDEX, &data); if (!data) { // Nothing to print, no preview available. - RejectJavascriptCallback( - base::Value(callback_id), - print_with_privet ? base::Value(-1) : base::Value("NO_DATA")); + RejectJavascriptCallback(base::Value(callback_id), + GetErrorValue(user_action, "NO_DATA")); return; } DCHECK(data->size()); DCHECK(data->front()); - if (is_cloud_printer) { - // Does not send the title like the other printer handler types below, - // because JS already has the document title from the initial settings. - SendCloudPrintJob(callback_id, data.get()); - return; - } - std::string destination_id; std::string print_ticket; std::string capabilities; int width = 0; int height = 0; - if ((print_with_privet || print_with_extension) && - (!settings->GetString(printing::kSettingDeviceName, &destination_id) || - !settings->GetString(printing::kSettingTicket, &print_ticket) || - !settings->GetString(printing::kSettingCapabilities, &capabilities) || - !settings->GetInteger(printing::kSettingPageWidth, &width) || - !settings->GetInteger(printing::kSettingPageHeight, &height) || - width <= 0 || height <= 0)) { + if (user_action == PRINT_WITH_PRIVET || user_action == PRINT_WITH_EXTENSION) { + if (!settings->GetString(printing::kSettingDeviceName, &destination_id) || + !settings->GetString(printing::kSettingTicket, &print_ticket) || + !settings->GetString(printing::kSettingCapabilities, &capabilities) || + !settings->GetInteger(printing::kSettingPageWidth, &width) || + !settings->GetInteger(printing::kSettingPageHeight, &height) || + width <= 0 || height <= 0) { + NOTREACHED(); + RejectJavascriptCallback(base::Value(callback_id), + GetErrorValue(user_action, "FAILED")); + return; + } + } + + // After validating |settings|, record metrics. + ReportPrintSettingsStats(*settings); + { + PrintDocumentTypeBuckets doc_type = + print_preview_ui()->source_is_modifiable() ? HTML_DOCUMENT + : PDF_DOCUMENT; + size_t average_page_size_in_kb = data->size() / page_count; + average_page_size_in_kb /= 1024; + ReportPrintDocumentTypeAndSizeHistograms(doc_type, average_page_size_in_kb); + } + ReportUserActionHistogram(user_action); + if (!ReportPageCountHistogram(user_action, page_count)) { NOTREACHED(); - RejectJavascriptCallback( - base::Value(callback_id), - print_with_privet ? base::Value(-1) : base::Value("FAILED")); return; } - PrinterType type = PrinterType::kLocalPrinter; - if (print_with_extension) - type = PrinterType::kExtensionPrinter; - else if (print_with_privet) - type = PrinterType::kPrivetPrinter; - else if (print_to_pdf) - type = PrinterType::kPdfPrinter; + if (user_action == PRINT_WITH_CLOUD_PRINT) { + // Does not send the title like the other printer handler types below, + // because JS already has the document title from the initial settings. + SendCloudPrintJob(callback_id, data.get()); + return; + } + + PrinterType type = GetPrinterTypeForUserAction(user_action); PrinterHandler* handler = GetPrinterHandler(type); handler->StartPrint( destination_id, capabilities, print_preview_ui()->initiator_title(),
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index 8332032..92db0fd 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -112,6 +112,21 @@ callback); } +// Returns the list of |printers| formatted as a CupsPrintersList. +base::Value BuildCupsPrintersList(const std::vector<Printer>& printers) { + base::Value printers_list(base::Value::Type::LIST); + for (const Printer& printer : printers) { + // Some of these printers could be invalid but we want to allow the user + // to edit them. crbug.com/778383 + printers_list.GetList().push_back( + base::Value::FromUniquePtrValue(GetCupsPrinterInfo(printer))); + } + + base::Value response(base::Value::Type::DICTIONARY); + response.SetKey("printerList", std::move(printers_list)); + return response; +} + // Extracts a sanitized value of printerQueue from |printer_dict|. Returns an // empty string if the value was not present in the dictionary. std::string GetPrinterQueue(const base::DictionaryValue& printer_dict) { @@ -275,16 +290,8 @@ std::vector<Printer> printers = printers_manager_->GetPrinters(CupsPrintersManager::kConfigured); - auto printers_list = std::make_unique<base::ListValue>(); - for (const Printer& printer : printers) { - // Some of these printers could be invalid but we want to allow the user - // to edit them. crbug.com/778383 - printers_list->Append(GetCupsPrinterInfo(printer)); - } - - auto response = std::make_unique<base::DictionaryValue>(); - response->Set("printerList", std::move(printers_list)); - ResolveJavascriptCallback(base::Value(callback_id), *response); + auto response = BuildCupsPrintersList(printers); + ResolveJavascriptCallback(base::Value(callback_id), response); } void CupsPrintersHandler::HandleUpdateCupsPrinter(const base::ListValue* args) { @@ -753,6 +760,8 @@ UMA_HISTOGRAM_COUNTS_100( "Printing.CUPS.PrintersDiscovered", discovered_printers_.size() + automatic_printers_.size()); + // Scan completes immediately right now. Emit done. + FireWebUIListener("on-printer-discovery-done"); } void CupsPrintersHandler::HandleStopDiscovery(const base::ListValue* args) { @@ -780,20 +789,32 @@ void CupsPrintersHandler::OnPrintersChanged( CupsPrintersManager::PrinterClass printer_class, const std::vector<Printer>& printers) { - if (!discovery_active_) { - return; - } switch (printer_class) { case CupsPrintersManager::kAutomatic: automatic_printers_ = printers; + UpdateDiscoveredPrinters(); break; case CupsPrintersManager::kDiscovered: discovered_printers_ = printers; + UpdateDiscoveredPrinters(); break; - default: - // It's a class we don't care about. + case CupsPrintersManager::kConfigured: { + auto printers_list = BuildCupsPrintersList(printers); + FireWebUIListener("on-printers-changed", printers_list); + break; + } + case CupsPrintersManager::kEnterprise: + case CupsPrintersManager::kNumPrinterClasses: + // These classes are not shown. return; } +} + +void CupsPrintersHandler::UpdateDiscoveredPrinters() { + if (!discovery_active_) { + return; + } + std::unique_ptr<base::ListValue> printers_list = std::make_unique<base::ListValue>(); for (const Printer& printer : automatic_printers_) { @@ -804,7 +825,6 @@ } FireWebUIListener("on-printer-discovered", *printers_list); - FireWebUIListener("on-printer-discovery-done"); } void CupsPrintersHandler::HandleAddDiscoveredPrinter(
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index dddfb63e..447eecb 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -126,6 +126,9 @@ const std::string& manufacturer, const std::string& model); + // Emits the updated discovered printer list after new printers are received. + void UpdateDiscoveredPrinters(); + // Attempt to add a discovered printer. void HandleAddDiscoveredPrinter(const base::ListValue* args);
diff --git a/chrome/browser/unload_browsertest.cc b/chrome/browser/unload_browsertest.cc index ff81d2c9..d78d3a3 100644 --- a/chrome/browser/unload_browsertest.cc +++ b/chrome/browser/unload_browsertest.cc
@@ -14,6 +14,7 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/net/url_request_mock_util.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" @@ -962,6 +963,35 @@ } IN_PROC_BROWSER_TEST_F(FastUnloadTest, + BrowserListForceCloseWithIncognitoProfileCloseProfiles) { + Profile* otr_profile = browser()->profile()->GetOffTheRecordProfile(); + Browser* otr_browser1 = CreateBrowser(otr_profile); + Browser* otr_browser2 = CreateBrowser(otr_profile); + content::WindowedNotificationObserver otr_browser1_observer( + chrome::NOTIFICATION_BROWSER_CLOSED, + content::Source<Browser>(otr_browser1)); + content::WindowedNotificationObserver otr_browser2_observer( + chrome::NOTIFICATION_BROWSER_CLOSED, + content::Source<Browser>(otr_browser2)); + UnloadResults unload_results; + BrowserList::CloseAllBrowsersWithIncognitoProfile( + otr_profile, + base::BindRepeating(&UnloadResults::AddSuccess, + base::Unretained(&unload_results)), + base::BindRepeating(&UnloadResults::AddAbort, + base::Unretained(&unload_results)), + true); + // Incognito browsers should be closed. + otr_browser1_observer.Wait(); + otr_browser2_observer.Wait(); + // Browser with original profile should not close. + EXPECT_EQ(1, browser()->tab_strip_model()->count()); + + EXPECT_EQ(1, unload_results.get_successes()); + EXPECT_EQ(0, unload_results.get_aborts()); +} + +IN_PROC_BROWSER_TEST_F(FastUnloadTest, BrowserListForceCloseAfterNormalCloseWithFastUnload) { NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload"); PrepareForDialog(browser());
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index ca5b9f5..72e907b 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -77,10 +77,6 @@ "elements/paged_grid_layout.h", "elements/paged_scroll_view.cc", "elements/paged_scroll_view.h", - "elements/prompt.cc", - "elements/prompt.h", - "elements/prompt_texture.cc", - "elements/prompt_texture.h", "elements/rect.cc", "elements/rect.h", "elements/render_text_wrapper.cc", @@ -99,6 +95,8 @@ "elements/spinner.h", "elements/text.cc", "elements/text.h", + "elements/text_button.cc", + "elements/text_button.h", "elements/text_input.cc", "elements/text_input.h", "elements/textured_element.cc", @@ -277,7 +275,6 @@ "elements/omnibox_text_field_unittest.cc", "elements/oval_unittest.cc", "elements/paged_grid_layout_unittest.cc", - "elements/prompt_unittest.cc", "elements/rect_unittest.cc", "elements/repositioner_unittest.cc", "elements/resizer_unittest.cc",
diff --git a/chrome/browser/vr/browser_ui_interface.h b/chrome/browser/vr/browser_ui_interface.h index b0b666f0..0211aaf 100644 --- a/chrome/browser/vr/browser_ui_interface.h +++ b/chrome/browser/vr/browser_ui_interface.h
@@ -56,6 +56,7 @@ const base::string16& title) = 0; virtual void RemoveTab(int id, bool incognito) = 0; virtual void RemoveAllTabs() = 0; + virtual void OnTabSelected(int id, bool incognito) = 0; }; } // namespace vr
diff --git a/chrome/browser/vr/elements/button.cc b/chrome/browser/vr/elements/button.cc index 0a867861..c99bf772 100644 --- a/chrome/browser/vr/elements/button.cc +++ b/chrome/browser/vr/elements/button.cc
@@ -108,10 +108,14 @@ click_handler_.Run(); } +void Button::OnSetColors(const ButtonColors& colors) {} + void Button::OnStateUpdated() { pressed_ = hovered_ ? down_ : false; background_->SetColor(colors_.GetBackgroundColor(hovered_, pressed_)); + OnSetColors(colors_); + if (hover_offset_ == 0.0f) return; @@ -136,7 +140,9 @@ } void Button::OnSetSize(const gfx::SizeF& size) { - background_->SetSize(size.width(), size.height()); + if (!background_->contributes_to_parent_bounds()) { + background_->SetSize(size.width(), size.height()); + } hit_plane_->SetSize(size.width(), size.height()); }
diff --git a/chrome/browser/vr/elements/button.h b/chrome/browser/vr/elements/button.h index 02a4da14..46b98dc 100644 --- a/chrome/browser/vr/elements/button.h +++ b/chrome/browser/vr/elements/button.h
@@ -76,6 +76,8 @@ void HandleButtonDown(); void HandleButtonUp(); + virtual void OnSetColors(const ButtonColors& colors); + const Sounds& GetSounds() const override; bool down_ = false;
diff --git a/chrome/browser/vr/elements/prompt.cc b/chrome/browser/vr/elements/prompt.cc deleted file mode 100644 index c7d1874..0000000 --- a/chrome/browser/vr/elements/prompt.cc +++ /dev/null
@@ -1,115 +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 "chrome/browser/vr/elements/prompt.h" - -#include "chrome/browser/vr/elements/prompt_texture.h" - -namespace vr { - -Prompt::Prompt(int preferred_width, - int content_message_id, - const gfx::VectorIcon& icon, - int primary_button_message_id, - int secondary_button_message_id, - const PromptCallback& result_callback) - : TexturedElement(), - texture_(std::make_unique<PromptTexture>(content_message_id, - icon, - primary_button_message_id, - secondary_button_message_id)), - preferred_width_(preferred_width), - result_callback_(result_callback) {} - -Prompt::~Prompt() = default; - -void Prompt::OnHoverEnter(const gfx::PointF& position) { - OnStateUpdated(position); -} - -void Prompt::OnHoverLeave() { - OnStateUpdated(gfx::PointF(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max())); -} - -void Prompt::OnMove(const gfx::PointF& position) { - OnStateUpdated(position); -} - -void Prompt::OnButtonDown(const gfx::PointF& position) { - if (texture_->HitsPrimaryButton(position)) - primary_down_ = true; - else if (texture_->HitsSecondaryButton(position)) - secondary_down_ = true; - OnStateUpdated(position); -} - -void Prompt::OnButtonUp(const gfx::PointF& position) { - if (primary_down_ && texture_->HitsPrimaryButton(position)) - result_callback_.Run(PRIMARY, reason_); - else if (secondary_down_ && texture_->HitsSecondaryButton(position)) - result_callback_.Run(SECONDARY, reason_); - - primary_down_ = false; - secondary_down_ = false; - - OnStateUpdated(position); -} - -void Prompt::SetContentMessageId(int message_id) { - texture_->SetContentMessageId(message_id); -} - -void Prompt::SetIconColor(SkColor color) { - static_cast<PromptTexture*>(GetTexture())->SetIconColor(color); -} - -void Prompt::SetPrimaryButtonColors(const ButtonColors& colors) { - texture_->SetPrimaryButtonColors(colors); -} - -void Prompt::SetSecondaryButtonColors(const ButtonColors& colors) { - texture_->SetSecondaryButtonColors(colors); -} - -void Prompt::SetTextureForTesting(std::unique_ptr<PromptTexture> texture) { - texture_ = std::move(texture); -} - -void Prompt::ClickPrimaryButtonForTesting() { - result_callback_.Run(PRIMARY, reason_); -} - -void Prompt::ClickSecondaryButtonForTesting() { - result_callback_.Run(SECONDARY, reason_); -} - -void Prompt::Cancel() { - result_callback_.Run(NONE, reason_); -} - -void Prompt::OnStateUpdated(const gfx::PointF& position) { - const bool primary_hovered = texture_->HitsPrimaryButton(position); - const bool secondary_hovered = texture_->HitsSecondaryButton(position); - - texture_->SetPrimaryButtonHovered(primary_hovered); - texture_->SetPrimaryButtonPressed(primary_hovered ? primary_down_ : false); - texture_->SetSecondaryButtonHovered(secondary_hovered); - texture_->SetSecondaryButtonPressed(secondary_hovered ? secondary_down_ - : false); -} - -UiTexture* Prompt::GetTexture() const { - return texture_.get(); -} - -bool Prompt::TextureDependsOnMeasurement() const { - return false; -} - -gfx::Size Prompt::MeasureTextureSize() { - return texture_->GetPreferredTextureSize(preferred_width_); -} - -} // namespace vr
diff --git a/chrome/browser/vr/elements/prompt.h b/chrome/browser/vr/elements/prompt.h deleted file mode 100644 index d2f24071..0000000 --- a/chrome/browser/vr/elements/prompt.h +++ /dev/null
@@ -1,78 +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 CHROME_BROWSER_VR_ELEMENTS_PROMPT_H_ -#define CHROME_BROWSER_VR_ELEMENTS_PROMPT_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/macros.h" -#include "chrome/browser/vr/elements/textured_element.h" -#include "chrome/browser/vr/ui_unsupported_mode.h" -#include "ui/gfx/vector_icon_types.h" - -namespace vr { - -class PromptTexture; -struct ButtonColors; - -class Prompt : public TexturedElement { - public: - enum Button { NONE, PRIMARY, SECONDARY }; - - typedef typename base::RepeatingCallback<void(Button, UiUnsupportedMode)> - PromptCallback; - - Prompt(int preferred_width, - int content_message_id, - const gfx::VectorIcon& icon, - int primary_button_message_id, - int secondary_button_message_id, - const PromptCallback& result_callback); - ~Prompt() override; - - void set_reason(UiUnsupportedMode reason) { reason_ = reason; } - - void OnHoverEnter(const gfx::PointF& position) override; - void OnHoverLeave() override; - void OnMove(const gfx::PointF& position) override; - void OnButtonDown(const gfx::PointF& position) override; - void OnButtonUp(const gfx::PointF& position) override; - - void SetContentMessageId(int message_id); - void SetIconColor(SkColor color); - void SetPrimaryButtonColors(const ButtonColors& colors); - void SetSecondaryButtonColors(const ButtonColors& colors); - - void Cancel(); - - void SetTextureForTesting(std::unique_ptr<PromptTexture> texture); - void ClickPrimaryButtonForTesting(); - void ClickSecondaryButtonForTesting(); - - protected: - UiTexture* GetTexture() const override; - - private: - void OnStateUpdated(const gfx::PointF& position); - - bool TextureDependsOnMeasurement() const override; - gfx::Size MeasureTextureSize() override; - - bool primary_down_ = false; - bool secondary_down_ = false; - UiUnsupportedMode reason_ = UiUnsupportedMode::kCount; - - std::unique_ptr<PromptTexture> texture_; - int preferred_width_ = 0; - - PromptCallback result_callback_; - - DISALLOW_COPY_AND_ASSIGN(Prompt); -}; - -} // namespace vr - -#endif // CHROME_BROWSER_VR_ELEMENTS_PROMPT_H_
diff --git a/chrome/browser/vr/elements/prompt_texture.cc b/chrome/browser/vr/elements/prompt_texture.cc deleted file mode 100644 index 970c1cb2..0000000 --- a/chrome/browser/vr/elements/prompt_texture.cc +++ /dev/null
@@ -1,206 +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 "chrome/browser/vr/elements/prompt_texture.h" - -#include "base/i18n/case_conversion.h" -#include "cc/paint/skia_paint_canvas.h" -#include "chrome/browser/vr/elements/vector_icon.h" -#include "chrome/grit/generated_resources.h" -#include "components/strings/grit/components_strings.h" -#include "components/vector_icons/vector_icons.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/vector2d.h" -#include "ui/gfx/render_text.h" - -namespace vr { - -namespace { - -constexpr float kWidth = 0.63f; -constexpr float kHeight = 0.218f; -constexpr float kButtonHeight = 0.064f; -constexpr float kCornerRadius = 0.006f; -constexpr float kPadding = 0.028f; -constexpr float kIconSize = 0.042f; -constexpr float kFontSizePromptText = 0.028f; -constexpr float kTextTopMargin = 0.007f; -constexpr float kTextLeftMargin = 0.010f; -constexpr float kVerticalGap = 0.056f; -constexpr float kButtonsDistance = 0.014f; -constexpr float kFontSizePromptButtonText = 0.024f; -constexpr float kButtonRadius = 0.0035f; - -constexpr float kButtonWidth = 0.162f; - -constexpr char kPreferredFontNameForButtons[] = "sans-serif-medium"; - -} // namespace - -PromptTexture::PromptTexture(int content_message_id, - const gfx::VectorIcon& icon, - int primary_button_message_id, - int secondary_button_message_id) - : icon_(icon), - primary_button_message_id_(primary_button_message_id), - secondary_button_message_id_(secondary_button_message_id) { - SetContentMessageId(content_message_id); -} - -PromptTexture::~PromptTexture() = default; - -gfx::Size PromptTexture::GetPreferredTextureSize(int maximum_width) const { - return gfx::Size(maximum_width, maximum_width * kHeight / kWidth); -} - -void PromptTexture::SetPrimaryButtonHovered(bool hovered) { - SetAndDirty(&primary_hovered_, hovered); -} - -void PromptTexture::SetPrimaryButtonPressed(bool pressed) { - SetAndDirty(&primary_pressed_, pressed); -} - -void PromptTexture::SetSecondaryButtonHovered(bool hovered) { - SetAndDirty(&secondary_hovered_, hovered); -} - -void PromptTexture::SetSecondaryButtonPressed(bool pressed) { - SetAndDirty(&secondary_pressed_, pressed); -} - -void PromptTexture::SetContentMessageId(int message_id) { - SetAndDirty(&content_message_id_, message_id); -} - -bool PromptTexture::HitsSecondaryButton(const gfx::PointF& position) const { - return secondary_button_rect_.Contains(PercentToPixels(position)); -} - -bool PromptTexture::HitsPrimaryButton(const gfx::PointF& position) const { - return primary_button_rect_.Contains(PercentToPixels(position)); -} - -void PromptTexture::SetPrimaryButtonColors(const ButtonColors& colors) { - SetAndDirty(&primary_button_colors_, colors); -} - -void PromptTexture::SetSecondaryButtonColors(const ButtonColors& colors) { - SetAndDirty(&secondary_button_colors_, colors); -} - -void PromptTexture::SetIconColor(SkColor color) { - SetAndDirty(&icon_color_, color); -} - -float PromptTexture::ToPixels(float meters) const { - return meters * size_.width() / kWidth; -} - -gfx::PointF PromptTexture::PercentToPixels(const gfx::PointF& percent) const { - return gfx::PointF(percent.x() * size_.width(), percent.y() * size_.height()); -} - -void PromptTexture::Draw(SkCanvas* sk_canvas, const gfx::Size& texture_size) { - // TODO(cjgrant): Use a fixed scalar, like text, since size should be ~DMM. - size_.set_width(texture_size.width()); - size_.set_height(texture_size.height()); - - // background - cc::SkiaPaintCanvas paint_canvas(sk_canvas); - gfx::Canvas gfx_canvas(&paint_canvas, 1.0f); - gfx::Canvas* canvas = &gfx_canvas; - - SkPaint back_paint; - back_paint.setColor(background_color()); - sk_canvas->drawRoundRect(SkRect::MakeWH(size_.width(), size_.height()), - ToPixels(kCornerRadius), ToPixels(kCornerRadius), - back_paint); - - // Icon - gfx::PointF icon_location(ToPixels(kPadding), ToPixels(kPadding)); - VectorIcon::DrawVectorIcon(canvas, icon_, ToPixels(kIconSize), icon_location, - icon_color_); - - // Prompt description. - auto text = l10n_util::GetStringUTF16(content_message_id_); - gfx::FontList fonts; - GetDefaultFontList(ToPixels(kFontSizePromptText), text, &fonts); - gfx::Rect prompt_text_size( - ToPixels(kWidth - 2 * kPadding - kTextLeftMargin - kIconSize), 0); - std::vector<std::unique_ptr<gfx::RenderText>> lines = - PrepareDrawStringRect(text, fonts, foreground_color(), &prompt_text_size, - kTextAlignmentNone, kWrappingBehaviorWrap); - canvas->Save(); - canvas->Translate( - gfx::Vector2d(ToPixels(kTextLeftMargin + kIconSize + kPadding), - ToPixels(kPadding + kTextTopMargin))); - for (auto& render_text : lines) - render_text->Draw(canvas); - canvas->Restore(); - - // Buttons - SkPaint paint; - gfx::Rect button_text_size(ToPixels(kButtonWidth), 0); - float radius = ToPixels(kButtonRadius); - - // Secondary button area. - // TODO(https://crbug.com/787654): Uppercasing should be conditional. - text = base::i18n::ToUpper( - l10n_util::GetStringUTF16(secondary_button_message_id_)); - GetFontList(kPreferredFontNameForButtons, ToPixels(kFontSizePromptButtonText), - text, &fonts); - lines = PrepareDrawStringRect( - text, fonts, secondary_button_colors_.foreground, &button_text_size, - kTextAlignmentCenter, kWrappingBehaviorWrap); - secondary_button_rect_.SetRect( - ToPixels(kWidth - kPadding - kButtonsDistance - 2 * kButtonWidth), - ToPixels(kPadding + kIconSize + kVerticalGap), ToPixels(kButtonWidth), - ToPixels(kButtonHeight)); - paint.setColor(secondary_button_colors_.GetBackgroundColor( - secondary_hovered_, secondary_pressed_)); - canvas->Save(); - canvas->Translate( - gfx::Vector2d(secondary_button_rect_.x(), secondary_button_rect_.y())); - sk_canvas->drawRoundRect( - SkRect::MakeXYWH(0, 0, ToPixels(kButtonWidth), ToPixels(kButtonHeight)), - radius, radius, paint); - canvas->Translate(gfx::Vector2d( - 0, ToPixels(kButtonHeight) / 2 - button_text_size.height() / 2)); - for (auto& render_text : lines) - render_text->Draw(canvas); - canvas->Restore(); - - // Primary button area. - // TODO(https://crbug.com/787654): Uppercasing should be conditional. - text = base::i18n::ToUpper( - l10n_util::GetStringUTF16(primary_button_message_id_)); - GetFontList(kPreferredFontNameForButtons, ToPixels(kFontSizePromptButtonText), - text, &fonts); - button_text_size.set_size(gfx::Size(ToPixels(kButtonWidth), 0)); - lines = PrepareDrawStringRect(text, fonts, primary_button_colors_.foreground, - &button_text_size, kTextAlignmentCenter, - kWrappingBehaviorWrap); - primary_button_rect_.SetRect(ToPixels(kWidth - kPadding - kButtonWidth), - ToPixels(kPadding + kIconSize + kVerticalGap), - ToPixels(kButtonWidth), ToPixels(kButtonHeight)); - paint.setColor(primary_button_colors_.GetBackgroundColor(primary_hovered_, - primary_pressed_)); - canvas->Save(); - canvas->Translate( - gfx::Vector2d(primary_button_rect_.x(), primary_button_rect_.y())); - sk_canvas->drawRoundRect( - SkRect::MakeXYWH(0, 0, ToPixels(kButtonWidth), ToPixels(kButtonHeight)), - radius, radius, paint); - canvas->Translate(gfx::Vector2d( - 0, ToPixels(kButtonHeight) / 2 - button_text_size.height() / 2)); - for (auto& render_text : lines) - render_text->Draw(canvas); - canvas->Restore(); -} - -} // namespace vr
diff --git a/chrome/browser/vr/elements/prompt_texture.h b/chrome/browser/vr/elements/prompt_texture.h deleted file mode 100644 index 0f35346..0000000 --- a/chrome/browser/vr/elements/prompt_texture.h +++ /dev/null
@@ -1,66 +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 CHROME_BROWSER_VR_ELEMENTS_PROMPT_TEXTURE_H_ -#define CHROME_BROWSER_VR_ELEMENTS_PROMPT_TEXTURE_H_ - -#include "base/macros.h" -#include "chrome/browser/vr/elements/ui_texture.h" -#include "chrome/browser/vr/model/color_scheme.h" -#include "ui/gfx/geometry/rect_f.h" -#include "ui/gfx/vector_icon_types.h" - -namespace vr { - -class PromptTexture : public UiTexture { - public: - PromptTexture(int content_message_id, - const gfx::VectorIcon& icon, - int primary_button_message_id, - int secondary_button_message_id); - ~PromptTexture() override; - gfx::Size GetPreferredTextureSize(int width) const; - - void SetPrimaryButtonHovered(bool hovered); - void SetPrimaryButtonPressed(bool pressed); - void SetSecondaryButtonHovered(bool hovered); - void SetSecondaryButtonPressed(bool pressed); - virtual void SetContentMessageId(int message_id); - - virtual bool HitsSecondaryButton(const gfx::PointF& position) const; - virtual bool HitsPrimaryButton(const gfx::PointF& position) const; - - void SetPrimaryButtonColors(const ButtonColors& colors); - void SetSecondaryButtonColors(const ButtonColors& colors); - void SetIconColor(SkColor color); - - private: - float ToPixels(float meters) const; - gfx::PointF PercentToPixels(const gfx::PointF& percent) const; - void Draw(SkCanvas* sk_canvas, const gfx::Size& texture_size) override; - - gfx::RectF secondary_button_rect_; - gfx::RectF primary_button_rect_; - gfx::SizeF size_; - - bool primary_hovered_ = false; - bool primary_pressed_ = false; - bool secondary_hovered_ = false; - bool secondary_pressed_ = false; - - ButtonColors primary_button_colors_; - ButtonColors secondary_button_colors_; - SkColor icon_color_ = SK_ColorBLACK; - const gfx::VectorIcon& icon_; - - int primary_button_message_id_ = -1; - int secondary_button_message_id_ = -1; - int content_message_id_ = -1; - - DISALLOW_COPY_AND_ASSIGN(PromptTexture); -}; - -} // namespace vr - -#endif // CHROME_BROWSER_VR_ELEMENTS_PROMPT_TEXTURE_H_
diff --git a/chrome/browser/vr/elements/prompt_unittest.cc b/chrome/browser/vr/elements/prompt_unittest.cc deleted file mode 100644 index 9363dc1..0000000 --- a/chrome/browser/vr/elements/prompt_unittest.cc +++ /dev/null
@@ -1,114 +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 "chrome/browser/vr/elements/prompt.h" - -#include "base/bind.h" -#include "base/macros.h" -#include "chrome/browser/vr/elements/prompt_texture.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/gfx/test/gfx_util.h" - -using ::testing::Return; - -namespace vr { - -namespace { - -class MockPromptTexture : public PromptTexture { - public: - MockPromptTexture() : PromptTexture(-1, gfx::kNoneIcon, -1, -1) {} - ~MockPromptTexture() override {} - - MOCK_CONST_METHOD1(HitsPrimaryButton, bool(const gfx::PointF&)); - MOCK_CONST_METHOD1(HitsSecondaryButton, bool(const gfx::PointF&)); - - MOCK_CONST_METHOD1(GetPreferredTextureSize, gfx::Size(int)); - MOCK_CONST_METHOD0(GetDrawnSize, gfx::SizeF()); - MOCK_METHOD2(Draw, void(SkCanvas*, const gfx::Size&)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockPromptTexture); -}; - -} // namespace - -class TestPrompt : public Prompt { - public: - TestPrompt(); - ~TestPrompt() override {} - - bool primary_button_pressed() const { return primary_button_pressed_; } - bool secondary_button_pressed() const { return secondary_button_pressed_; } - - private: - void OnButtonPressed(Prompt::Button button, UiUnsupportedMode reason) { - switch (button) { - case Prompt::NONE: - break; - case Prompt::PRIMARY: - primary_button_pressed_ = true; - break; - case Prompt::SECONDARY: - secondary_button_pressed_ = true; - break; - } - } - - bool primary_button_pressed_ = false; - bool secondary_button_pressed_ = false; -}; - -TestPrompt::TestPrompt() - : Prompt(512, - -1, - gfx::kNoneIcon, - -1, - -1, - base::BindRepeating(&TestPrompt::OnButtonPressed, - base::Unretained(this))) {} - -TEST(PromptTest, PrimaryButtonCallbackCalled) { - TestPrompt prompt; - auto texture = std::make_unique<MockPromptTexture>(); - // Called twice from OnButtonDown and twice from OnButtonUp. - EXPECT_CALL(*texture, HitsPrimaryButton(gfx::PointF())) - .Times(4) - .WillRepeatedly(Return(true)); - // Called once from OnButtonDown and once from OnButtonUp (via OnStatUpdated). - EXPECT_CALL(*texture, HitsSecondaryButton(gfx::PointF())) - .Times(2) - .WillRepeatedly(Return(false)); - prompt.SetTextureForTesting(std::move(texture)); - - prompt.OnButtonDown(gfx::PointF()); - prompt.OnButtonUp(gfx::PointF()); - - EXPECT_TRUE(prompt.primary_button_pressed()); - EXPECT_FALSE(prompt.secondary_button_pressed()); -} - -TEST(PromptTest, SecondaryButtonCallbackCalled) { - TestPrompt prompt; - auto texture = std::make_unique<MockPromptTexture>(); - // Called twice from OnButtonDown and once from OnButtonUp. - EXPECT_CALL(*texture, HitsPrimaryButton(gfx::PointF())) - .Times(3) - .WillRepeatedly(Return(false)); - // Called twice from OnButtonDown and twice from OnButtonUp. - EXPECT_CALL(*texture, HitsSecondaryButton(gfx::PointF())) - .Times(4) - .WillRepeatedly(Return(true)); - prompt.SetTextureForTesting(std::move(texture)); - - prompt.OnButtonDown(gfx::PointF()); - prompt.OnButtonUp(gfx::PointF()); - - EXPECT_FALSE(prompt.primary_button_pressed()); - EXPECT_TRUE(prompt.secondary_button_pressed()); -} - -} // namespace vr
diff --git a/chrome/browser/vr/elements/text.cc b/chrome/browser/vr/elements/text.cc index 8621c327..9cd75d2 100644 --- a/chrome/browser/vr/elements/text.cc +++ b/chrome/browser/vr/elements/text.cc
@@ -4,15 +4,20 @@ #include "chrome/browser/vr/elements/text.h" +#include "base/i18n/char_iterator.h" #include "cc/paint/skia_paint_canvas.h" #include "chrome/browser/vr/elements/render_text_wrapper.h" #include "chrome/browser/vr/elements/ui_texture.h" +#include "chrome/browser/vr/font_fallback.h" +#include "third_party/icu/source/common/unicode/uscript.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/render_text.h" +#include "ui/gfx/shadow_value.h" +#include "ui/gfx/text_elider.h" namespace vr { @@ -21,6 +26,7 @@ constexpr float kCursorWidthRatio = 0.07f; constexpr int kTextPixelPerDmm = 1100; constexpr float kTextShadowScaleFactor = 1000.0f; +constexpr char kDefaultFontFamily[] = "sans-serif"; int DmmToPixel(float dmm) { return static_cast<int>(dmm * kTextPixelPerDmm); @@ -34,6 +40,160 @@ return mode == kSingleLineFixedWidth || mode == kMultiLineFixedWidth; } +std::unique_ptr<gfx::RenderText> CreateRenderText( + const base::string16& text, + const gfx::FontList& font_list, + SkColor color, + TextAlignment text_alignment, + bool shadows_enabled, + SkColor shadow_color, + float shadow_size) { + auto render_text = gfx::RenderText::CreateHarfBuzzInstance(); + + // Disable the cursor to avoid reserving width for a trailing caret. + render_text->SetCursorEnabled(false); + + // Subpixel rendering is counterproductive when drawing VR textures. + render_text->set_subpixel_rendering_suppressed(true); + + render_text->SetText(text); + render_text->SetFontList(font_list); + render_text->SetColor(color); + if (shadows_enabled) { + render_text->set_shadows( + {gfx::ShadowValue({0, 0}, shadow_size, shadow_color)}); + } + + switch (text_alignment) { + case kTextAlignmentNone: + break; + case kTextAlignmentLeft: + render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); + break; + case kTextAlignmentRight: + render_text->SetHorizontalAlignment(gfx::ALIGN_RIGHT); + break; + case kTextAlignmentCenter: + render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER); + break; + } + + const int font_style = font_list.GetFontStyle(); + render_text->SetStyle(gfx::ITALIC, (font_style & gfx::Font::ITALIC) != 0); + render_text->SetStyle(gfx::UNDERLINE, + (font_style & gfx::Font::UNDERLINE) != 0); + render_text->SetWeight(font_list.GetFontWeight()); + + return render_text; +} + +std::set<UChar32> CollectDifferentChars(base::string16 text) { + std::set<UChar32> characters; + for (base::i18n::UTF16CharIterator it(&text); !it.end(); it.Advance()) { + characters.insert(it.get()); + } + return characters; +} + +bool GetFontList(const std::string& preferred_font_name, + int font_size, + base::string16 text, + gfx::FontList* font_list) { + gfx::Font preferred_font(preferred_font_name, font_size); + std::vector<gfx::Font> fonts{preferred_font}; + + std::set<std::string> names; + // TODO(acondor): Query BrowserProcess to obtain the application locale. + for (UChar32 c : CollectDifferentChars(text)) { + std::string name; + bool found_name = GetFallbackFontNameForChar(preferred_font, c, "", &name); + if (!found_name) + return false; + if (!name.empty()) + names.insert(name); + } + for (const auto& name : names) { + DCHECK(!name.empty()); + fonts.push_back(gfx::Font(name, font_size)); + } + *font_list = gfx::FontList(fonts); + return true; +} + +std::vector<std::unique_ptr<gfx::RenderText>> PrepareDrawStringRect( + const base::string16& text, + const gfx::FontList& font_list, + gfx::Rect* bounds, + const TextRenderParameters& parameters) { + DCHECK(bounds); + + std::vector<std::unique_ptr<gfx::RenderText>> lines; + + if (parameters.wrapping_behavior == kWrappingBehaviorWrap) { + DCHECK(!parameters.cursor_enabled); + + gfx::Rect rect(*bounds); + std::vector<base::string16> strings; + gfx::ElideRectangleText(text, font_list, bounds->width(), + bounds->height() ? bounds->height() : INT_MAX, + gfx::WRAP_LONG_WORDS, &strings); + + int height = 0; + int line_height = 0; + for (size_t i = 0; i < strings.size(); i++) { + std::unique_ptr<gfx::RenderText> render_text = CreateRenderText( + strings[i], font_list, parameters.color, parameters.text_alignment, + parameters.shadows_enabled, parameters.shadow_color, + parameters.shadow_size); + + if (i == 0) { + // Measure line and center text vertically. + line_height = render_text->GetStringSize().height(); + rect.set_height(line_height); + if (bounds->height()) { + const int text_height = strings.size() * line_height; + rect += gfx::Vector2d(0, (bounds->height() - text_height) / 2); + } + } + + render_text->SetDisplayRect(rect); + height += line_height; + rect += gfx::Vector2d(0, line_height); + lines.push_back(std::move(render_text)); + } + + // Set calculated height. + if (bounds->height() == 0) + bounds->set_height(height); + } else { + std::unique_ptr<gfx::RenderText> render_text = + CreateRenderText(text, font_list, parameters.color, + parameters.text_alignment, parameters.shadows_enabled, + parameters.shadow_color, parameters.shadow_size); + if (bounds->width() != 0 && !parameters.cursor_enabled) + render_text->SetElideBehavior(gfx::TRUNCATE); + if (parameters.cursor_enabled) { + render_text->SetCursorEnabled(true); + render_text->SetCursorPosition(parameters.cursor_position); + } + + if (bounds->width() == 0) + bounds->set_width(render_text->GetStringSize().width()); + if (bounds->height() == 0) + bounds->set_height(render_text->GetStringSize().height()); + + render_text->SetDisplayRect(*bounds); + lines.push_back(std::move(render_text)); + } + + if (parameters.shadows_enabled) { + bounds->Inset(-parameters.shadow_size, -parameters.shadow_size); + bounds->Offset(parameters.shadow_size, parameters.shadow_size); + } + + return lines; +} + } // namespace TextFormattingAttribute::TextFormattingAttribute(SkColor color, @@ -235,7 +395,7 @@ texture_->SetFormatting(formatting); } -void Text::SetAlignment(UiTexture::TextAlignment alignment) { +void Text::SetAlignment(TextAlignment alignment) { texture_->SetAlignment(alignment); } @@ -338,7 +498,7 @@ } gfx::FontList fonts; - if (!GetDefaultFontList(pixel_font_height, text_, &fonts) || + if (!GetFontList(kDefaultFontFamily, pixel_font_height, text_, &fonts) || unsupported_code_point_for_test_) { if (unhandled_codepoint_callback_) unhandled_codepoint_callback_.Run(); @@ -355,10 +515,7 @@ parameters.shadows_enabled = shadows_enabled_; parameters.shadow_size = kTextShadowScaleFactor * font_height_dmms_; - lines_ = - // TODO(vollick): if this subsumes all text, then we should probably move - // this function into this class. - PrepareDrawStringRect(text_, fonts, &text_bounds, parameters); + lines_ = PrepareDrawStringRect(text_, fonts, &text_bounds, parameters); if (cursor_enabled_) { DCHECK_EQ(lines_.size(), 1u);
diff --git a/chrome/browser/vr/elements/text.h b/chrome/browser/vr/elements/text.h index c51f325..84bc3e08dd 100644 --- a/chrome/browser/vr/elements/text.h +++ b/chrome/browser/vr/elements/text.h
@@ -69,6 +69,29 @@ typedef std::vector<TextFormattingAttribute> TextFormatting; +enum TextAlignment { + kTextAlignmentNone, + kTextAlignmentLeft, + kTextAlignmentCenter, + kTextAlignmentRight, +}; + +enum WrappingBehavior { + kWrappingBehaviorWrap, + kWrappingBehaviorNoWrap, +}; + +struct TextRenderParameters { + SkColor color = SK_ColorBLACK; + TextAlignment text_alignment = kTextAlignmentNone; + WrappingBehavior wrapping_behavior = kWrappingBehaviorNoWrap; + bool cursor_enabled = false; + int cursor_position = 0; + bool shadows_enabled = false; + SkColor shadow_color = SK_ColorBLACK; + float shadow_size = 10.0f; +}; + class Text : public TexturedElement { public: explicit Text(float font_height_dmms); @@ -87,7 +110,7 @@ // Formatting must be applied only to non-wrapping text elements. void SetFormatting(const TextFormatting& formatting); - void SetAlignment(UiTexture::TextAlignment alignment); + void SetAlignment(TextAlignment alignment); void SetLayoutMode(TextLayoutMode mode); // This text element does not typically feature a cursor, but since the cursor
diff --git a/chrome/browser/vr/elements/text_button.cc b/chrome/browser/vr/elements/text_button.cc new file mode 100644 index 0000000..145ee8b --- /dev/null +++ b/chrome/browser/vr/elements/text_button.cc
@@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/vr/elements/text_button.h" + +#include "base/bind_helpers.h" +#include "chrome/browser/vr/elements/rect.h" + +namespace vr { + +namespace { + +constexpr float kTextPaddingRatio = 0.7f; + +} // namespace + +TextButton::TextButton(float text_size, AudioDelegate* audio_delegate) + : Button(base::DoNothing(), audio_delegate) { + set_hover_offset(0.0f); + set_bounds_contain_children(true); + + // Add the text object to the button. + auto text = std::make_unique<Text>(text_size); + text->SetDrawPhase(kPhaseForeground); + text->SetType(kTypeButtonText); + text->SetLayoutMode(kSingleLine); + text->set_hit_testable(false); + text_ = text.get(); + background()->AddChild(std::move(text)); + + // Configure background to size with text. + background()->set_bounds_contain_children(true); + background()->set_contributes_to_parent_bounds(true); + background()->set_padding(text_size * kTextPaddingRatio, + text_size * kTextPaddingRatio); +} + +TextButton::~TextButton() = default; + +void TextButton::SetText(const base::string16& text) { + text_->SetText(text); +} + +void TextButton::OnSetColors(const ButtonColors& colors) { + if (!enabled()) { + text_->SetColor(colors.foreground_disabled); + } else { + text_->SetColor(colors.foreground); + } +} + +} // namespace vr
diff --git a/chrome/browser/vr/elements/text_button.h b/chrome/browser/vr/elements/text_button.h new file mode 100644 index 0000000..a353c2e3b --- /dev/null +++ b/chrome/browser/vr/elements/text_button.h
@@ -0,0 +1,34 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VR_ELEMENTS_TEXT_BUTTON_H_ +#define CHROME_BROWSER_VR_ELEMENTS_TEXT_BUTTON_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/vr/elements/button.h" +#include "chrome/browser/vr/elements/text.h" + +namespace vr { + +// TextButton is a Button that sizes itself to a supplied text string. +class TextButton : public Button { + public: + TextButton(float text_height, AudioDelegate* audio_delegate); + ~TextButton() override; + + void SetText(const base::string16& text); + + private: + void OnSetColors(const ButtonColors& colors) override; + + Text* text_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(TextButton); +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_ELEMENTS_TEXT_BUTTON_H_
diff --git a/chrome/browser/vr/elements/text_input.cc b/chrome/browser/vr/elements/text_input.cc index af7a6bc..0a9f41b 100644 --- a/chrome/browser/vr/elements/text_input.cc +++ b/chrome/browser/vr/elements/text_input.cc
@@ -28,7 +28,7 @@ text->set_x_centering(LEFT); text->SetSize(1, 1); text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth); - text->SetAlignment(UiTexture::kTextAlignmentLeft); + text->SetAlignment(kTextAlignmentLeft); hint_element_ = text.get(); this->AddChild(std::move(text)); @@ -42,7 +42,7 @@ text->set_bubble_events(true); text->SetSize(1, 1); text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth); - text->SetAlignment(UiTexture::kTextAlignmentLeft); + text->SetAlignment(kTextAlignmentLeft); text->SetCursorEnabled(true); text_element_ = text.get(); this->AddChild(std::move(text));
diff --git a/chrome/browser/vr/elements/ui_element_name.cc b/chrome/browser/vr/elements/ui_element_name.cc index ee0dc9f..a680b17 100644 --- a/chrome/browser/vr/elements/ui_element_name.cc +++ b/chrome/browser/vr/elements/ui_element_name.cc
@@ -42,7 +42,6 @@ "kCeiling", "kFloor", "kStars", - "kUpdateKeyboardPrompt", "kUrlBarPositioner", "kUrlBarDmmRoot", "kUrlBar", @@ -111,8 +110,6 @@ "kExitWarningText", "kExitWarningBackground", "kExitPrompt", - "kAudioPermissionPrompt", - "kAudioPermissionPromptBackplane", "kWebVrUrlToastTransientParent", "kWebVrUrlToast", "kWebVrExclusiveScreenToast",
diff --git a/chrome/browser/vr/elements/ui_element_name.h b/chrome/browser/vr/elements/ui_element_name.h index f85d765c..2e9e4af8 100644 --- a/chrome/browser/vr/elements/ui_element_name.h +++ b/chrome/browser/vr/elements/ui_element_name.h
@@ -41,7 +41,6 @@ kCeiling, kFloor, kStars, - kUpdateKeyboardPrompt, kUrlBarPositioner, kUrlBarDmmRoot, kUrlBar, @@ -110,8 +109,6 @@ kExitWarningText, kExitWarningBackground, kExitPrompt, - kAudioPermissionPrompt, - kAudioPermissionPromptBackplane, kWebVrUrlToastTransientParent, kWebVrUrlToast, kWebVrExclusiveScreenToast,
diff --git a/chrome/browser/vr/elements/ui_element_type.cc b/chrome/browser/vr/elements/ui_element_type.cc index 442ef95..69c9e7b 100644 --- a/chrome/browser/vr/elements/ui_element_type.cc +++ b/chrome/browser/vr/elements/ui_element_type.cc
@@ -16,6 +16,7 @@ "kTypeButtonBackground", "kTypeButtonForeground", "kTypeButtonHitTarget", + "kTypeButtonText", "kTypeHostedUiBackplane", "kTypeScaledDepthAdjuster", "kTypeOmniboxSuggestionBackground", @@ -27,6 +28,11 @@ "kTypeOmniboxSuggestionDescriptionText", "kTypePromptBackplane", "kTypePromptShadow", + "kTypePromptBackground", + "kTypePromptIcon", + "kTypePromptText", + "kTypePromptPrimaryButton", + "kTypePromptSecondaryButton", "kTypeSpacer", "kTypeTextInputHint", "kTypeTextInputText", @@ -43,7 +49,7 @@ static_assert( kNumUiElementTypes == arraysize(g_ui_element_type_strings), - "Mismatch between the kUiElementName enum and the corresponding array " + "Mismatch between the kUiElementType enum and the corresponding array " "of strings."); } // namespace
diff --git a/chrome/browser/vr/elements/ui_element_type.h b/chrome/browser/vr/elements/ui_element_type.h index 321a075..fdcc80e 100644 --- a/chrome/browser/vr/elements/ui_element_type.h +++ b/chrome/browser/vr/elements/ui_element_type.h
@@ -16,6 +16,7 @@ kTypeButtonBackground, kTypeButtonForeground, kTypeButtonHitTarget, + kTypeButtonText, kTypeHostedUiBackplane, kTypeScaledDepthAdjuster, kTypeOmniboxSuggestionBackground, @@ -27,6 +28,11 @@ kTypeOmniboxSuggestionDescriptionText, kTypePromptBackplane, kTypePromptShadow, + kTypePromptBackground, + kTypePromptIcon, + kTypePromptText, + kTypePromptPrimaryButton, + kTypePromptSecondaryButton, kTypeSpacer, kTypeTextInputHint, kTypeTextInputText,
diff --git a/chrome/browser/vr/elements/ui_texture.cc b/chrome/browser/vr/elements/ui_texture.cc index 8be24b2..398cadd 100644 --- a/chrome/browser/vr/elements/ui_texture.cc +++ b/chrome/browser/vr/elements/ui_texture.cc
@@ -4,42 +4,13 @@ #include "chrome/browser/vr/elements/ui_texture.h" -#include <set> -#include <string> -#include <vector> - -#include "base/i18n/char_iterator.h" -#include "base/i18n/rtl.h" -#include "base/strings/string_util.h" #include "base/trace_event/trace_event.h" -#include "chrome/browser/vr/font_fallback.h" -#include "third_party/icu/source/common/unicode/uscript.h" #include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/render_text.h" -#include "ui/gfx/shadow_value.h" -#include "ui/gfx/text_elider.h" #include "ui/gl/gl_bindings.h" namespace vr { -namespace { - -constexpr char kDefaultFontFamily[] = "sans-serif"; - -static bool force_font_fallback_failure_for_testing_ = false; - -std::set<UChar32> CollectDifferentChars(base::string16 text) { - std::set<UChar32> characters; - for (base::i18n::UTF16CharIterator it(&text); !it.end(); it.Advance()) { - characters.insert(it.get()); - } - return characters; -} - -} // namespace - UiTexture::UiTexture() = default; UiTexture::~UiTexture() = default; @@ -63,184 +34,6 @@ set_dirty(); } -std::vector<std::unique_ptr<gfx::RenderText>> UiTexture::PrepareDrawStringRect( - const base::string16& text, - const gfx::FontList& font_list, - SkColor color, - gfx::Rect* bounds, - UiTexture::TextAlignment text_alignment, - UiTexture::WrappingBehavior wrapping_behavior) { - TextRenderParameters parameters; - parameters.color = color; - parameters.text_alignment = text_alignment; - parameters.wrapping_behavior = wrapping_behavior; - return PrepareDrawStringRect(text, font_list, bounds, parameters); -} - -std::vector<std::unique_ptr<gfx::RenderText>> UiTexture::PrepareDrawStringRect( - const base::string16& text, - const gfx::FontList& font_list, - gfx::Rect* bounds, - const TextRenderParameters& parameters) { - DCHECK(bounds); - - std::vector<std::unique_ptr<gfx::RenderText>> lines; - - if (parameters.wrapping_behavior == kWrappingBehaviorWrap) { - DCHECK(!parameters.cursor_enabled); - - gfx::Rect rect(*bounds); - std::vector<base::string16> strings; - gfx::ElideRectangleText(text, font_list, bounds->width(), - bounds->height() ? bounds->height() : INT_MAX, - gfx::WRAP_LONG_WORDS, &strings); - - int height = 0; - int line_height = 0; - for (size_t i = 0; i < strings.size(); i++) { - std::unique_ptr<gfx::RenderText> render_text = CreateConfiguredRenderText( - strings[i], font_list, parameters.color, parameters.text_alignment, - parameters.shadows_enabled, parameters.shadow_color, - parameters.shadow_size); - - if (i == 0) { - // Measure line and center text vertically. - line_height = render_text->GetStringSize().height(); - rect.set_height(line_height); - if (bounds->height()) { - const int text_height = strings.size() * line_height; - rect += gfx::Vector2d(0, (bounds->height() - text_height) / 2); - } - } - - render_text->SetDisplayRect(rect); - height += line_height; - rect += gfx::Vector2d(0, line_height); - lines.push_back(std::move(render_text)); - } - - // Set calculated height. - if (bounds->height() == 0) - bounds->set_height(height); - } else { - std::unique_ptr<gfx::RenderText> render_text = CreateConfiguredRenderText( - text, font_list, parameters.color, parameters.text_alignment, - parameters.shadows_enabled, parameters.shadow_color, - parameters.shadow_size); - if (bounds->width() != 0 && !parameters.cursor_enabled) - render_text->SetElideBehavior(gfx::TRUNCATE); - if (parameters.cursor_enabled) { - render_text->SetCursorEnabled(true); - render_text->SetCursorPosition(parameters.cursor_position); - } - - if (bounds->width() == 0) - bounds->set_width(render_text->GetStringSize().width()); - if (bounds->height() == 0) - bounds->set_height(render_text->GetStringSize().height()); - - render_text->SetDisplayRect(*bounds); - lines.push_back(std::move(render_text)); - } - - if (parameters.shadows_enabled) { - bounds->Inset(-parameters.shadow_size, -parameters.shadow_size); - bounds->Offset(parameters.shadow_size, parameters.shadow_size); - } - - return lines; -} - -std::unique_ptr<gfx::RenderText> UiTexture::CreateRenderText() { - auto render_text = gfx::RenderText::CreateHarfBuzzInstance(); - - // Disable the cursor to avoid reserving width for a trailing caret. - render_text->SetCursorEnabled(false); - - // Subpixel rendering is counterproductive when drawing VR textures. - render_text->set_subpixel_rendering_suppressed(true); - - return render_text; -} - -std::unique_ptr<gfx::RenderText> UiTexture::CreateConfiguredRenderText( - const base::string16& text, - const gfx::FontList& font_list, - SkColor color, - UiTexture::TextAlignment text_alignment, - bool shadows_enabled, - SkColor shadow_color, - float shadow_size) { - std::unique_ptr<gfx::RenderText> render_text(CreateRenderText()); - render_text->SetText(text); - render_text->SetFontList(font_list); - render_text->SetColor(color); - if (shadows_enabled) { - render_text->set_shadows( - {gfx::ShadowValue({0, 0}, shadow_size, shadow_color)}); - } - - switch (text_alignment) { - case UiTexture::kTextAlignmentNone: - break; - case UiTexture::kTextAlignmentLeft: - render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); - break; - case UiTexture::kTextAlignmentRight: - render_text->SetHorizontalAlignment(gfx::ALIGN_RIGHT); - break; - case UiTexture::kTextAlignmentCenter: - render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER); - break; - } - - const int font_style = font_list.GetFontStyle(); - render_text->SetStyle(gfx::ITALIC, (font_style & gfx::Font::ITALIC) != 0); - render_text->SetStyle(gfx::UNDERLINE, - (font_style & gfx::Font::UNDERLINE) != 0); - render_text->SetWeight(font_list.GetFontWeight()); - - return render_text; -} - -bool UiTexture::IsRTL() { - return base::i18n::IsRTL(); -} - -bool UiTexture::GetFontList(const std::string& preferred_font_name, - int font_size, - base::string16 text, - gfx::FontList* font_list) { - if (force_font_fallback_failure_for_testing_) - return false; - - gfx::Font preferred_font(preferred_font_name, font_size); - std::vector<gfx::Font> fonts{preferred_font}; - - std::set<std::string> names; - // TODO(acondor): Query BrowserProcess to obtain the application locale. - for (UChar32 c : CollectDifferentChars(text)) { - std::string name; - bool found_name = GetFallbackFontNameForChar(preferred_font, c, "", &name); - if (!found_name) - return false; - if (!name.empty()) - names.insert(name); - } - for (const auto& name : names) { - DCHECK(!name.empty()); - fonts.push_back(gfx::Font(name, font_size)); - } - *font_list = gfx::FontList(fonts); - return true; -} - -bool UiTexture::GetDefaultFontList(int font_size, - base::string16 text, - gfx::FontList* font_list) { - return GetFontList(kDefaultFontFamily, font_size, text, font_list); -} - SkColor UiTexture::foreground_color() const { DCHECK(foreground_color_); return foreground_color_.value(); @@ -265,8 +58,4 @@ set_dirty(); } -void UiTexture::SetForceFontFallbackFailureForTesting(bool force) { - force_font_fallback_failure_for_testing_ = force; -} - } // namespace vr
diff --git a/chrome/browser/vr/elements/ui_texture.h b/chrome/browser/vr/elements/ui_texture.h index 87c617f..eee4a1a 100644 --- a/chrome/browser/vr/elements/ui_texture.h +++ b/chrome/browser/vr/elements/ui_texture.h
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -20,9 +19,7 @@ namespace gfx { -class FontList; class PointF; -class RenderText; } // namespace gfx @@ -53,45 +50,6 @@ void SetForegroundColor(SkColor color); void SetBackgroundColor(SkColor color); - // This function sets |font_list| to a list of available fonts for |text|. If - // no font supports |text|, it returns false and leave |font_list| untouched. - static bool GetDefaultFontList(int font_size, - base::string16 text, - gfx::FontList* font_list); - - // This function sets |font_list| to a list of available fonts for |text|. If - // the font with |preferred_font_name| is available and supports |text|, - // |font_list| will be configured to use the preferred font instead of default - // font. If no font supports |text|, it returns false and leave |font_list| - // untouched. - static bool GetFontList(const std::string& preferred_font_name, - int font_size, - base::string16 text, - gfx::FontList* font_list); - - enum TextAlignment { - kTextAlignmentNone, - kTextAlignmentLeft, - kTextAlignmentCenter, - kTextAlignmentRight, - }; - - enum WrappingBehavior { - kWrappingBehaviorWrap, - kWrappingBehaviorNoWrap, - }; - - struct TextRenderParameters { - SkColor color = SK_ColorBLACK; - TextAlignment text_alignment = kTextAlignmentNone; - WrappingBehavior wrapping_behavior = kWrappingBehaviorNoWrap; - bool cursor_enabled = false; - int cursor_position = 0; - bool shadows_enabled = false; - SkColor shadow_color = SK_ColorBLACK; - float shadow_size = 10.0f; - }; - protected: template <typename T> void SetAndDirty(T* target, const T& value) { @@ -100,42 +58,6 @@ *target = value; } - // Prepares a set of RenderText objects with the given parameters. - // Attempts to fit the text within the provided size. |flags| specifies how - // the text should be rendered. If multiline is requested and provided height - // is 0, it will be set to the minimum needed to fit the whole text. If - // multiline is not requested and provided width is 0, it will be set to the - // minimum needed to fit the whole text. - static std::vector<std::unique_ptr<gfx::RenderText>> PrepareDrawStringRect( - const base::string16& text, - const gfx::FontList& font_list, - gfx::Rect* bounds, - const TextRenderParameters& parameters); - - // Deprecated legacy text prep function. UI elements that use this routine - // should migrate to use Text elements, rather than drawing text directly. - static std::vector<std::unique_ptr<gfx::RenderText>> PrepareDrawStringRect( - const base::string16& text, - const gfx::FontList& font_list, - SkColor color, - gfx::Rect* bounds, - TextAlignment text_alignment, - WrappingBehavior wrapping_behavior); - - static std::unique_ptr<gfx::RenderText> CreateRenderText(); - - static std::unique_ptr<gfx::RenderText> CreateConfiguredRenderText( - const base::string16& text, - const gfx::FontList& font_list, - SkColor color, - TextAlignment text_alignment, - bool shadows_enabled, - SkColor shadow_color, - float shadow_size); - - static bool IsRTL(); - static void SetForceFontFallbackFailureForTesting(bool force); - void set_dirty() { measured_ = false; dirty_ = true;
diff --git a/chrome/browser/vr/model/modal_prompt_type.cc b/chrome/browser/vr/model/modal_prompt_type.cc index dc0387c..33d3853 100644 --- a/chrome/browser/vr/model/modal_prompt_type.cc +++ b/chrome/browser/vr/model/modal_prompt_type.cc
@@ -22,6 +22,8 @@ return UiUnsupportedMode::kNeedsKeyboardUpdate; case kModalPromptTypeNone: return UiUnsupportedMode::kCount; + case kNumModalPromptTypes: + break; } NOTREACHED(); return UiUnsupportedMode::kCount;
diff --git a/chrome/browser/vr/model/modal_prompt_type.h b/chrome/browser/vr/model/modal_prompt_type.h index f16f04f..0556791 100644 --- a/chrome/browser/vr/model/modal_prompt_type.h +++ b/chrome/browser/vr/model/modal_prompt_type.h
@@ -16,6 +16,8 @@ kModalPromptTypeExitVRForVoiceSearchRecordAudioOsPermission, kModalPromptTypeGenericUnsupportedFeature, kModalPromptTypeUpdateKeyboard, + + kNumModalPromptTypes }; UiUnsupportedMode GetReasonForPrompt(ModalPromptType prompt);
diff --git a/chrome/browser/vr/test/mock_browser_ui_interface.h b/chrome/browser/vr/test/mock_browser_ui_interface.h index 161cac2..d427c70d 100644 --- a/chrome/browser/vr/test/mock_browser_ui_interface.h +++ b/chrome/browser/vr/test/mock_browser_ui_interface.h
@@ -46,6 +46,7 @@ void(int id, bool incognito, const base::string16& title)); MOCK_METHOD2(RemoveTab, void(int id, bool incognito)); MOCK_METHOD0(RemoveAllTabs, void()); + MOCK_METHOD2(OnTabSelected, void(int id, bool incognito)); private: DISALLOW_COPY_AND_ASSIGN(MockBrowserUiInterface);
diff --git a/chrome/browser/vr/test/mock_ui_browser_interface.h b/chrome/browser/vr/test/mock_ui_browser_interface.h index 23b2d23..28e58fb 100644 --- a/chrome/browser/vr/test/mock_ui_browser_interface.h +++ b/chrome/browser/vr/test/mock_ui_browser_interface.h
@@ -23,6 +23,7 @@ MOCK_METHOD0(NavigateForward, void()); MOCK_METHOD0(ReloadTab, void()); MOCK_METHOD1(OpenNewTab, void(bool)); + MOCK_METHOD2(SelectTab, void(int id, bool incognito)); MOCK_METHOD0(OpenBookmarks, void()); MOCK_METHOD0(OpenRecentTabs, void()); MOCK_METHOD0(OpenHistory, void()); @@ -41,8 +42,8 @@ MOCK_METHOD1(SetVoiceSearchActive, void(bool active)); MOCK_METHOD1(StartAutocomplete, void(const AutocompleteRequest& request)); MOCK_METHOD0(StopAutocomplete, void()); - MOCK_METHOD0(ShowPageInfo, void()); MOCK_METHOD0(LoadAssets, void()); + MOCK_METHOD0(ShowPageInfo, void()); private: DISALLOW_COPY_AND_ASSIGN(MockUiBrowserInterface);
diff --git a/chrome/browser/vr/test/ui_test.cc b/chrome/browser/vr/test/ui_test.cc index cf1e997f..e2c08be 100644 --- a/chrome/browser/vr/test/ui_test.cc +++ b/chrome/browser/vr/test/ui_test.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/vr/test/constants.h" #include "chrome/browser/vr/test/fake_ui_element_renderer.h" #include "chrome/browser/vr/ui.h" +#include "chrome/browser/vr/ui_renderer.h" #include "chrome/browser/vr/ui_scene.h" #include "chrome/browser/vr/ui_scene_creator.h" #include "third_party/blink/public/platform/web_gesture_event.h" @@ -252,4 +253,32 @@ *background_color = color; } +void UiTest::ClickElement(UiElement* element) { + // Synthesize a controller vector targeting the element. + gfx::Point3F target; + element->ComputeTargetWorldSpaceTransform().TransformPoint(&target); + gfx::Point3F origin; + gfx::Vector3dF direction(target - origin); + direction.GetNormalized(&direction); + + RenderInfo render_info; + ReticleModel reticle_model; + GestureList gesture_list; + ControllerModel controller_model; + controller_model.laser_direction = direction; + controller_model.laser_origin = origin; + + controller_model.touchpad_button_state = UiInputManager::ButtonState::DOWN; + ui_->input_manager()->HandleInput(current_time_, render_info, + controller_model, &reticle_model, + &gesture_list); + OnBeginFrame(); + + controller_model.touchpad_button_state = UiInputManager::ButtonState::UP; + ui_->input_manager()->HandleInput(current_time_, render_info, + controller_model, &reticle_model, + &gesture_list); + OnBeginFrame(); +} + } // namespace vr
diff --git a/chrome/browser/vr/test/ui_test.h b/chrome/browser/vr/test/ui_test.h index 2d488e291..1e348eb6 100644 --- a/chrome/browser/vr/test/ui_test.h +++ b/chrome/browser/vr/test/ui_test.h
@@ -106,6 +106,11 @@ void GetBackgroundColor(SkColor* background_color) const; + // Synthesize a controller orientation that intersects the element, and cycle + // the controller button. This offers a reasonably correct means of testing + // clicks on elements, that's true to hit testability, visbility, etc. + void ClickElement(UiElement* element); + std::unique_ptr<Ui> ui_; std::unique_ptr<MockUiBrowserInterface> browser_; MockContentInputDelegate* content_input_delegate_ = nullptr;
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index 94e85e2..fdf2a6ef 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -59,6 +59,10 @@ constexpr gfx::Vector3dF kLaserLocalOffset = {0.f, -0.0075f, -0.05f}; constexpr float kControllerScaleFactor = 1.5f; constexpr float kTouchpadPositionDelta = 0.05f; +const float kVerticalScrollScaleFactor = + -8.0f / ui::MouseWheelEvent::kWheelDelta; +const float kHorizontalScrollScaleFactor = + 60.0f / ui::MouseWheelEvent::kWheelDelta; constexpr gfx::PointF kInitialTouchPosition = {0.5f, 0.5f}; void RotateToward(const gfx::Vector3dF& fwd, gfx::Transform* transform) { @@ -75,15 +79,20 @@ out_image->get()); } -GestureList CreateScrollGestureList(blink::WebInputEvent::Type type, - const gfx::Vector2dF& delta) { - auto event = std::make_unique<blink::WebGestureEvent>(); - event->SetType(type); - event->data.scroll_update.delta_x = delta.x(); - event->data.scroll_update.delta_y = delta.y(); - GestureList gesture_list; - gesture_list.push_back(std::move(event)); - return gesture_list; +GestureList CreateScrollGestureEventList(blink::WebGestureEvent::Type type) { + auto gesture = std::make_unique<blink::WebGestureEvent>(); + gesture->SetType(type); + GestureList list; + list.push_back(std::move(gesture)); + return list; +} + +GestureList CreateScrollGestureEventList(blink::WebGestureEvent::Type type, + const gfx::Vector2dF& delta) { + auto list = CreateScrollGestureEventList(type); + list.front()->data.scroll_update.delta_x = delta.x(); + list.front()->data.scroll_update.delta_y = delta.y(); + return list; } } // namespace @@ -250,32 +259,16 @@ case ui::DomCode::US_T: touching_touchpad_ = !touching_touchpad_; break; - case ui::DomCode::US_Q: + case ui::DomCode::US_Q: { + auto mode = model_->active_modal_prompt_type; model_->active_modal_prompt_type = - kModalPromptTypeGenericUnsupportedFeature; + static_cast<ModalPromptType>((mode + 1) % kNumModalPromptTypes); model_->push_mode(kModeModalPrompt); break; + } case ui::DomCode::US_L: model_->standalone_vr_device = !model_->standalone_vr_device; break; - case ui::DomCode::ARROW_RIGHT: - gesture_lists_.push(CreateScrollGestureList( - blink::WebInputEvent::kGestureScrollBegin, gfx::Vector2dF(0, 0))); - gesture_lists_.push( - CreateScrollGestureList(blink::WebInputEvent::kGestureScrollUpdate, - gfx::Vector2dF(-100, 0))); - gesture_lists_.push(CreateScrollGestureList( - blink::WebInputEvent::kGestureScrollEnd, gfx::Vector2dF(0, 0))); - break; - case ui::DomCode::ARROW_LEFT: - gesture_lists_.push(CreateScrollGestureList( - blink::WebInputEvent::kGestureScrollBegin, gfx::Vector2dF(0, 0))); - gesture_lists_.push( - CreateScrollGestureList(blink::WebInputEvent::kGestureScrollUpdate, - gfx::Vector2dF(100, 0))); - gesture_lists_.push(CreateScrollGestureList( - blink::WebInputEvent::kGestureScrollEnd, gfx::Vector2dF(0, 0))); - break; default: break; } @@ -286,13 +279,29 @@ int direction = base::ClampToRange(event->AsMouseWheelEvent()->y_offset(), -1, 1); if (event->IsControlDown()) { + view_scale_factor_ *= (1 + direction * kViewScaleAdjustmentFactor); + view_scale_factor_ = base::ClampToRange( + view_scale_factor_, kMinViewScaleFactor, kMaxViewScaleFactor); + } else if (model_->reposition_window_enabled()) { touchpad_touch_position_.set_y(base::ClampToRange( touchpad_touch_position_.y() + kTouchpadPositionDelta * direction, 0.0f, 1.0f)); } else { - view_scale_factor_ *= (1 + direction * kViewScaleAdjustmentFactor); - view_scale_factor_ = base::ClampToRange( - view_scale_factor_, kMinViewScaleFactor, kMaxViewScaleFactor); + gesture_lists_.push(CreateScrollGestureEventList( + blink::WebGestureEvent::kGestureScrollBegin)); + + auto offset = gfx::Vector2dF(event->AsMouseWheelEvent()->offset()); + if (event->IsShiftDown()) { + offset.Scale(kHorizontalScrollScaleFactor); + offset = gfx::Vector2dF(offset.y(), offset.x()); + } else { + offset.Scale(kVerticalScrollScaleFactor); + } + gesture_lists_.push(CreateScrollGestureEventList( + blink::WebGestureEvent::kGestureScrollUpdate, offset)); + + gesture_lists_.push(CreateScrollGestureEventList( + blink::WebGestureEvent::kGestureScrollEnd)); } return; } @@ -396,7 +405,6 @@ // Hit testing is done in terms of this synthesized controller model. if (gesture_lists_.empty()) { gesture_lists_.push(GestureList()); - gesture_lists_.back().push_back(std::make_unique<blink::WebGestureEvent>()); } ReticleModel reticle_model; ui_->input_manager()->HandleInput(current_time, render_info, controller_model, @@ -571,6 +579,10 @@ ui_->AddOrUpdateTab(tab_id_++, incognito, base::UTF8ToUTF16("test")); } +void VrTestContext::SelectTab(int id, bool incognito) { + ui_->OnTabSelected(id, incognito); +} + void VrTestContext::OpenBookmarks() {} void VrTestContext::OpenRecentTabs() {} void VrTestContext::OpenHistory() {}
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h index 691423d..a2dca7a 100644 --- a/chrome/browser/vr/testapp/vr_test_context.h +++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -48,6 +48,7 @@ void NavigateForward() override; void ReloadTab() override; void OpenNewTab(bool incognito) override; + void SelectTab(int id, bool incognito) override; void OpenBookmarks() override; void OpenRecentTabs() override; void OpenHistory() override;
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index 8922d0a..0238224 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -12,7 +12,6 @@ #include "chrome/browser/vr/content_input_delegate.h" #include "chrome/browser/vr/cpu_surface_provider.h" #include "chrome/browser/vr/elements/content_element.h" -#include "chrome/browser/vr/elements/prompt.h" #include "chrome/browser/vr/elements/text_input.h" #include "chrome/browser/vr/ganesh_surface_provider.h" #include "chrome/browser/vr/keyboard_delegate.h" @@ -268,6 +267,10 @@ model_->incognito_tabs.clear(); } +void Ui::OnTabSelected(int id, bool incognito) { + model_->pop_mode(kModeTabsView); +} + bool Ui::CanSendWebVrVSync() { return model_->web_vr_enabled() && !model_->web_vr.awaiting_min_splash_screen_duration() && @@ -542,14 +545,14 @@ void Ui::AcceptDoffPromptForTesting() { DCHECK(model_->active_modal_prompt_type != kModalPromptTypeNone); - if (model_->active_modal_prompt_type == - kModalPromptTypeExitVRForVoiceSearchRecordAudioOsPermission) { - static_cast<Prompt*>(scene_->GetUiElementByName(kAudioPermissionPrompt)) - ->ClickPrimaryButtonForTesting(); - } else { - static_cast<Prompt*>(scene_->GetUiElementByName(kExitPrompt)) - ->ClickSecondaryButtonForTesting(); - } + auto* prompt = scene_->GetUiElementByName(kExitPrompt); + DCHECK(prompt); + auto* button = prompt->GetDescendantByType(kTypePromptSecondaryButton); + DCHECK(button); + button->OnHoverEnter({0.5f, 0.5f}); + button->OnButtonDown({0.5f, 0.5f}); + button->OnButtonUp({0.5f, 0.5f}); + button->OnHoverLeave(); } void Ui::PerformUiActionForTesting(UiTestInput test_input) {
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h index d12453f..0c6cdfc 100644 --- a/chrome/browser/vr/ui.h +++ b/chrome/browser/vr/ui.h
@@ -116,6 +116,7 @@ const base::string16& title) override; void RemoveTab(int id, bool incognito) override; void RemoveAllTabs() override; + void OnTabSelected(int id, bool incognito) override; // TODO(ymalik): We expose this to stop sending VSync to the WebVR page until // the splash screen has been visible for its minimum duration. The visibility
diff --git a/chrome/browser/vr/ui_browser_interface.h b/chrome/browser/vr/ui_browser_interface.h index 6c2a3c61..c30db2b 100644 --- a/chrome/browser/vr/ui_browser_interface.h +++ b/chrome/browser/vr/ui_browser_interface.h
@@ -33,6 +33,7 @@ virtual void NavigateForward() = 0; virtual void ReloadTab() = 0; virtual void OpenNewTab(bool incognito) = 0; + virtual void SelectTab(int id, bool incognito) = 0; virtual void OpenBookmarks() = 0; virtual void OpenRecentTabs() = 0; virtual void OpenHistory() = 0;
diff --git a/chrome/browser/vr/ui_input_manager_unittest.cc b/chrome/browser/vr/ui_input_manager_unittest.cc index 091aa6e..5cc0b89 100644 --- a/chrome/browser/vr/ui_input_manager_unittest.cc +++ b/chrome/browser/vr/ui_input_manager_unittest.cc
@@ -10,7 +10,7 @@ #include "base/time/time.h" #include "cc/test/geometry_test_utils.h" #include "chrome/browser/vr/content_input_delegate.h" -#include "chrome/browser/vr/elements/prompt.h" +#include "chrome/browser/vr/elements/invisible_hit_target.h" #include "chrome/browser/vr/elements/rect.h" #include "chrome/browser/vr/elements/ui_element.h" #include "chrome/browser/vr/model/model.h" @@ -449,8 +449,8 @@ // Even if the reticle is over the URL bar, the backplane should be in front // and should be hit. ASSERT_NE(0, reticle_model.target_element_id); - auto* backplane = scene_->GetUiElementByName(kAudioPermissionPromptBackplane); - EXPECT_EQ(backplane->type(), kTypePromptBackplane); + auto* prompt = scene_->GetUiElementByName(kExitPrompt); + auto* backplane = prompt->GetDescendantByType(kTypePromptBackplane); EXPECT_EQ(backplane->id(), reticle_model.target_element_id); }
diff --git a/chrome/browser/vr/ui_scene_constants.h b/chrome/browser/vr/ui_scene_constants.h index 183c345..90b5da3345 100644 --- a/chrome/browser/vr/ui_scene_constants.h +++ b/chrome/browser/vr/ui_scene_constants.h
@@ -140,7 +140,6 @@ static constexpr float kTimeoutMessageIconWidthDMM = 0.056f; static constexpr float kTimeoutMessageIconHeightDMM = 0.056f; static constexpr float kTimeoutMessageTextFontHeightDMM = 0.022f; -static constexpr float kTimeoutMessageTextHeightDMM = 0.056f; static constexpr float kTimeoutMessageTextWidthDMM = 0.4f; static constexpr float kTimeoutButtonDepthOffset = -0.1f; @@ -148,7 +147,6 @@ static constexpr float kWebVrTimeoutMessageButtonDiameterDMM = 0.096f; static constexpr float kTimeoutButtonTextWidthDMM = 0.058f; -static constexpr float kTimeoutButtonTextHeightDMM = 0.024f; static constexpr float kTimeoutButtonTextVerticalOffsetDMM = 0.024f; static constexpr float kHostedUiHeightRatio = 0.6f; @@ -210,15 +208,6 @@ static constexpr float kKeyboardVerticalOffsetDMM = -0.45f; static constexpr float kKeyboardWebInputOffset = 1.2f; -static constexpr float kSnackbarDistance = 1.5f; -static constexpr float kSnackbarAngle = -gfx::DegToRad(34.0f); -static constexpr float kSnackbarPaddingDMM = 0.032f; -static constexpr float kSnackbarIconWidthDMM = 0.034f; -static constexpr float kSnackbarFontHeightDMM = 0.024f; -static constexpr float kSnackbarHeightDMM = 0.08f; -static constexpr float kSnackbarMoveInAngle = -base::kPiFloat / 10; -static constexpr int kSnackbarTransitionDurationMs = 300; - static constexpr float kControllerLabelSpacerSize = 0.025f; static constexpr float kControllerLabelLayoutMargin = -0.005f; static constexpr float kControllerLabelCalloutWidth = 0.02f; @@ -262,11 +251,19 @@ static constexpr int kWebVrPermissionOffsetMs = 250; static constexpr int kWebVrPermissionAnimationDurationMs = 750; -static constexpr float kPromptWidthDMM = 0.63f; -static constexpr float kPromptHeightDMM = 0.218f; static constexpr float kPromptVerticalOffsetDMM = -0.1f; static constexpr float kPromptShadowOffsetDMM = 0.1f; static constexpr float kPromptDistance = 2.4f; +static constexpr float kPromptPadding = 0.028f; +static constexpr float kPromptCornerRadius = 0.006f; +static constexpr float kPromptTextWidth = 0.522f; +static constexpr float kPromptFontSize = 0.028f; +static constexpr float kPromptIconSize = 0.042f; +static constexpr float kPromptButtonCornerRadius = 0.0035f; +static constexpr float kPromptIconTextGap = 0.010f; +static constexpr float kPromptMessageButtonGap = 0.056f; +static constexpr float kPromptButtonTextSize = 0.024f; +static constexpr float kPromptButtonGap = 0.014f; static constexpr float kRepositionCursorBackgroundSize = 1.85f; static constexpr float kRepositionCursorSize = 1.5f;
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index d02ebd33..f780a83 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -38,7 +38,6 @@ #include "chrome/browser/vr/elements/oval.h" #include "chrome/browser/vr/elements/paged_grid_layout.h" #include "chrome/browser/vr/elements/paged_scroll_view.h" -#include "chrome/browser/vr/elements/prompt.h" #include "chrome/browser/vr/elements/rect.h" #include "chrome/browser/vr/elements/repositioner.h" #include "chrome/browser/vr/elements/resizer.h" @@ -46,6 +45,7 @@ #include "chrome/browser/vr/elements/scaled_depth_adjuster.h" #include "chrome/browser/vr/elements/spinner.h" #include "chrome/browser/vr/elements/text.h" +#include "chrome/browser/vr/elements/text_button.h" #include "chrome/browser/vr/elements/text_input.h" #include "chrome/browser/vr/elements/throbber.h" #include "chrome/browser/vr/elements/transient_element.h" @@ -166,7 +166,7 @@ content_text->SetType(kTypeOmniboxSuggestionContentText); content_text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth); content_text->SetFieldWidth(kSuggestionTextFieldWidthDMM); - content_text->SetAlignment(UiTexture::kTextAlignmentLeft); + content_text->SetAlignment(kTextAlignmentLeft); Text* p_content_text = content_text.get(); auto description_text = @@ -175,7 +175,7 @@ description_text->SetType(kTypeOmniboxSuggestionDescriptionText); description_text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth); description_text->SetFieldWidth(kSuggestionTextFieldWidthDMM); - description_text->SetAlignment(UiTexture::kTextAlignmentLeft); + description_text->SetAlignment(kTextAlignmentLeft); Text* p_description_text = description_text.get(); auto text_layout = std::make_unique<LinearLayout>(LinearLayout::kDown); @@ -280,12 +280,15 @@ Model* model, bool incognito, PagedGridLayout* tabs_view, + AudioDelegate* audio_delegate, + UiBrowserInterface* browser, TabBinding* element_binding) { - auto item = Create<Rect>(kNone, kPhaseForeground); - item->SetColor(ColorScheme::GetColorScheme(incognito - ? ColorScheme::kModeIncognito - : ColorScheme::kModeNormal) - .tab_item_background); + auto item = Create<Button>(kNone, kPhaseForeground, base::RepeatingClosure(), + audio_delegate); + item->SetButtonColors( + ColorScheme::GetColorScheme(incognito ? ColorScheme::kModeIncognito + : ColorScheme::kModeNormal) + .disc_button_colors); item->SetSize(kTabItemWidthDMM, kTabItemHeightDMM); item->SetTransitionedProperties({OPACITY}); item->set_corner_radius(kTabItemCornerRadiusDMM); @@ -296,20 +299,39 @@ }, base::Unretained(tabs_view), base::Unretained(item.get())), VR_BIND_LAMBDA( - [](UiElement* item, const PagedGridLayout::PageState& page_state) { + [](Button* item, const PagedGridLayout::PageState& page_state) { switch (page_state) { case PagedGridLayout::kActive: item->SetOpacity(kTabsViewActivePageOpacity); + item->SetEnabled(true); break; case PagedGridLayout::kInactive: item->SetOpacity(kTabsViewInactivePageOpacity); + item->SetEnabled(false); break; default: item->SetOpacity(kTabsViewHiddenPageOpacity); + item->SetEnabled(false); break; } }, base::Unretained(item.get())))); + element_binding->bindings().push_back(std::make_unique<Binding<int>>( + VR_BIND_LAMBDA( + [](TabBinding* element_binding) { + return element_binding->model()->id; + }, + base::Unretained(element_binding)), + VR_BIND_LAMBDA( + [](Button* item, UiBrowserInterface* browser, bool incognito, + const int& id) { + item->set_click_handler(base::BindRepeating( + [](UiBrowserInterface* browser, int id, bool incognito) { + browser->SelectTab(id, incognito); + }, + base::Unretained(browser), id, incognito)); + }, + base::Unretained(item.get()), base::Unretained(browser), incognito))); // TODO(crbug.com/838937): This is just a placeholder text. Replace with // proper tab item. @@ -324,7 +346,7 @@ ? ColorScheme::kModeIncognito : ColorScheme::kModeNormal) .tab_item_text); - item->AddChild(std::move(text)); + item->background()->AddChild(std::move(text)); scene->AddUiElement(tabs_view, std::move(item)); } @@ -352,58 +374,109 @@ return spacer; } -std::pair<std::unique_ptr<UiElement>, Prompt*> CreatePrompt( - UiElementName name, - UiElementName backplane_name, - Model* model, - int content_message_id, - const gfx::VectorIcon& icon, - int primary_button_message_id, - int secondary_button_message_id, - const Prompt::PromptCallback& result_callback) { - auto prompt = Create<Prompt>(name, kPhaseForeground, 1024, content_message_id, - icon, primary_button_message_id, - secondary_button_message_id, result_callback); - auto* prompt_ptr = prompt.get(); - prompt->SetDrawPhase(kPhaseForeground); - prompt->SetTranslate(0, 0, kPromptShadowOffsetDMM); - prompt->SetSize(kPromptWidthDMM, kPromptHeightDMM); - prompt->set_hit_testable(true); - VR_BIND_BUTTON_COLORS(model, prompt.get(), +std::unique_ptr<UiElement> CreatePrompt(Model* model) { + auto primary_button = Create<TextButton>(kNone, kPhaseForeground, + kPromptButtonTextSize, nullptr); + primary_button->SetType(kTypePromptPrimaryButton); + primary_button->set_corner_radius(kPromptButtonCornerRadius); + VR_BIND_BUTTON_COLORS(model, primary_button.get(), &ColorScheme::modal_prompt_primary_button_colors, - &Prompt::SetPrimaryButtonColors); - VR_BIND_BUTTON_COLORS(model, prompt.get(), - &ColorScheme::modal_prompt_secondary_button_colors, - &Prompt::SetSecondaryButtonColors); - VR_BIND_COLOR(model, prompt.get(), &ColorScheme::modal_prompt_icon_foreground, - &Prompt::SetIconColor); - VR_BIND_COLOR(model, prompt.get(), &ColorScheme::modal_prompt_background, - &TexturedElement::SetBackgroundColor); - VR_BIND_COLOR(model, prompt.get(), &ColorScheme::modal_prompt_foreground, - &TexturedElement::SetForegroundColor); + &Button::SetButtonColors); - // Place an invisible but hittable plane behind the exit prompt, to keep the - // reticle roughly planar with the content if near content. - auto backplane = Create<InvisibleHitTarget>(backplane_name, kPhaseForeground); - backplane->SetType(kTypePromptBackplane); - backplane->SetSize(kBackplaneSize, kBackplaneSize); - backplane->SetTranslate(0, kPromptVerticalOffsetDMM, 0); - backplane->SetTransitionedProperties({OPACITY}); - EventHandlers event_handlers; - event_handlers.button_up = base::BindRepeating( - [](Prompt* prompt) { prompt->Cancel(); }, base::Unretained(prompt.get())); - backplane->set_event_handlers(event_handlers); + auto secondary_button = Create<TextButton>(kNone, kPhaseForeground, + kPromptButtonTextSize, nullptr); + secondary_button->SetType(kTypePromptSecondaryButton); + secondary_button->set_corner_radius(kPromptButtonCornerRadius); + VR_BIND_BUTTON_COLORS(model, secondary_button.get(), + &ColorScheme::modal_prompt_secondary_button_colors, + &Button::SetButtonColors); + + auto button_layout = + Create<LinearLayout>(kNone, kPhaseNone, LinearLayout::kLeft); + button_layout->AddChild(std::move(primary_button)); + button_layout->AddChild(std::move(secondary_button)); + button_layout->set_margin(kPromptButtonGap); + button_layout->set_x_anchoring(RIGHT); + + auto icon = Create<VectorIcon>(kNone, kPhaseForeground, 100); + icon->SetType(kTypePromptIcon); + icon->SetSize(kPromptIconSize, kPromptIconSize); + icon->set_y_anchoring(TOP); + VR_BIND_COLOR(model, icon.get(), &ColorScheme::modal_prompt_icon_foreground, + &VectorIcon::SetColor); + + auto text = Create<Text>(kNone, kPhaseForeground, kPromptFontSize); + text->SetType(kTypePromptText); + text->SetLayoutMode(kMultiLineFixedWidth); + text->SetAlignment(kTextAlignmentLeft); + text->SetFieldWidth(kPromptTextWidth); + VR_BIND_COLOR(model, text.get(), &ColorScheme::modal_prompt_foreground, + &Text::SetColor); + + // This spacer's padding ensures that the top line of text is aligned with the + // icon even in the multi-line case. + auto text_spacer = CreateSpacer(0, 0); + text_spacer->set_bounds_contain_children(true); + text_spacer->set_padding(0, (kPromptIconSize - kPromptFontSize) / 2, 0, 0); + text_spacer->set_y_anchoring(TOP); + text_spacer->AddChild(std::move(text)); + + auto message_layout = + Create<LinearLayout>(kNone, kPhaseNone, LinearLayout::kRight); + message_layout->set_margin(kPromptIconTextGap); + message_layout->AddChild(std::move(icon)); + message_layout->AddChild(std::move(text_spacer)); + + auto prompt_layout = + Create<LinearLayout>(kNone, kPhaseNone, LinearLayout::kDown); + prompt_layout->set_margin(kPromptMessageButtonGap); + prompt_layout->AddChild(std::move(message_layout)); + prompt_layout->AddChild(std::move(button_layout)); + + auto background = Create<Rect>(kNone, kPhaseForeground); + background->SetType(kTypePromptBackground); + background->set_bounds_contain_children(true); + background->set_hit_testable(true); + background->set_padding(kPromptPadding, kPromptPadding); + background->SetTranslate(0, 0, kPromptShadowOffsetDMM); + background->set_corner_radius(kPromptCornerRadius); + background->AddChild(std::move(prompt_layout)); + VR_BIND_COLOR(model, background.get(), &ColorScheme::modal_prompt_background, + &Rect::SetColor); auto shadow = Create<Shadow>(kNone, kPhaseForeground); shadow->SetType(kTypePromptShadow); - shadow->AddChild(std::move(prompt)); + shadow->AddChild(std::move(background)); + + // Place an invisible but hittable plane behind the exit prompt, to keep the + // reticle roughly planar with the content if near content. + auto backplane = Create<InvisibleHitTarget>(kNone, kPhaseForeground); + backplane->SetType(kTypePromptBackplane); + backplane->SetTranslate(0, kPromptVerticalOffsetDMM, 0); + backplane->SetSize(kBackplaneSize, kBackplaneSize); + backplane->SetTransitionedProperties({OPACITY}); backplane->AddChild(std::move(shadow)); auto scaler = Create<ScaledDepthAdjuster>(kNone, kPhaseNone, kPromptDistance); scaler->SetType(kTypeScaledDepthAdjuster); scaler->AddChild(std::move(backplane)); scaler->set_contributes_to_parent_bounds(false); - return {std::move(scaler), prompt_ptr}; + return scaler; +} + +base::RepeatingCallback<void()> CreatePromptCallback( + UiUnsupportedMode mode, + ExitVrPromptChoice choice, + Model* model, + UiBrowserInterface* browser) { + return base::BindRepeating( + [](UiUnsupportedMode mode, ExitVrPromptChoice choice, Model* m, + UiBrowserInterface* b) { + b->OnExitVrPromptResult(choice, mode); + m->active_modal_prompt_type = kModalPromptTypeNone; + m->pop_mode(kModeModalPrompt); + }, + mode, choice, base::Unretained(model), base::Unretained(browser)); } std::unique_ptr<UiElement> CreateControllerLabel(UiElementName name, @@ -442,7 +515,7 @@ label->SetText(text); label->SetColor(model->color_scheme().controller_label_callout); label->SetVisible(true); - label->SetAlignment(UiTexture::kTextAlignmentRight); + label->SetAlignment(kTextAlignmentRight); label->SetLayoutMode(kSingleLine); label->SetRotate(1, 0, 0, -base::kPiFloat / 2); label->SetShadowsEnabled(true); @@ -609,7 +682,7 @@ auto text_element = Create<Text>(kNone, kPhaseOverlayForeground, kWebVrPermissionFontHeight); text_element->SetLayoutMode(kMultiLineFixedWidth); - text_element->SetAlignment(UiTexture::kTextAlignmentLeft); + text_element->SetAlignment(kTextAlignmentLeft); text_element->SetColor(SK_ColorWHITE); text_element->SetFieldWidth(kWebVrPermissionTextWidth); if (spec.signal) @@ -807,6 +880,8 @@ std::unique_ptr<UiElement> CreateTabsView(Model* model, UiScene* scene, + AudioDelegate* audio_delegate, + UiBrowserInterface* browser, bool incognito) { auto tabs_scroll_view = Create<PagedScrollView>( kNone, kPhaseNone, @@ -829,7 +904,8 @@ TabSetBinding::ModelAddedCallback added_callback = base::BindRepeating( &OnTabModelAdded, base::Unretained(scene), base::Unretained(model), - incognito, base::Unretained(tabs_layout.get())); + incognito, base::Unretained(tabs_layout.get()), + base::Unretained(audio_delegate), base::Unretained(browser)); TabSetBinding::ModelRemovedCallback removed_callback = base::BindRepeating(&OnTabModelRemoved, base::Unretained(scene)); tabs_layout->AddBinding(std::make_unique<TabSetBinding>( @@ -1425,7 +1501,7 @@ l10n_util::GetStringUTF16(IDS_VR_WEB_VR_TIMEOUT_MESSAGE)); timeout_text->SetColor( model_->color_scheme().web_vr_timeout_message_foreground); - timeout_text->SetAlignment(UiTexture::kTextAlignmentLeft); + timeout_text->SetAlignment(kTextAlignmentLeft); timeout_text->SetFieldWidth(kTimeoutMessageTextWidthDMM); timeout_text->set_hit_testable(true); @@ -1617,7 +1693,7 @@ speech_result->SetDrawPhase(kPhaseForeground); speech_result->SetTranslate(0.f, kSpeechRecognitionResultTextYOffset, 0.f); speech_result->SetFieldWidth(kVoiceSearchRecognitionResultTextWidth); - speech_result->SetAlignment(UiTexture::kTextAlignmentCenter); + speech_result->SetAlignment(kTextAlignmentCenter); VR_BIND_COLOR(model_, speech_result.get(), &ColorScheme::prompt_foreground, &Text::SetColor); speech_result->AddBinding(VR_BIND_FUNC(base::string16, Model, model_, @@ -2076,7 +2152,7 @@ hint_text->SetFieldWidth(kUrlBarOriginRegionWidthDMM - kUrlBarOriginContentOffsetDMM); hint_text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth); - hint_text->SetAlignment(UiTexture::kTextAlignmentLeft); + hint_text->SetAlignment(kTextAlignmentLeft); hint_text->SetText(l10n_util::GetStringUTF16(IDS_SEARCH_OR_TYPE_WEB_ADDRESS)); VR_BIND_COLOR(model_, hint_text.get(), &ColorScheme::url_bar_hint_text, &Text::SetColor); @@ -2268,7 +2344,7 @@ text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth); text->SetFieldWidth(kOverflowMenuMinimumWidth - 2 * kOverflowMenuItemXPadding); - text->SetAlignment(UiTexture::kTextAlignmentLeft); + text->SetAlignment(kTextAlignmentLeft); text->AddBinding(VR_BIND_FUNC( SkColor, Model, model_, model->color_scheme().url_bar_button.foreground, Text, text.get(), SetColor)); @@ -2722,102 +2798,103 @@ } void UiSceneCreator::CreatePrompts() { - auto prompt_callback = base::BindRepeating( - [](Model* model, UiBrowserInterface* browser, Prompt::Button button, - UiUnsupportedMode mode) { - ExitVrPromptChoice choice = CHOICE_NONE; - switch (button) { - case Prompt::NONE: - choice = CHOICE_NONE; - break; - case Prompt::PRIMARY: - choice = CHOICE_EXIT; - break; - case Prompt::SECONDARY: - choice = CHOICE_STAY; - break; - } - browser->OnExitVrPromptResult(choice, mode); - model->active_modal_prompt_type = kModalPromptTypeNone; - model->pop_mode(kModeModalPrompt); - }, - base::Unretained(model_), base::Unretained(browser_)); - // Create audio permission prompt. - auto prompt = CreatePrompt( - kAudioPermissionPrompt, kAudioPermissionPromptBackplane, model_, - IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_DESCRIPTION, vector_icons::kMicIcon, - IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_CONTINUE_BUTTON, - IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_ABORT_BUTTON, prompt_callback); - prompt.second->set_reason( - UiUnsupportedMode::kVoiceSearchNeedsRecordAudioOsPermission); - VR_BIND_VISIBILITY( - prompt.first, - model->active_modal_prompt_type == - kModalPromptTypeExitVRForVoiceSearchRecordAudioOsPermission); - scene_->AddUiElement(k2dBrowsingRepositioner, std::move(prompt.first)); - - // Create keyboard update prompt. Note that we re-use the same button texts as - // the audio permission prompt. - prompt = CreatePrompt( - kUpdateKeyboardPrompt, kNone, model_, IDS_VR_UPDATE_KEYBOARD_PROMPT, - vector_icons::kInfoOutlineIcon, - IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_CONTINUE_BUTTON, - IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_ABORT_BUTTON, prompt_callback); - prompt.second->set_reason(UiUnsupportedMode::kNeedsKeyboardUpdate); - VR_BIND_VISIBILITY(prompt.first, model->active_modal_prompt_type == - kModalPromptTypeUpdateKeyboard); - scene_->AddUiElement(k2dBrowsingRepositioner, std::move(prompt.first)); - - // Create generic unsupported UI exit prompt. - prompt_callback = base::BindRepeating( - [](Model* model, UiBrowserInterface* browser, Prompt::Button button, - UiUnsupportedMode mode) { - ExitVrPromptChoice choice = CHOICE_NONE; - switch (button) { - case Prompt::NONE: - choice = CHOICE_NONE; - break; - case Prompt::PRIMARY: - choice = CHOICE_STAY; - break; - case Prompt::SECONDARY: - choice = CHOICE_EXIT; - break; - } - browser->OnExitVrPromptResult(choice, mode); - model->active_modal_prompt_type = kModalPromptTypeNone; - model->pop_mode(kModeModalPrompt); - }, - base::Unretained(model_), base::Unretained(browser_)); - prompt = CreatePrompt( - kExitPrompt, kNone, model_, IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION, - vector_icons::kInfoOutlineIcon, IDS_OK, - IDS_VR_SHELL_EXIT_PROMPT_EXIT_VR_BUTTON, prompt_callback); - VR_BIND_VISIBILITY( - prompt.first, - model->active_modal_prompt_type != kModalPromptTypeNone && - model->active_modal_prompt_type != - kModalPromptTypeExitVRForVoiceSearchRecordAudioOsPermission && - model->active_modal_prompt_type != kModalPromptTypeUpdateKeyboard); - prompt.second->AddBinding(std::make_unique<Binding<ModalPromptType>>( + auto prompt = CreatePrompt(model_); + prompt->SetName(kExitPrompt); + VR_BIND_VISIBILITY(prompt, + model->active_modal_prompt_type != kModalPromptTypeNone); + prompt->AddBinding(std::make_unique<Binding<ModalPromptType>>( VR_BIND_LAMBDA([](Model* m) { return m->active_modal_prompt_type; }, base::Unretained(model_)), VR_BIND_LAMBDA( - [](Prompt* e, const ModalPromptType& p) { - e->set_reason(GetReasonForPrompt(p)); - switch (p) { - case kModalPromptTypeExitVRForSiteInfo: - e->SetContentMessageId( - IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION_SITE_INFO); + [](UiElement* e, Model* model, UiBrowserInterface* browser, + const ModalPromptType& type) { + if (type == kModalPromptTypeNone) + return; + + int message_id = 0; + const gfx::VectorIcon* icon = nullptr; + int primary_button_text_id = 0; + int secondary_button_text_id = 0; + ExitVrPromptChoice primary_choice = CHOICE_NONE; + ExitVrPromptChoice secondary_choice = CHOICE_NONE; + UiUnsupportedMode reason = GetReasonForPrompt(type); + + switch (type) { + case kModalPromptTypeExitVRForVoiceSearchRecordAudioOsPermission: + message_id = IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_DESCRIPTION; + icon = &vector_icons::kMicIcon; + primary_button_text_id = + IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_CONTINUE_BUTTON; + secondary_button_text_id = + IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_ABORT_BUTTON; + primary_choice = CHOICE_EXIT; + secondary_choice = CHOICE_STAY; break; - case kModalPromptTypeGenericUnsupportedFeature: // Fall through. - default: - e->SetContentMessageId(IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION); + case kModalPromptTypeUpdateKeyboard: + message_id = IDS_VR_UPDATE_KEYBOARD_PROMPT; + icon = &vector_icons::kInfoOutlineIcon; + primary_button_text_id = + IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_CONTINUE_BUTTON; + secondary_button_text_id = + IDS_VR_SHELL_AUDIO_PERMISSION_PROMPT_ABORT_BUTTON; + primary_choice = CHOICE_EXIT; + secondary_choice = CHOICE_STAY; + break; + case kModalPromptTypeExitVRForSiteInfo: + message_id = IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION_SITE_INFO; + icon = &vector_icons::kInfoOutlineIcon; + primary_button_text_id = IDS_OK; + secondary_button_text_id = + IDS_VR_SHELL_EXIT_PROMPT_EXIT_VR_BUTTON; + primary_choice = CHOICE_STAY; + secondary_choice = CHOICE_EXIT; + break; + case kModalPromptTypeExitVRForConnectionInfo: + case kModalPromptTypeGenericUnsupportedFeature: + message_id = IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION; + icon = &vector_icons::kInfoOutlineIcon; + primary_button_text_id = IDS_OK; + secondary_button_text_id = + IDS_VR_SHELL_EXIT_PROMPT_EXIT_VR_BUTTON; + primary_choice = CHOICE_STAY; + secondary_choice = CHOICE_EXIT; + break; + case kNumModalPromptTypes: + case kModalPromptTypeNone: + NOTREACHED(); break; } + Text* text_element = + static_cast<Text*>(e->GetDescendantByType(kTypePromptText)); + text_element->SetText(l10n_util::GetStringUTF16(message_id)); + VectorIcon* icon_element = static_cast<VectorIcon*>( + e->GetDescendantByType(kTypePromptIcon)); + icon_element->SetIcon(icon); + TextButton* primary_button = static_cast<TextButton*>( + e->GetDescendantByType(kTypePromptPrimaryButton)); + // TODO(crbug.com/787654): Uppercasing should be conditional. + primary_button->SetText(base::i18n::ToUpper( + l10n_util::GetStringUTF16(primary_button_text_id))); + primary_button->set_click_handler( + CreatePromptCallback(reason, primary_choice, model, browser)); + TextButton* secondary_button = static_cast<TextButton*>( + e->GetDescendantByType(kTypePromptSecondaryButton)); + // TODO(crbug.com/787654): Uppercasing should be conditional. + secondary_button->SetText(base::i18n::ToUpper( + l10n_util::GetStringUTF16(secondary_button_text_id))); + secondary_button->set_click_handler( + CreatePromptCallback(reason, secondary_choice, model, browser)); + InvisibleHitTarget* backplane = static_cast<InvisibleHitTarget*>( + e->GetDescendantByType(kTypePromptBackplane)); + EventHandlers event_handlers; + event_handlers.button_up = + CreatePromptCallback(reason, CHOICE_NONE, model, browser); + backplane->set_event_handlers(event_handlers); + }, - base::Unretained(prompt.second)))); - scene_->AddUiElement(k2dBrowsingRepositioner, std::move(prompt.first)); + base::Unretained(prompt.get()), base::Unretained(model_), + base::Unretained(browser_)))); + scene_->AddUiElement(k2dBrowsingRepositioner, std::move(prompt)); } void UiSceneCreator::CreateWebVrOverlayElements() { @@ -3045,11 +3122,13 @@ VR_BIND_VISIBILITY(tabs_view_root, model->get_last_opaque_mode() == kModeTabsView); - auto regular_tabs_view = CreateTabsView(model_, scene_, false); + auto regular_tabs_view = + CreateTabsView(model_, scene_, audio_delegate_, browser_, false); VR_BIND_VISIBILITY(regular_tabs_view, !model->incognito); tabs_view_root->AddChild(std::move(regular_tabs_view)); - auto incognito_tabs_view = CreateTabsView(model_, scene_, true); + auto incognito_tabs_view = + CreateTabsView(model_, scene_, audio_delegate_, browser_, true); VR_BIND_VISIBILITY(incognito_tabs_view, model->incognito); tabs_view_root->AddChild(std::move(incognito_tabs_view));
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc index 72ee306..a22e6940 100644 --- a/chrome/browser/vr/ui_unittest.cc +++ b/chrome/browser/vr/ui_unittest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/vr/elements/content_element.h" #include "chrome/browser/vr/elements/disc_button.h" #include "chrome/browser/vr/elements/indicator_spec.h" -#include "chrome/browser/vr/elements/prompt.h" #include "chrome/browser/vr/elements/rect.h" #include "chrome/browser/vr/elements/repositioner.h" #include "chrome/browser/vr/elements/ui_element.h" @@ -545,13 +544,12 @@ auto* omnibox = scene_->GetUiElementByName(kUrlBarOriginRegion); EXPECT_CALL(*browser_, OnUnsupportedMode(UiUnsupportedMode::kNeedsKeyboardUpdate)); - omnibox->OnHoverEnter({0.5, 0.5}); - omnibox->OnButtonUp({0.5, 0.5}); + ClickElement(omnibox); ui_->ShowExitVrPrompt(UiUnsupportedMode::kNeedsKeyboardUpdate); OnBeginFrame(); EXPECT_EQ(model_->active_modal_prompt_type, ModalPromptType::kModalPromptTypeUpdateKeyboard); - EXPECT_TRUE(scene_->GetUiElementByName(kUpdateKeyboardPrompt)->IsVisible()); + EXPECT_TRUE(scene_->GetUiElementByName(kExitPrompt)->IsVisible()); } TEST_F(UiTest, WebInputEditingTriggersUnsupportedMode) { @@ -568,7 +566,7 @@ OnBeginFrame(); EXPECT_EQ(model_->active_modal_prompt_type, ModalPromptType::kModalPromptTypeUpdateKeyboard); - EXPECT_TRUE(scene_->GetUiElementByName(kUpdateKeyboardPrompt)->IsVisible()); + EXPECT_TRUE(scene_->GetUiElementByName(kExitPrompt)->IsVisible()); } TEST_F(UiTest, ExitWebInputEditingOnAppButtonClick) { @@ -602,18 +600,37 @@ // Initial state. VerifyOnlyElementsVisible("Initial", kElementsVisibleInBrowsing); - model_->active_modal_prompt_type = kModalPromptTypeExitVRForSiteInfo; + ui_->ShowExitVrPrompt(UiUnsupportedMode::kUnhandledPageInfo); OnBeginFrame(); // Click on 'OK' should trigger UI browser interface and close prompt. EXPECT_CALL(*browser_, OnExitVrPromptResult(ExitVrPromptChoice::CHOICE_STAY, UiUnsupportedMode::kUnhandledPageInfo)); - static_cast<Prompt*>(scene_->GetUiElementByName(kExitPrompt)) - ->ClickPrimaryButtonForTesting(); + auto* prompt = scene_->GetUiElementByName(kExitPrompt); + auto* button = prompt->GetDescendantByType(kTypePromptPrimaryButton); + ClickElement(button); VerifyOnlyElementsVisible("Prompt cleared", kElementsVisibleInBrowsing); } +TEST_F(UiTest, ClickOnPromptBackgroundDoesNothing) { + CreateScene(kNotInCct, kNotInWebVr); + + ui_->ShowExitVrPrompt(UiUnsupportedMode::kUnhandledPageInfo); + OnBeginFrame(); + + EXPECT_CALL(*browser_, OnExitVrPromptResult(testing::_, testing::_)).Times(0); + auto* prompt = scene_->GetUiElementByName(kExitPrompt); + UiElement* target; + // Target the inert icon and text to reliably miss the buttons. + target = prompt->GetDescendantByType(kTypePromptIcon); + ClickElement(target); + target = prompt->GetDescendantByType(kTypePromptText); + ClickElement(target); + + EXPECT_EQ(model_->get_mode(), kModeModalPrompt); +} + TEST_F(UiTest, SecondaryButtonClickTriggersOnExitPrompt) { CreateScene(kNotInCct, kNotInWebVr); @@ -627,8 +644,9 @@ OnExitVrPromptResult(ExitVrPromptChoice::CHOICE_EXIT, UiUnsupportedMode::kUnhandledPageInfo)); - static_cast<Prompt*>(scene_->GetUiElementByName(kExitPrompt)) - ->ClickSecondaryButtonForTesting(); + auto* prompt = scene_->GetUiElementByName(kExitPrompt); + auto* button = prompt->GetDescendantByType(kTypePromptSecondaryButton); + ClickElement(button); VerifyOnlyElementsVisible("Prompt cleared", kElementsVisibleInBrowsing); } @@ -962,7 +980,9 @@ base::string16(), base::string16(), ACMatchClassifications(), ACMatchClassifications(), AutocompleteMatch::Type::VOICE_SUGGEST, gurl, base::string16(), base::string16())); - OnBeginFrame(); + + // Let the omnibox fade in. + RunForMs(100); UiElement* suggestions = scene_->GetUiElementByName(kOmniboxSuggestions); ASSERT_NE(suggestions, nullptr); @@ -971,9 +991,7 @@ EXPECT_CALL(*browser_, Navigate(gurl, NavigationMethod::kOmniboxSuggestionSelected)) .Times(1); - suggestion->OnHoverEnter({0, 0}); - suggestion->OnButtonDown({0, 0}); - suggestion->OnButtonUp({0, 0}); + ClickElement(suggestion); } TEST_F(UiTest, ControllerQuiescence) {
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 713a57ad..34bb65c 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -243,9 +243,6 @@ // disable that check. This switch is used during automated testing. const char kDisablePromptOnRepost[] = "disable-prompt-on-repost"; -// Enable background mode for the Push API. -const char kDisablePushApiBackgroundMode[] = "disable-push-api-background-mode"; - // Disables showing the search geolocation disclosure UI. Used for perf testing. const char kDisableSearchGeolocationDisclosure[] = "disable-search-geolocation-disclosure"; @@ -338,9 +335,6 @@ const char kEnablePrintPreviewRegisterPromos[] = "enable-print-preview-register-promos"; -// Enable background mode for the Push API. -const char kEnablePushApiBackgroundMode[] = "enable-push-api-background-mode"; - // Enables user control over muting tab audio from the tab strip. const char kEnableTabAudioMuting[] = "enable-tab-audio-muting"; @@ -651,10 +645,6 @@ // Used for testing. const char kSupervisedUserId[] = "managed-user-id"; -// Used to authenticate requests to the Sync service for supervised users. -// Setting this switch also causes Sync to be set up for a supervised user. -const char kSupervisedUserSyncToken[] = "managed-user-sync-token"; - // Frequency in Milliseconds for system log uploads. Should only be used for // testing purposes. const char kSystemLogUploadFrequency[] = "system-log-upload-frequency";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index d822440..6aae74d2 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -83,7 +83,6 @@ extern const char kDisablePopupBlocking[]; extern const char kDisablePrintPreview[]; extern const char kDisablePromptOnRepost[]; -extern const char kDisablePushApiBackgroundMode[]; extern const char kDisableSearchGeolocationDisclosure[]; extern const char kDisableZeroBrowsersOpenForTests[]; extern const char kDiskCacheDir[]; @@ -108,7 +107,6 @@ extern const char kEnablePotentiallyAnnoyingSecurityFeatures[]; extern const char kEnablePowerOverlay[]; extern const char kEnablePrintPreviewRegisterPromos[]; -extern const char kEnablePushApiBackgroundMode[]; extern const char kEnableTabAudioMuting[]; extern const char kEnableUiDevTools[]; extern const char kExtensionContentVerification[]; @@ -188,7 +186,6 @@ extern const char kStartMaximized[]; extern const char kStartStackProfiler[]; extern const char kSupervisedUserId[]; -extern const char kSupervisedUserSyncToken[]; extern const char kSystemLogUploadFrequency[]; extern const char kTaskManagerShowExtraRenderers[]; extern const char kTestName[];
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index 90ba05d4..cec0caa8 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -35,7 +35,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // http://crbug.com/717501 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // http://crbug.com/717501 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // http://crbug.com/717501 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // http://crbug.com/717501 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // http://crbug.com/717501 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "accessibilityPrivate.onTwoFingerTouchStop": { @@ -52,7 +53,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // http://crbug.com/717501 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // http://crbug.com/717501 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // http://crbug.com/717501 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // http://crbug.com/717501 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // http://crbug.com/717501 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "action": {
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index 88afe22..1c97ddd 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -148,7 +148,8 @@ "96FF2FFA5C9173C76D47184B3E86D267B37781DE", // http://crbug.com/642141 "0136FCB13DB29FD5CD442F56E59E53B61F1DF96F", // http://crbug.com/642141 "9834387FDA1F66A1B5CA06CB442137B556F12F2A", // http://crbug.com/772346 - "930F7D9989A5FBCDCCD7D85BB5C3B7006C24D91D" // http://crbug.com/782139 + "930F7D9989A5FBCDCCD7D85BB5C3B7006C24D91D", // http://crbug.com/782139 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "clipboardRead": { @@ -730,7 +731,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // https://crbug.com/803362 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // https://crbug.com/803362 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // https://crbug.com/803362 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // https://crbug.com/803362 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // https://crbug.com/803362 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // https://crbug.com/839189 ] }], "signedInDevices": {
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl index d7b7507..a827b7c 100644 --- a/chrome/common/extensions/api/file_manager_private.idl +++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -1072,6 +1072,13 @@ [nocompile] static void getRecentFiles(SourceRestriction restriction, GetRecentFilesCallback callback); + + // Returns true if crostini is enabled. + // |callback| + static void isCrostiniEnabled(BooleanCallback callback); + + // Starts and mounts crostini container. + static void mountCrostiniContainer(); }; interface Events {
diff --git a/chrome/common/trace_event_args_whitelist.cc b/chrome/common/trace_event_args_whitelist.cc index d7eb322..d0744bf 100644 --- a/chrome/common/trace_event_args_whitelist.cc +++ b/chrome/common/trace_event_args_whitelist.cc
@@ -36,6 +36,7 @@ {nullptr, nullptr, nullptr}}; const char* kMetadataWhitelist[] = { + "chrome-library-name", "clock-domain", "config", "cpu-*",
diff --git a/chrome/notification_helper/notification_activator.cc b/chrome/notification_helper/notification_activator.cc index 19d6f1c..746681b 100644 --- a/chrome/notification_helper/notification_activator.cc +++ b/chrome/notification_helper/notification_activator.cc
@@ -77,7 +77,8 @@ SHELLEXECUTEINFO info; memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); - info.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_LOG_USAGE; + info.fMask = + SEE_MASK_NOASYNC | SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_NOCLOSEPROCESS; info.lpFile = chrome_exe_path.value().c_str(); info.lpParameters = params.c_str(); info.nShow = SW_SHOWNORMAL; @@ -88,6 +89,18 @@ return HRESULT_FROM_WIN32(error_code); } + if (info.hProcess != NULL) { + DWORD pid = ::GetProcessId(info.hProcess); + if (!::AllowSetForegroundWindow(pid)) { + DWORD error_code = ::GetLastError(); + Trace(L"Unable to forward activation privilege; error: 0x%08X\n", + error_code); + return HRESULT_FROM_WIN32(error_code); + } + + CloseHandle(info.hProcess); + } + return S_OK; }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index cb14bd7..5bea1ed 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -728,7 +728,6 @@ "../browser/spellchecker/spellcheck_service_browsertest.cc", "../browser/ssl/certificate_reporting_test_utils.cc", "../browser/ssl/certificate_reporting_test_utils.h", - "../browser/ssl/certificate_transparency_browsertest.cc", "../browser/ssl/chrome_expect_ct_reporter_browsertest.cc", "../browser/ssl/chrome_ssl_host_state_delegate_test.cc", "../browser/ssl/connection_help_tab_helper_browsertest.cc", @@ -2996,7 +2995,6 @@ "../browser/ui/global_error/global_error_service_unittest.cc", "../browser/ui/omnibox/chrome_omnibox_navigation_observer_unittest.cc", "../browser/ui/omnibox/clipboard_utils_unittest.cc", - "../browser/ui/omnibox/favicon_cache_unittest.cc", "../browser/ui/page_info/permission_menu_model_unittest.cc", "../browser/ui/passwords/manage_passwords_bubble_model_unittest.cc", "../browser/ui/passwords/password_dialog_controller_impl_unittest.cc", @@ -3078,7 +3076,6 @@ deps += [ "//chrome/browser/resource_coordinator:tab_metrics_event_proto", - "//components/favicon/core/test:test_support", "//components/signin/core/browser:signin_buildflags", "//services/metrics/public/cpp:ukm_builders", "//third_party/libaddressinput",
diff --git a/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js index af310b63..b3c0877 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js +++ b/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
@@ -547,7 +547,7 @@ newwindow.contentWindow.onload = function(evt) { var newwebview = newwindow.contentWindow.document.querySelector('webview'); - newwebview.request.onBeforeRequest.addListener(function(e) { + newwebview.request.onCompleted.addListener(function(e) { if (!calledWebRequestEvent) { calledWebRequestEvent = true; newwebview.parentElement.removeChild(newwebview);
diff --git a/chrome/test/data/webui/cr_elements/cr_lazy_render_tests.js b/chrome/test/data/webui/cr_elements/cr_lazy_render_tests.js index 4d0a69d..d8f4cf70 100644 --- a/chrome/test/data/webui/cr_elements/cr_lazy_render_tests.js +++ b/chrome/test/data/webui/cr_elements/cr_lazy_render_tests.js
@@ -8,7 +8,7 @@ suiteSetup(function() { return PolymerTest.importHtml( - 'chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html'); + 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html'); }); setup(function() { @@ -18,7 +18,7 @@ <cr-lazy-render id="lazy"> <template> <h1> - <paper-checkbox checked="{{checked}}"></paper-checkbox> + <cr-checkbox checked="{{checked}}"></cr-checkbox> {{name}} </h1> </template> @@ -51,7 +51,7 @@ bind.checked = true; const inner = lazy.get(); - const checkbox = document.querySelector('paper-checkbox'); + const checkbox = document.querySelector('cr-checkbox'); assertTrue(checkbox.checked); MockInteractions.tap(checkbox); assertFalse(checkbox.checked);
diff --git a/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js b/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js index 18a9de6..24cefac 100644 --- a/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js +++ b/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js
@@ -104,7 +104,7 @@ expectTrue(items[1].querySelector('paper-button').hidden); // Bailout checkbox should be hidden when auto-launch editing // disabled. - expectTrue(dialog.$$('paper-checkbox').hidden); + expectTrue(dialog.$$('cr-checkbox').hidden); MockInteractions.tap( items[0].querySelector('.icon-delete-gray button')); @@ -156,14 +156,14 @@ let bailoutCheckbox; return initPage() .then(() => { - bailoutCheckbox = dialog.$$('paper-checkbox'); + bailoutCheckbox = dialog.$$('cr-checkbox'); // Bailout checkbox should be usable when auto-launching. expectFalse(bailoutCheckbox.hidden); expectFalse(bailoutCheckbox.disabled); expectFalse(bailoutCheckbox.checked); // Making sure canceling doesn't change anything. - bailoutCheckbox.dispatchEvent(new PointerEvent('pointerdown')); + bailoutCheckbox.click(); Polymer.dom.flush(); expectTrue(dialog.$['confirm-dialog'].open); @@ -175,7 +175,7 @@ expectTrue(dialog.$.dialog.open); // Accepting confirmation dialog should trigger browserProxy call. - bailoutCheckbox.dispatchEvent(new PointerEvent('pointerdown')); + bailoutCheckbox.click(); Polymer.dom.flush(); expectTrue(dialog.$['confirm-dialog'].open); @@ -192,7 +192,7 @@ // Test clicking on checkbox again should simply re-enable bailout. browserProxy.reset(); - bailoutCheckbox.dispatchEvent(new PointerEvent('pointerdown')); + bailoutCheckbox.click(); expectFalse(bailoutCheckbox.checked); expectFalse(dialog.$['confirm-dialog'].open); return browserProxy.whenCalled('setDisableBailoutShortcut');
diff --git a/chrome/test/data/webui/extensions/extension_pack_dialog_test.js b/chrome/test/data/webui/extensions/extension_pack_dialog_test.js index b5cf222..6f737d3 100644 --- a/chrome/test/data/webui/extensions/extension_pack_dialog_test.js +++ b/chrome/test/data/webui/extensions/extension_pack_dialog_test.js
@@ -82,6 +82,7 @@ expectEquals(kRootPath, packDialog.packDirectory_); })); + Polymer.dom.flush(); expectEquals('', packDialog.$$('#key-file').value); MockInteractions.tap(packDialog.$$('#key-file-browse')); expectTrue(!!mockDelegate.keyPromise);
diff --git a/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js b/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js index 12955bd..74520c6 100644 --- a/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js +++ b/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js
@@ -71,6 +71,7 @@ dialog.titleValue_ = 'Permission Site'; dialog.urlValue_ = 'permission.site'; + Polymer.dom.flush(); MockInteractions.tap(dialog.$.saveButton); @@ -87,7 +88,9 @@ assertTrue(dialog.validateUrl_()); dialog.urlValue_ = 'example.com'; + Polymer.dom.flush(); assertTrue(dialog.validateUrl_()); + Polymer.dom.flush(); assertEquals('http://example.com', dialog.urlValue_); dialog.urlValue_ = ''; @@ -103,7 +106,9 @@ dialog.urlValue_ = ''; + Polymer.dom.flush(); MockInteractions.tap(dialog.$.saveButton); + Polymer.dom.flush(); assertTrue(dialog.$.url.invalid); assertTrue(dialog.$.dialog.open);
diff --git a/chrome/test/data/webui/print_preview/destination_search_test.js b/chrome/test/data/webui/print_preview/destination_search_test.js new file mode 100644 index 0000000..16404ea --- /dev/null +++ b/chrome/test/data/webui/print_preview/destination_search_test.js
@@ -0,0 +1,216 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('destination_search_test', function() { + /** @enum {string} */ + const TestNames = { + ReceiveSuccessfulSetup: 'receive successful setup', + ResolutionFails: 'resolution fails', + ReceiveFailedSetup: 'receive failed setup', + GetCapabilitiesFails: 'get capabilities fails', + CloudKioskPrinter: 'cloud kiosk printer', + }; + + const suiteName = 'NewDestinationSearchTest'; + suite(suiteName, function() { + /** @type {?PrintPreviewDestinationDialogElement} */ + let dialog = null; + + /** @type {?print_preview.DestinationStore} */ + let destinationStore = null; + + /** @type {?print_preview.UserInfo} */ + let userInfo = null; + + /** @type {?print_preview.NativeLayer} */ + let nativeLayer = null; + + /** @override */ + setup(function() { + // Create data classes + nativeLayer = new print_preview.NativeLayerStub(); + print_preview.NativeLayer.setInstance(nativeLayer); + userInfo = new print_preview.UserInfo(); + destinationStore = new print_preview.DestinationStore( + userInfo, new WebUIListenerTracker()); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('FooDevice', 'FooName')); + destinationStore.init( + false /* isInAppKioskMode */, + 'FooDevice' /* printerName */, + '' /* serializedDefaultDestinationSelectionRulesStr */, + [] /* recentDestinations */); + + // Set up dialog + dialog = document.createElement('print-preview-destination-dialog'); + dialog.userInfo = userInfo; + dialog.destinationStore = destinationStore; + dialog.invitationStore = new print_preview.InvitationStore(userInfo); + dialog.recentDestinations = []; + PolymerTest.clearBody(); + document.body.appendChild(dialog); + return nativeLayer.whenCalled('getPrinterCapabilities').then(function() { + dialog.show(); + Polymer.dom.flush(); + nativeLayer.reset(); + }); + }); + + /** + * @param {!print_preview.Destination} destination The destination to + * simulate selection of. + */ + function simulateDestinationSelect(destination) { + // Fake destinationListItem. + const item = + document.createElement('print-preview-destination-list-item'); + item.destination = destination; + + // Get print list and fire event. + const list = dialog.shadowRoot.querySelectorAll( + 'print-preview-destination-list')[1]; + list.fire('destination-selected', item); + } + + /** + * Adds a destination to the dialog and simulates selection of the + * destination. + * @param {string} destId The ID for the destination. + */ + function requestSetup(destId) { + const origin = cr.isChromeOS ? print_preview.DestinationOrigin.CROS : + print_preview.DestinationOrigin.LOCAL; + + const dest = new print_preview.Destination(destId, + print_preview.DestinationType.LOCAL, + origin, + 'displayName', + print_preview.DestinationConnectionStatus.ONLINE); + + // Add the destination to the list. + dialog.updateDestinations_([dest]); + simulateDestinationSelect(dest); + } + + // Tests that a destination is selected if the user clicks on it and setup + // (for CrOS) or capabilities fetch (for non-Cros) succeeds. + test(assert(TestNames.ReceiveSuccessfulSetup), function() { + const destId = '00112233DEADBEEF'; + const response = { + printerId: destId, + capabilities: + print_preview_test_utils.getCddTemplate(destId).capabilities, + success: true, + }; + if (cr.isChromeOS) { + nativeLayer.setSetupPrinterResponse(false, response); + } else { + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate(destId)); + } + + const waiter = test_util.eventToPromise( + print_preview.DestinationStore.EventType.DESTINATION_SELECT, + destinationStore); + requestSetup(destId); + const callback = + cr.isChromeOS ? 'setupPrinter' : 'getPrinterCapabilities'; + return Promise.all([nativeLayer.whenCalled(callback), waiter]).then( + function(results) { + const actualId = + cr.isChromeOS ? results[0] : results[0].destinationId; + assertEquals(destId, actualId); + // After setup or capabilities fetch succeeds, the destination + // should be selected. + assertNotEquals(null, destinationStore.selectedDestination); + assertEquals(destId, destinationStore.selectedDestination.id); + }); + }); + + // Test what happens when the setupPrinter request is rejected. ChromeOS + // only. + test(assert(TestNames.ResolutionFails), function() { + const destId = '001122DEADBEEF'; + const originalDestination = destinationStore.selectedDestination; + nativeLayer.setSetupPrinterResponse(true, {printerId: destId, + success: false}); + requestSetup(destId); + return nativeLayer.whenCalled('setupPrinter').then( + function(actualId) { + assertEquals(destId, actualId); + // The selected printer should not have changed, since a printer + // cannot be selected until setup succeeds. + assertEquals(originalDestination, + destinationStore.selectedDestination); + }); + }); + + // Test what happens when the setupPrinter request is resolved with a + // failed status. Chrome OS only. + test(assert(TestNames.ReceiveFailedSetup), function() { + const originalDestination = destinationStore.selectedDestination; + const destId = '00112233DEADBEEF'; + const response = { + printerId: destId, + capabilities: + print_preview_test_utils.getCddTemplate(destId).capabilities, + success: false, + }; + nativeLayer.setSetupPrinterResponse(false, response); + requestSetup(destId); + return nativeLayer.whenCalled('setupPrinter').then( + function (actualDestId) { + assertEquals(destId, actualDestId); + // The selected printer should not have changed, since a printer + // cannot be selected until setup succeeds. + assertEquals(originalDestination, + destinationStore.selectedDestination); + }); + }); + + // Tests what happens when capabilities cannot be retrieved for the chosen + // destination. The destination will still be selected in this case. + // non-Chrome OS only. + test(assert(TestNames.GetCapabilitiesFails), function() { + const destId = '001122DEADBEEF'; + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate(destId), true); + requestSetup(destId); + return nativeLayer.whenCalled('getPrinterCapabilities').then( + function(args) { + assertEquals(destId, args.destinationId); + // The destination is selected even though capabilities cannot be + // retrieved. + assertEquals(destId, destinationStore.selectedDestination.id); + }); + }); + + // Test what happens when a simulated cloud kiosk printer is selected. + test(assert(TestNames.CloudKioskPrinter), function() { + const printerId = 'cloud-printer-id'; + + // Create cloud destination. + const cloudDest = new print_preview.Destination(printerId, + print_preview.DestinationType.GOOGLE, + print_preview.DestinationOrigin.DEVICE, + 'displayName', + print_preview.DestinationConnectionStatus.ONLINE); + cloudDest.capabilities = + print_preview_test_utils.getCddTemplate(printerId, 'displayName') + .capabilities; + + // Place destination in the local list as happens for Kiosk printers. + dialog.updateDestinations_([cloudDest]); + simulateDestinationSelect(cloudDest); + + // Verify that the destination has been selected. + assertEquals(printerId, destinationStore.selectedDestination.id); + }); + }); + + return { + suiteName: suiteName, + TestNames: TestNames, + }; +});
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js index 7c6d3bd..8ad4b12f 100644 --- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -174,6 +174,37 @@ this.runMochaTest(settings_select_test.TestNames.CustomMediaNames); }); +PrintPreviewPagesSettingsTest = class extends NewPrintPreviewTest { + /** @override */ + get browsePreload() { + return 'chrome://print/new/pages_settings.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + ROOT_PATH + 'chrome/test/data/webui/settings/test_util.js', + 'print_preview_test_utils.js', + 'pages_settings_test.js', + ]); + } + + /** @override */ + get suiteName() { + return pages_settings_test.suiteName; + } +}; + +TEST_F('PrintPreviewPagesSettingsTest', 'ValidPageRanges', + function() { + this.runMochaTest(pages_settings_test.TestNames.ValidPageRanges); +}); + +TEST_F('PrintPreviewPagesSettingsTest', 'InvalidPageRanges', + function() { + this.runMochaTest(pages_settings_test.TestNames.InvalidPageRanges); +}); + PrintPreviewRestoreStateTest = class extends NewPrintPreviewTest { /** @override */ get browsePreload() { @@ -575,3 +606,55 @@ function() { this.runMochaTest(custom_margins_test.TestNames.ControlsCheck); }); + +PrintPreviewNewDestinationSearchTest = class extends NewPrintPreviewTest { + /** @override */ + get browsePreload() { + return 'chrome://print/new/destination_dialog.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + ROOT_PATH + 'chrome/test/data/webui/settings/test_util.js', + ROOT_PATH + 'ui/webui/resources/js/webui_listener_tracker.js', + '../test_browser_proxy.js', + 'native_layer_stub.js', + 'print_preview_test_utils.js', + 'destination_search_test.js', + ]); + } + + /** @override */ + get suiteName() { + return destination_search_test.suiteName; + } +}; + +TEST_F('PrintPreviewNewDestinationSearchTest', 'ReceiveSuccessfulSetup', + function() { + this.runMochaTest(destination_search_test.TestNames.ReceiveSuccessfulSetup); +}); + +GEN('#if defined(OS_CHROMEOS)'); +TEST_F('PrintPreviewNewDestinationSearchTest', 'ResolutionFails', + function() { + this.runMochaTest(destination_search_test.TestNames.ResolutionFails); +}); + +TEST_F('PrintPreviewNewDestinationSearchTest', 'ReceiveFailedSetup', + function() { + this.runMochaTest(destination_search_test.TestNames.ReceiveFailedSetup); +}); + +GEN('#else'); // !defined(OS_CHROMEOS) +TEST_F('PrintPreviewNewDestinationSearchTest', 'GetCapabilitiesFails', + function() { + this.runMochaTest(destination_search_test.TestNames.GetCapabilitiesFails); +}); +GEN('#endif'); // defined(OS_CHROMEOS) + +TEST_F('PrintPreviewNewDestinationSearchTest', 'CloudKioskPrinter', + function() { + this.runMochaTest(destination_search_test.TestNames.CloudKioskPrinter); +});
diff --git a/chrome/test/data/webui/print_preview/pages_settings_test.js b/chrome/test/data/webui/print_preview/pages_settings_test.js new file mode 100644 index 0000000..7bfefd0 --- /dev/null +++ b/chrome/test/data/webui/print_preview/pages_settings_test.js
@@ -0,0 +1,159 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('pages_settings_test', function() { + /** @enum {string} */ + const TestNames = { + ValidPageRanges: 'valid page ranges', + InvalidPageRanges: 'invalid page ranges', + }; + + const suiteName = 'PagesSettingsTest'; + suite(suiteName, function() { + /** @type {?PrintPreviewPagesSettingsElement} */ + let pagesSection = null; + + /** @type {?print_preview.DocumentInfo} */ + let documentInfo = null; + + /** @override */ + setup(function() { + documentInfo = new print_preview.DocumentInfo(); + documentInfo.init(true, 'title', false); + + PolymerTest.clearBody(); + pagesSection = document.createElement('print-preview-pages-settings'); + pagesSection.settings = { + pages: { + value: [1], + unavailableValue: [], + valid: true, + available: true, + key: '', + }, + ranges: { + value: [], + unavailableValue: [], + valid: true, + available: true, + key: '', + }, + }; + pagesSection.documentInfo = documentInfo; + pagesSection.disabled = false; + document.body.appendChild(pagesSection); + }); + + /** + * Sets up the pages section to use the custom input with the input string + * given by |inputString|, with the document page count set to |pageCount| + * @param {string} inputString + * @param {number} pageCount + * @return {!Promise} Promise that resolves when the input-change event + * has fired. + */ + function setupInput(inputString, pageCount) { + // Set page count. + documentInfo.updatePageCount(pageCount); + pagesSection.notifyPath('documentInfo.pageCount'); + Polymer.dom.flush(); + + // Select custom + pagesSection.$$('#custom-radio-button').checked = true; + pagesSection.$$('#all-radio-button').dispatchEvent( + new CustomEvent('change')); + + // Set input string + const input = pagesSection.$.pageSettingsCustomInput; + input.value = inputString; + input.dispatchEvent(new CustomEvent('input')); + + // Validate results + return test_util.eventToPromise('input-change', pagesSection); + } + + // Tests that the page ranges set are valid for different user inputs. + test(assert(TestNames.ValidPageRanges), function() { + /** @param {!Array<number>} expectedPages The expected pages value. */ + const validateState = function(expectedPages) { + const pagesValue = pagesSection.getSettingValue('pages'); + assertEquals(expectedPages.length, pagesValue.length); + expectedPages.forEach((page, index) => { + assertEquals(page, pagesValue[index]); + }); + assertTrue(pagesSection.$$('.hint').hidden); + }; + + const oneToHundred = Array.from({length: 100}, (x, i) => i + 1); + const tenToHundred = Array.from({length: 91}, (x, i) => i + 10); + + return setupInput('1, 2, 3, 1, 56', 100).then(function() { + validateState([1, 2, 3, 56]); + return setupInput('1-3, 6-9, 6-10', 100); + }).then(function() { + validateState([1, 2, 3, 6, 7, 8, 9, 10]); + return setupInput('10-', 100); + }).then(function() { + validateState(tenToHundred); + return setupInput('10-100', 100); + }).then(function() { + validateState(tenToHundred); + return setupInput('-', 100); + }).then(function() { + validateState(oneToHundred); + // https://crbug.com/806165 + return setupInput('1\u30012\u30013\u30011\u300156', 100); + }).then(function() { + validateState([1, 2, 3, 56]); + return setupInput('1,2,3\u30011\u300156', 100); + }).then(function() { + validateState([1, 2, 3, 56]); + }); + }); + + // Tests that the correct error messages are shown for different user + // inputs. + test(assert(TestNames.InvalidPageRanges), function() { + const limitError = 'Out of bounds page reference, limit is '; + const syntaxError = 'Invalid page range, use e.g. 1-5, 8, 11-13'; + + /** @param {string} expectedMessage The expected error message. */ + const validateState = function(expectedMessage) { + assertFalse(pagesSection.$$('.hint').hidden); + assertEquals(expectedMessage, + pagesSection.$$('.hint').textContent.trim()); + }; + + return setupInput('10-100000', 100).then(function() { + validateState(limitError + '100'); + return setupInput('1, 100000', 100); + }).then(function() { + validateState(limitError + '100'); + return setupInput('1, 2, 0, 56', 100); + }).then(function() { + validateState(syntaxError); + return setupInput('-1, 1, 2,, 56', 100); + }).then(function() { + validateState(syntaxError); + return setupInput('1,2,56-40', 100); + }).then(function() { + validateState(syntaxError); + return setupInput('101-110', 100); + }).then(function() { + validateState(limitError + '100'); + return setupInput('1\u30012\u30010\u300156', 100); + }).then(function() { + validateState(syntaxError); + return setupInput('-1,1,2\u3001\u300156', 100); + }).then(function() { + validateState(syntaxError); + }); + }); + }); + + return { + suiteName: suiteName, + TestNames: TestNames, + }; +});
diff --git a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js index eecd1e5c..cf3d23b 100644 --- a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
@@ -73,6 +73,7 @@ testElement = document.createElement('settings-password-prompt-dialog'); testElement.quickUnlockPrivate_ = quickUnlockPrivateApi; testElement.writeUma_ = fakeUma.recordProgress.bind(fakeUma); + Polymer.dom.flush(); document.body.appendChild(testElement); passwordElement = getFromElement('#passwordInput'); @@ -99,13 +100,16 @@ const confirmButton = getFromElement('#passwordInput'); quickUnlockPrivateApi.accountPassword = 'bar'; passwordElement.value = 'foo'; + Polymer.dom.flush(); + MockInteractions.tap( getFromElement('paper-button[class="action-button"]')); - assertEquals(0, passwordElement.inputElement.selectionStart); + assertEquals( + 0, passwordElement.inputElement.inputElement.selectionStart); assertEquals( passwordElement.value.length, - passwordElement.inputElement.selectionEnd); + passwordElement.inputElement.inputElement.selectionEnd); }); test('TapConfirmButtonWithWrongPasswordRestoresFocus', function() {
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.js b/chrome/test/data/webui/settings/search_engines_page_test.js index c2a75dd..f1254b0c 100644 --- a/chrome/test/data/webui/settings/search_engines_page_test.js +++ b/chrome/test/data/webui/settings/search_engines_page_test.js
@@ -112,13 +112,16 @@ Promise.resolve(); }; - assertEquals('', dialog.$.searchEngine.value); - assertEquals('', dialog.$.keyword.value); - assertEquals('', dialog.$.queryUrl.value); const actionButton = dialog.$.actionButton; - assertTrue(actionButton.disabled); - return inputAndValidate('searchEngine') + return browserProxy.whenCalled('searchEngineEditStarted') + .then(() => { + assertEquals('', dialog.$.searchEngine.value); + assertEquals('', dialog.$.keyword.value); + assertEquals('', dialog.$.queryUrl.value); + assertTrue(actionButton.disabled); + }) + .then(() => inputAndValidate('searchEngine')) .then(() => inputAndValidate('keyword')) .then(() => inputAndValidate('queryUrl')) .then(() => {
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js index 37986260..3f22e158 100644 --- a/chrome/test/data/webui/settings/site_list_tests.js +++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -291,7 +291,7 @@ function openActionMenu(index) { const item = testElement.$.listContainer.children[index]; const dots = item.querySelector('#actionMenuButton'); - MockInteractions.tap(dots); + dots.click(); Polymer.dom.flush(); } @@ -569,7 +569,7 @@ // Select 'Remove' from menu. const remove = testElement.$.reset; assertTrue(!!remove); - MockInteractions.tap(remove); + remove.click(); return browserProxy.whenCalled('resetCategoryPermissionForPattern'); }) .then(function(args) { @@ -607,7 +607,7 @@ openActionMenu(1); const remove = testElement.$.reset; assertTrue(!!remove); - MockInteractions.tap(remove); + remove.click(); return browserProxy.whenCalled('resetCategoryPermissionForPattern'); }) .then(function(args) { @@ -649,7 +649,7 @@ assertTrue(!!resetButton); assertFalse(resetButton.hidden); - MockInteractions.tap(resetButton.querySelector('button')); + resetButton.querySelector('button').click(); return browserProxy.whenCalled('resetCategoryPermissionForPattern'); }) .then(function(args) { @@ -673,7 +673,7 @@ assertTrue(menu.open); const edit = testElement.$.edit; assertTrue(!!edit); - MockInteractions.tap(edit); + edit.click(); Polymer.dom.flush(); assertFalse(menu.open); @@ -681,6 +681,30 @@ }); }); + test('edit dialog closes when incognito status changes', function() { + setUpCategory( + settings.ContentSettingsTypes.COOKIES, settings.ContentSetting.BLOCK, + prefsSessionOnly); + + return browserProxy.whenCalled('getExceptionList') + .then(function() { + Polymer.dom.flush(); // Populates action menu. + + openActionMenu(0); + testElement.$.edit.click(); + Polymer.dom.flush(); + + const dialog = testElement.$$('settings-edit-exception-dialog'); + assertTrue(!!dialog); + const closeEventPromise = test_util.eventToPromise('close', dialog); + browserProxy.setIncognito(true); + return closeEventPromise; + }) + .then(() => { + assertFalse(!!testElement.$$('settings-edit-exception-dialog')); + }); + }); + test('list items shown and clickable when data is present', function() { const contentType = settings.ContentSettingsTypes.GEOLOCATION; setUpCategory(contentType, settings.ContentSetting.ALLOW, prefsGeolocation); @@ -705,7 +729,7 @@ const firstItem = testElement.$.listContainer.children[0]; const clickable = firstItem.querySelector('.middle'); assertTrue(!!clickable); - MockInteractions.tap(clickable); + clickable.click(); assertEquals( prefsGeolocation.exceptions[contentType][0].origin, settings.getQueryParameters().get('site')); @@ -831,7 +855,7 @@ openActionMenu(0); const allow = testElement.$.allow; assertTrue(!!allow); - MockInteractions.tap(allow); + allow.click(); return browserProxy.whenCalled('setCategoryPermissionForPattern'); }); }); @@ -848,7 +872,7 @@ const allow = testElement.$.allow; assertTrue(!!allow); - MockInteractions.tap(allow); + allow.click(); return browserProxy.whenCalled('setCategoryPermissionForPattern'); }) .then(function(args) { @@ -933,7 +957,7 @@ assertTrue(!!actionButton); assertFalse(actionButton.disabled); - MockInteractions.tap(actionButton); + actionButton.click(); return browserProxy.whenCalled('resetCategoryPermissionForPattern') .then(function(args) { assertEquals(cookieException.origin, args[0]);
diff --git a/chrome/test/data/webui/settings/startup_urls_page_test.js b/chrome/test/data/webui/settings/startup_urls_page_test.js index 73b6765..30245bd8 100644 --- a/chrome/test/data/webui/settings/startup_urls_page_test.js +++ b/chrome/test/data/webui/settings/startup_urls_page_test.js
@@ -85,6 +85,7 @@ test('Initialization_Add', function() { document.body.appendChild(dialog); + Polymer.dom.flush(); assertTrue(dialog.$.dialog.open); // Assert that the "Add" button is disabled.
diff --git a/chrome/test/media_router/media_router_base_browsertest.h b/chrome/test/media_router/media_router_base_browsertest.h index ab63b78..3ac0db9c 100644 --- a/chrome/test/media_router/media_router_base_browsertest.h +++ b/chrome/test/media_router/media_router_base_browsertest.h
@@ -28,7 +28,7 @@ * 2. "--extension-unpacked" flag to specify the unpacked extension location * Only one of them should be passed when run browser tests. */ -class MediaRouterBaseBrowserTest : public ExtensionBrowserTest, +class MediaRouterBaseBrowserTest : public extensions::ExtensionBrowserTest, public extensions::ProcessManagerObserver { public: MediaRouterBaseBrowserTest();
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index dc9f124f9..96eb7eb 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1250,7 +1250,7 @@ } #if BUILDFLAG(ENABLE_NACL) -class PackagedAppTest : public ExtensionBrowserTest { +class PackagedAppTest : public extensions::ExtensionBrowserTest { public: explicit PackagedAppTest(const std::string& toolchain) : toolchain_(toolchain) { }
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 64434aa..8c9091df 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -506,11 +506,13 @@ if (enable_chromecast_extensions) { sources += [ + "$root_gen_dir/chromecast/renderer/extensions_renderer_resources.pak", "$root_gen_dir/extensions/extensions_renderer_resources.pak", "$root_gen_dir/extensions/extensions_resources.pak", "$root_gen_dir/extensions/shell/app_shell_resources.pak", ] deps += [ + "//chromecast/renderer:extensions_resources", "//extensions:extensions_resources", "//extensions/shell:resources", ]
diff --git a/chromecast/android/AndroidManifest.xml b/chromecast/android/AndroidManifest.xml deleted file mode 100644 index bd606188..0000000 --- a/chromecast/android/AndroidManifest.xml +++ /dev/null
@@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright 2015 The Chromium Authors. All rights reserved. Use of this - source code is governed by a BSD-style license that can be found in the - LICENSE file. ---> - -<!-- - This is a dummy manifest which is required by lint for determining min/target - SDK version. ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="dummy.package"> - - <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="22" /> - -</manifest>
diff --git a/chromecast/android/src/dummy b/chromecast/android/src/dummy deleted file mode 100644 index c1069e01..0000000 --- a/chromecast/android/src/dummy +++ /dev/null
@@ -1,2 +0,0 @@ -Note(gunsch): This file is for the cast_shell_apk target in chromecast.gyp. -See the notes above that target's 'java_in_dir' variable in chromecast.gyp.
diff --git a/chromecast/base/chromecast_switches.cc b/chromecast/base/chromecast_switches.cc index b53a3f1..8bb660308 100644 --- a/chromecast/base/chromecast_switches.cc +++ b/chromecast/base/chromecast_switches.cc
@@ -149,6 +149,11 @@ // a valid origin for the top or bottom swipe gesture. const char kSystemGestureStartHeight[] = "system-gesture-start-height"; +// The number of pixels from the start of a left swipe gesture to consider as a +// 'back' gesture. +const char kBackGestureHorizontalThreshold[] = + "back-gesture-horizontal-threshold"; + } // namespace switches namespace chromecast {
diff --git a/chromecast/base/chromecast_switches.h b/chromecast/base/chromecast_switches.h index e511f0e..740bbb8a 100644 --- a/chromecast/base/chromecast_switches.h +++ b/chromecast/base/chromecast_switches.h
@@ -77,6 +77,7 @@ extern const char kEnableInput[]; extern const char kSystemGestureStartWidth[]; extern const char kSystemGestureStartHeight[]; +extern const char kBackGestureHorizontalThreshold[]; // Background color used when Chromium hasn't rendered anything yet. extern const char kCastAppBackgroundColor[];
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index f223f240..753238e 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -19,6 +19,8 @@ "application_media_capabilities.h", "bluetooth/cast_bluetooth_chooser.cc", "bluetooth/cast_bluetooth_chooser.h", + "cast_back_gesture_dispatcher.cc", + "cast_back_gesture_dispatcher.h", "cast_browser_context.cc", "cast_browser_context.h", "cast_browser_main_parts.cc", @@ -377,6 +379,7 @@ cast_source_set("browsertests") { testonly = true sources = [ + "cast_back_gesture_dispatcher_test.cc", "cast_media_blocker_browsertest.cc", "renderer_prelauncher_test.cc", "test/cast_features_browsertest.cc",
diff --git a/chromecast/browser/cast_back_gesture_dispatcher.cc b/chromecast/browser/cast_back_gesture_dispatcher.cc new file mode 100644 index 0000000..fbb74aba --- /dev/null +++ b/chromecast/browser/cast_back_gesture_dispatcher.cc
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/browser/cast_back_gesture_dispatcher.h" + +#include "chromecast/base/chromecast_switches.h" + +namespace chromecast { +namespace shell { + +namespace { +constexpr int kDefaultBackGestureHorizontalThreshold = 80; +} // namespace + +CastBackGestureDispatcher::CastBackGestureDispatcher( + CastContentWindow::Delegate* delegate) + : horizontal_threshold_( + GetSwitchValueInt(switches::kBackGestureHorizontalThreshold, + kDefaultBackGestureHorizontalThreshold)), + delegate_(delegate), + dispatched_back_(false) { + DCHECK(delegate_); +} +bool CastBackGestureDispatcher::CanHandleSwipe( + CastSideSwipeOrigin swipe_origin) { + return swipe_origin == CastSideSwipeOrigin::LEFT && + delegate_->CanHandleGesture(GestureType::GO_BACK); +} + +void CastBackGestureDispatcher::HandleSideSwipeBegin( + CastSideSwipeOrigin swipe_origin, + const gfx::Point& touch_location) { + if (swipe_origin == CastSideSwipeOrigin::LEFT) { + dispatched_back_ = false; + } +} + +void CastBackGestureDispatcher::HandleSideSwipeContinue( + CastSideSwipeOrigin swipe_origin, + const gfx::Point& touch_location) { + if (!dispatched_back_ && swipe_origin == CastSideSwipeOrigin::LEFT && + touch_location.x() >= horizontal_threshold_) { + dispatched_back_ = true; + delegate_->ConsumeGesture(GestureType::GO_BACK); + } +} + +} // namespace shell +} // namespace chromecast
diff --git a/chromecast/browser/cast_back_gesture_dispatcher.h b/chromecast/browser/cast_back_gesture_dispatcher.h new file mode 100644 index 0000000..6a651f9b --- /dev/null +++ b/chromecast/browser/cast_back_gesture_dispatcher.h
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_BROWSER_CAST_BACK_GESTURE_DISPATCHER_H_ +#define CHROMECAST_BROWSER_CAST_BACK_GESTURE_DISPATCHER_H_ + +#include "base/macros.h" +#include "chromecast/browser/cast_content_window.h" +#include "chromecast/graphics/cast_side_swipe_gesture_handler.h" + +namespace chromecast { +namespace shell { + +// Takes side swipe gestures destined for implementations of +// CastContentWindow and dispatches them to a CastContentWindow::Delegate if the +// side swipe is a back gesture. +class CastBackGestureDispatcher : public CastSideSwipeGestureHandlerInterface { + public: + explicit CastBackGestureDispatcher(CastContentWindow::Delegate* delegate); + + // CastSideSwipeGestureHandlerInterface implementation: + bool CanHandleSwipe(CastSideSwipeOrigin swipe_origin) override; + void HandleSideSwipeBegin(CastSideSwipeOrigin swipe_origin, + const gfx::Point& touch_location) override; + void HandleSideSwipeContinue(CastSideSwipeOrigin swipe_origin, + const gfx::Point& touch_location) override; + + private: + // Number of pixels past swipe origin to consider as a back gesture. + const int horizontal_threshold_; + CastContentWindow::Delegate* const delegate_; + bool dispatched_back_; +}; + +} // namespace shell +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_CAST_BACK_GESTURE_DISPATCHER_H_
diff --git a/chromecast/browser/cast_back_gesture_dispatcher_test.cc b/chromecast/browser/cast_back_gesture_dispatcher_test.cc new file mode 100644 index 0000000..726f34d --- /dev/null +++ b/chromecast/browser/cast_back_gesture_dispatcher_test.cc
@@ -0,0 +1,116 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/browser/cast_back_gesture_dispatcher.h" + +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_base.h" +#include "testing/gmock/include/gmock/gmock.h" + +// Gmock matchers and actions that we use below. +using testing::AnyOf; +using testing::Eq; +using testing::Return; +using testing::SetArgPointee; +using testing::WithArg; +using testing::_; + +namespace chromecast { +namespace shell { + +class MockCastContentWindowDelegate : public CastContentWindow::Delegate { + public: + ~MockCastContentWindowDelegate() override = default; + + MOCK_METHOD1(CanHandleGesture, bool(GestureType gesture_type)); + MOCK_METHOD1(ConsumeGesture, bool(GestureType gesture_type)); + std::string GetId() override { return "mockContentWindowDelegate"; } +}; + +// Verify the simple case of a left swipe with the right horizontal leads to +// back. +TEST(CastBackGestureDispatcherTest, VerifySimpleDispatchSuccess) { + MockCastContentWindowDelegate delegate; + CastBackGestureDispatcher dispatcher(&delegate); + EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(true)); + EXPECT_CALL(delegate, ConsumeGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(true)); + dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT); + dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, gfx::Point(5, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(90, 50)); +} + +// Verify that multiple 'continue' events still only lead to one back +// invocation. +TEST(CastBackGestureDispatcherTest, VerifyOnlySingleDispatch) { + MockCastContentWindowDelegate delegate; + CastBackGestureDispatcher dispatcher(&delegate); + EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(true)); + EXPECT_CALL(delegate, ConsumeGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(true)); + dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT); + dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, gfx::Point(5, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(90, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(105, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(200, 50)); +} + +// Verify that if the delegate says it doesn't handle back that we won't try to +// ask them to consume it. +TEST(CastBackGestureDispatcherTest, VerifyDelegateDoesNotConsumeUnwanted) { + MockCastContentWindowDelegate delegate; + CastBackGestureDispatcher dispatcher(&delegate); + EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(false)); + dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT); + dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, gfx::Point(5, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(90, 50)); +} + +// Verify that a not-left gesture doesn't lead to a swipe. +TEST(CastBackGestureDispatcherTest, VerifyNotLeftSwipeIsNotBack) { + MockCastContentWindowDelegate delegate; + CastBackGestureDispatcher dispatcher(&delegate); + dispatcher.CanHandleSwipe(CastSideSwipeOrigin::TOP); + dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::TOP, gfx::Point(0, 5)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::TOP, + gfx::Point(0, 90)); +} + +// Verify that if the gesture doesn't go far enough horizontally that we will +// not consider it a swipe. +TEST(CastBackGestureDispatcherTest, VerifyNotFarEnoughRightIsNotBack) { + MockCastContentWindowDelegate delegate; + CastBackGestureDispatcher dispatcher(&delegate); + EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(true)); + dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT); + dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, gfx::Point(5, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(70, 50)); +} + +// Verify that if the gesture ends before going far enough, that's also not a +// swipe. +TEST(CastBackGestureDispatcherTest, VerifyNotFarEnoughRightAndEndIsNotBack) { + MockCastContentWindowDelegate delegate; + CastBackGestureDispatcher dispatcher(&delegate); + EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK))) + .WillOnce(Return(true)); + dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT); + dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, gfx::Point(5, 50)); + dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT, + gfx::Point(70, 50)); + dispatcher.HandleSideSwipeEnd(CastSideSwipeOrigin::LEFT, gfx::Point(75, 50)); +} + +} // namespace shell +} // namespace chromecast
diff --git a/chromecast/browser/cast_content_window_aura.cc b/chromecast/browser/cast_content_window_aura.cc index 4a762b8..859cc6ff 100644 --- a/chromecast/browser/cast_content_window_aura.cc +++ b/chromecast/browser/cast_content_window_aura.cc
@@ -77,9 +77,9 @@ CastContentWindowAura::CastContentWindowAura( CastContentWindow::Delegate* delegate, bool is_touch_enabled) - : delegate_(delegate), is_touch_enabled_(is_touch_enabled) { - DCHECK(delegate_); -} + : back_gesture_dispatcher_( + std::make_unique<CastBackGestureDispatcher>(delegate)), + is_touch_enabled_(is_touch_enabled) {} CastContentWindowAura::~CastContentWindowAura() { if (window_manager_) @@ -121,16 +121,20 @@ void CastContentWindowAura::RequestMoveOut(){}; bool CastContentWindowAura::CanHandleSwipe(CastSideSwipeOrigin swipe_origin) { - return swipe_origin == CastSideSwipeOrigin::LEFT && - delegate_->CanHandleGesture(GestureType::GO_BACK); + return back_gesture_dispatcher_->CanHandleSwipe(swipe_origin); } void CastContentWindowAura::HandleSideSwipeBegin( CastSideSwipeOrigin swipe_origin, const gfx::Point& touch_location) { - if (swipe_origin == CastSideSwipeOrigin::LEFT) { - delegate_->ConsumeGesture(GestureType::GO_BACK); - } + back_gesture_dispatcher_->HandleSideSwipeBegin(swipe_origin, touch_location); +} + +void CastContentWindowAura::HandleSideSwipeContinue( + CastSideSwipeOrigin swipe_origin, + const gfx::Point& touch_location) { + back_gesture_dispatcher_->HandleSideSwipeContinue(swipe_origin, + touch_location); } } // namespace shell
diff --git a/chromecast/browser/cast_content_window_aura.h b/chromecast/browser/cast_content_window_aura.h index 555aba1..cd376d57 100644 --- a/chromecast/browser/cast_content_window_aura.h +++ b/chromecast/browser/cast_content_window_aura.h
@@ -6,6 +6,7 @@ #define CHROMECAST_BROWSER_CAST_CONTENT_WINDOW_AURA_H_ #include "base/macros.h" +#include "chromecast/browser/cast_back_gesture_dispatcher.h" #include "chromecast/browser/cast_content_window.h" #include "chromecast/graphics/cast_side_swipe_gesture_handler.h" @@ -38,6 +39,8 @@ bool CanHandleSwipe(CastSideSwipeOrigin swipe_origin) override; void HandleSideSwipeBegin(CastSideSwipeOrigin swipe_origin, const gfx::Point& touch_location) override; + void HandleSideSwipeContinue(CastSideSwipeOrigin swipe_origin, + const gfx::Point& touch_location) override; private: friend class CastContentWindow; @@ -45,7 +48,9 @@ // This class should only be instantiated by CastContentWindow::Create. CastContentWindowAura(Delegate* delegate, bool is_touch_enabled); - Delegate* const delegate_; + // Utility class for detecting and dispatching back gestures to delegates. + std::unique_ptr<CastBackGestureDispatcher> back_gesture_dispatcher_; + const bool is_touch_enabled_; std::unique_ptr<TouchBlocker> touch_blocker_;
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc index 8a8822a..b893bc0 100644 --- a/chromecast/browser/url_request_context_factory.cc +++ b/chromecast/browser/url_request_context_factory.cc
@@ -61,20 +61,6 @@ const char kCookieStoreFile[] = "Cookies"; -// A CTPolicyEnforcer that accepts all certificates. -class IgnoresCTPolicyEnforcer : public net::CTPolicyEnforcer { - public: - IgnoresCTPolicyEnforcer() = default; - ~IgnoresCTPolicyEnforcer() override = default; - - net::ct::CTPolicyCompliance CheckCompliance( - net::X509Certificate* cert, - const net::SCTList& verified_scts, - const net::NetLogWithSource& net_log) override { - return net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } -}; - bool IgnoreCertificateErrors() { base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); return cmd_line->HasSwitch(switches::kIgnoreCertificateErrors); @@ -247,7 +233,7 @@ transport_security_state_.reset(new net::TransportSecurityState()); // Certificate transparency is current disabled for Chromecast. cert_transparency_verifier_.reset(new net::DoNothingCTVerifier()); - ct_policy_enforcer_.reset(new IgnoresCTPolicyEnforcer()); + ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer()); http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(host_resolver_.get());
diff --git a/chromecast/public/avsettings.h b/chromecast/public/avsettings.h index deac339..0a8f013 100644 --- a/chromecast/public/avsettings.h +++ b/chromecast/public/avsettings.h
@@ -136,6 +136,9 @@ // This event should be fired when an HDMI error occurs. HDMI_ERROR = 102, + + // This event should be fired when the display brightness is changed. + DISPLAY_BRIGHTNESS_CHANGED = 200, }; // Delegate to inform the caller events. As a subclass of TaskRunner,
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn index 4c40c3bb..e7c83e7 100644 --- a/chromecast/renderer/BUILD.gn +++ b/chromecast/renderer/BUILD.gn
@@ -3,6 +3,26 @@ # found in the LICENSE file. import("//chromecast/chromecast.gni") +import("//tools/grit/grit_rule.gni") + +grit("extensions_resources") { + source = "resources/extensions_renderer_resources.grd" + output_dir = "$root_gen_dir/chromecast/renderer" + output_name = "extensions_renderer_resources" + outputs = [ + "grit/extensions_renderer_resources.h", + "extensions_renderer_resources.pak", + ] + grit_flags = [ + "-E", + "mojom_root=" + rebase_path(root_gen_dir, root_build_dir), + ] + deps = [ + "//net/interfaces:interfaces_js", + "//url/mojom:url_mojom_gurl_js", + "//url/mojom:url_mojom_origin_js", + ] +} cast_source_set("renderer") { sources = [
diff --git a/chromecast/renderer/resources/extensions/automation/automation_event.js b/chromecast/renderer/resources/extensions/automation/automation_event.js new file mode 100644 index 0000000..88c94d15 --- /dev/null +++ b/chromecast/renderer/resources/extensions/automation/automation_event.js
@@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var utils = require('utils'); + +function AutomationEventImpl(type, target, eventFrom) { + this.propagationStopped = false; + this.type = type; + this.target = target; + this.eventPhase = Event.NONE; + this.eventFrom = eventFrom; +} + +AutomationEventImpl.prototype = { + __proto__: null, + stopPropagation: function() { + this.propagationStopped = true; + }, +}; + +function AutomationEvent() { + privates(AutomationEvent).constructPrivate(this, arguments); +} +utils.expose(AutomationEvent, AutomationEventImpl, { + functions: [ + 'stopPropagation', + ], + readonly: [ + 'type', + 'target', + 'eventPhase', + 'eventFrom', + ], +}); + +exports.$set('AutomationEvent', AutomationEvent);
diff --git a/chromecast/renderer/resources/extensions/automation/automation_node.js b/chromecast/renderer/resources/extensions/automation/automation_node.js new file mode 100644 index 0000000..06ff7049 --- /dev/null +++ b/chromecast/renderer/resources/extensions/automation/automation_node.js
@@ -0,0 +1,1466 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var AutomationEvent = require('automationEvent').AutomationEvent; +var automationInternal = + getInternalApi ? + getInternalApi('automationInternal') : + require('binding').Binding.create('automationInternal').generate(); +var exceptionHandler = require('uncaught_exception_handler'); + +var natives = requireNative('automationInternal'); + +var IsInteractPermitted = natives.IsInteractPermitted; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?number} The id of the root node. + */ +var GetRootID = natives.GetRootID; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?string} The title of the document. + */ +var GetDocTitle = natives.GetDocTitle; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?string} The url of the document. + */ +var GetDocURL = natives.GetDocURL; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?boolean} True if the document has finished loading. + */ +var GetDocLoaded = natives.GetDocLoaded; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?number} The loading progress, from 0.0 to 1.0 (fully loaded). + */ +var GetDocLoadingProgress = + natives.GetDocLoadingProgress; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?number} The ID of the selection anchor object. + */ +var GetAnchorObjectID = natives.GetAnchorObjectID; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?number} The selection anchor offset. + */ +var GetAnchorOffset = natives.GetAnchorOffset; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?string} The selection anchor affinity. + */ +var GetAnchorAffinity = natives.GetAnchorAffinity; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?number} The ID of the selection focus object. + */ +var GetFocusObjectID = natives.GetFocusObjectID; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?number} The selection focus offset. + */ +var GetFocusOffset = natives.GetFocusOffset; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @return {?string} The selection focus affinity. + */ +var GetFocusAffinity = natives.GetFocusAffinity; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?number} The id of the node's parent, or undefined if it's the + * root of its tree or if the tree or node wasn't found. + */ +var GetParentID = natives.GetParentID; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?number} The number of children of the node, or undefined if + * the tree or node wasn't found. + */ +var GetChildCount = natives.GetChildCount; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {number} childIndex An index of a child of this node. + * @return {?number} The id of the child at the given index, or undefined + * if the tree or node or child at that index wasn't found. + */ +var GetChildIDAtIndex = natives.GetChildIDAtIndex; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?number} The ids of the children of the node, or undefined + * if the tree or node wasn't found. + */ +var GetChildIds = natives.GetChildIDs; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?Object} An object mapping html attributes to values. + */ +var GetHtmlAttributes = natives.GetHtmlAttributes; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?number} The index of this node in its parent, or undefined if + * the tree or node or node parent wasn't found. + */ +var GetIndexInParent = natives.GetIndexInParent; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?Object} An object with a string key for every state flag set, + * or undefined if the tree or node or node parent wasn't found. + */ +var GetState = natives.GetState; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {string} The restriction, one of + * "disabled", "readOnly" or undefined if enabled or other object not disabled + */ +var GetRestriction = natives.GetRestriction; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {string} The checked state, as undefined, "true", "false" or "mixed". + */ +var GetChecked = natives.GetChecked; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {string} The role of the node, or undefined if the tree or + * node wasn't found. + */ +var GetRole = natives.GetRole; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?automation.Rect} The location of the node, or undefined if + * the tree or node wasn't found. + */ +var GetLocation = natives.GetLocation; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {number} startIndex The start index of the range. + * @param {number} endIndex The end index of the range. + * @return {?automation.Rect} The bounding box of the subrange of this node, + * or the location if there are no subranges, or undefined if + * the tree or node wasn't found. + */ +var GetBoundsForRange = natives.GetBoundsForRange; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?automation.Rect} The unclipped location of the node, or + * undefined if the tree or node wasn't found. + */ +var GetUnclippedLocation = natives.GetUnclippedLocation; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {!Array<number>} The text offset where each line starts, or an empty + * array if this node has no text content, or undefined if the tree or node + * was not found. + */ +var GetLineStartOffsets = requireNative( + 'automationInternal').GetLineStartOffsets; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of a string attribute. + * @return {?string} The value of this attribute, or undefined if the tree, + * node, or attribute wasn't found. + */ +var GetStringAttribute = natives.GetStringAttribute; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an attribute. + * @return {?boolean} The value of this attribute, or undefined if the tree, + * node, or attribute wasn't found. + */ +var GetBoolAttribute = natives.GetBoolAttribute; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an attribute. + * @return {?number} The value of this attribute, or undefined if the tree, + * node, or attribute wasn't found. + */ +var GetIntAttribute = natives.GetIntAttribute; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an attribute. + * @return {?Array<number>} The ids of nodes who have a relationship pointing + * to |nodeID| (a reverse relationship). + */ +var GetIntAttributeReverseRelations = + natives.GetIntAttributeReverseRelations; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an attribute. + * @return {?number} The value of this attribute, or undefined if the tree, + * node, or attribute wasn't found. + */ +var GetFloatAttribute = natives.GetFloatAttribute; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an attribute. + * @return {?Array<number>} The value of this attribute, or undefined + * if the tree, node, or attribute wasn't found. + */ +var GetIntListAttribute = + natives.GetIntListAttribute; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an attribute. + * @return {?Array<number>} The ids of nodes who have a relationship pointing + * to |nodeID| (a reverse relationship). + */ +var GetIntListAttributeReverseRelations = + natives.GetIntListAttributeReverseRelations; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @param {string} attr The name of an HTML attribute. + * @return {?string} The value of this attribute, or undefined if the tree, + * node, or attribute wasn't found. + */ +var GetHtmlAttribute = natives.GetHtmlAttribute; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {automation.NameFromType} The source of the node's name. + */ +var GetNameFrom = natives.GetNameFrom; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {boolean} + */ +var GetBold = natives.GetBold; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {boolean} + */ +var GetItalic = natives.GetItalic; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {boolean} + */ +var GetUnderline = natives.GetUnderline; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {boolean} + */ +var GetLineThrough = natives.GetLineThrough; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?Array<automation.CustomAction>} List of custom actions of the + * node. + */ +var GetCustomActions = natives.GetCustomActions; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {?Array<string>} List of standard actions of the node. + */ +var GetStandardActions = natives.GetStandardActions; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. + * @return {automation.NameFromType} The source of the node's name. + */ +var GetDefaultActionVerb = natives.GetDefaultActionVerb; + +var logging = requireNative('logging'); +var utils = require('utils'); + +/** + * A single node in the Automation tree. + * @param {AutomationRootNodeImpl} root The root of the tree. + * @constructor + */ +function AutomationNodeImpl(root) { + this.rootImpl = root; + this.hostNode_ = null; + this.listeners = {__proto__: null}; +} + +AutomationNodeImpl.prototype = { + __proto__: null, + treeID: -1, + id: -1, + isRootNode: false, + + detach: function() { + this.rootImpl = null; + this.hostNode_ = null; + this.listeners = {__proto__: null}; + }, + + get root() { + return this.rootImpl && this.rootImpl.wrapper; + }, + + get parent() { + if (!this.rootImpl) + return undefined; + if (this.hostNode_) + return this.hostNode_; + var parentID = GetParentID(this.treeID, this.id); + return this.rootImpl.get(parentID); + }, + + get htmlAttributes() { + return GetHtmlAttributes(this.treeID, this.id) || {}; + }, + + get state() { + return GetState(this.treeID, this.id) || {}; + }, + + get role() { + return GetRole(this.treeID, this.id); + }, + + get restriction() { + return GetRestriction(this.treeID, this.id); + }, + + get checked() { + return GetChecked(this.treeID, this.id); + }, + + get location() { + return GetLocation(this.treeID, this.id); + }, + + boundsForRange: function(startIndex, endIndex) { + return GetBoundsForRange(this.treeID, this.id, startIndex, endIndex); + }, + + get unclippedLocation() { + var result = GetUnclippedLocation(this.treeID, this.id); + if (result === undefined) + result = GetLocation(this.treeID, this.id); + return result; + }, + + get indexInParent() { + return GetIndexInParent(this.treeID, this.id); + }, + + get lineStartOffsets() { + return GetLineStartOffsets(this.treeID, this.id); + }, + + get childTree() { + var childTreeID = GetIntAttribute(this.treeID, this.id, 'childTreeId'); + if (childTreeID) + return AutomationRootNodeImpl.get(childTreeID); + }, + + get firstChild() { + if (!this.rootImpl) + return undefined; + if (this.childTree) + return this.childTree; + if (!GetChildCount(this.treeID, this.id)) + return undefined; + var firstChildID = GetChildIDAtIndex(this.treeID, this.id, 0); + return this.rootImpl.get(firstChildID); + }, + + get lastChild() { + if (!this.rootImpl) + return undefined; + if (this.childTree) + return this.childTree; + var count = GetChildCount(this.treeID, this.id); + if (!count) + return undefined; + var lastChildID = GetChildIDAtIndex(this.treeID, this.id, count - 1); + return this.rootImpl.get(lastChildID); + }, + + get children() { + if (!this.rootImpl) + return []; + + if (this.childTree) + return [this.childTree]; + + var children = []; + var childIds = GetChildIds(this.treeID, this.id); + for (var i = 0; i < childIds.length; ++i) { + var childID = childIds[i]; + var child = this.rootImpl.get(childID); + $Array.push(children, child); + } + return children; + }, + + get previousSibling() { + var parent = this.parent; + if (!parent) + return undefined; + parent = privates(parent).impl; + var indexInParent = GetIndexInParent(this.treeID, this.id); + return this.rootImpl.get( + GetChildIDAtIndex(parent.treeID, parent.id, indexInParent - 1)); + }, + + get nextSibling() { + var parent = this.parent; + if (!parent) + return undefined; + parent = privates(parent).impl; + var indexInParent = GetIndexInParent(this.treeID, this.id); + return this.rootImpl.get( + GetChildIDAtIndex(parent.treeID, parent.id, indexInParent + 1)); + }, + + get nameFrom() { + return GetNameFrom(this.treeID, this.id); + }, + + get bold() { + return GetBold(this.treeID, this.id); + }, + + get italic() { + return GetItalic(this.treeID, this.id); + }, + + get underline() { + return GetUnderline(this.treeID, this.id); + }, + + get lineThrough() { + return GetLineThrough(this.treeID, this.id); + }, + + get customActions() { + return GetCustomActions(this.treeID, this.id); + }, + + get standardActions() { + return GetStandardActions(this.treeID, this.id); + }, + + get defaultActionVerb() { + return GetDefaultActionVerb(this.treeID, this.id); + }, + + doDefault: function() { + this.performAction_('doDefault'); + }, + + focus: function() { + this.performAction_('focus'); + }, + + getImageData: function(maxWidth, maxHeight) { + this.performAction_('getImageData', + { maxWidth: maxWidth, + maxHeight: maxHeight }); + }, + + hitTest: function(x, y, eventToFire) { + this.hitTestInternal(x, y, eventToFire); + }, + + hitTestWithReply: function(x, y, opt_callback) { + this.hitTestInternal(x, y, 'hitTestResult', opt_callback); + }, + + hitTestInternal: function(x, y, eventToFire, opt_callback) { + // Convert from global to tree-relative coordinates. + var location = GetLocation(this.treeID, GetRootID(this.treeID)); + this.performAction_('hitTest', + { x: Math.floor(x - location.left), + y: Math.floor(y - location.top), + eventToFire: eventToFire }, + opt_callback); + }, + + makeVisible: function() { + this.performAction_('scrollToMakeVisible'); + }, + + performCustomAction: function(customActionId) { + this.performAction_('customAction', { customActionID: customActionId }); + }, + + performStandardAction: function(action) { + var standardActions = GetStandardActions(this.treeID, this.id); + if (!standardActions || + !standardActions.find(item => action == item)) { + throw 'Inapplicable action for node: ' + action; + } + this.performAction_(action); + }, + + replaceSelectedText: function(value) { + if (this.state.editable) { + this.performAction_('replaceSelectedText', { value: value}); + } + }, + + resumeMedia: function() { + this.performAction_('resumeMedia'); + }, + + scrollBackward: function(opt_callback) { + this.performAction_('scrollBackward', {}, opt_callback); + }, + + scrollForward: function(opt_callback) { + this.performAction_('scrollForward', {}, opt_callback); + }, + + scrollUp: function(opt_callback) { + this.performAction_('scrollUp', {}, opt_callback); + }, + + scrollDown: function(opt_callback) { + this.performAction_('scrollDown', {}, opt_callback); + }, + + scrollLeft: function(opt_callback) { + this.performAction_('scrollLeft', {}, opt_callback); + }, + + scrollRight: function(opt_callback) { + this.performAction_('scrollRight', {}, opt_callback); + }, + + setSelection: function(startIndex, endIndex) { + if (this.state.editable) { + this.performAction_('setSelection', + { focusNodeID: this.id, + anchorOffset: startIndex, + focusOffset: endIndex }); + } + }, + + setSequentialFocusNavigationStartingPoint: function() { + this.performAction_('setSequentialFocusNavigationStartingPoint'); + }, + + setValue: function(value) { + if (this.state.editable) { + this.performAction_('setValue', { value: value}); + } + }, + + showContextMenu: function() { + this.performAction_('showContextMenu'); + }, + + startDuckingMedia: function() { + this.performAction_('startDuckingMedia'); + }, + + stopDuckingMedia: function() { + this.performAction_('stopDuckingMedia'); + }, + + suspendMedia: function() { + this.performAction_('suspendMedia'); + }, + + domQuerySelector: function(selector, callback) { + if (!this.rootImpl) + callback(); + automationInternal.querySelector( + { treeID: this.rootImpl.treeID, + automationNodeID: this.id, + selector: selector }, + $Function.bind(this.domQuerySelectorCallback_, this, callback)); + }, + + find: function(params) { + return this.findInternal_(params); + }, + + findAll: function(params) { + return this.findInternal_(params, []); + }, + + matches: function(params) { + return this.matchInternal_(params); + }, + + addEventListener: function(eventType, callback, capture) { + this.removeEventListener(eventType, callback); + if (!this.listeners[eventType]) + this.listeners[eventType] = []; + $Array.push(this.listeners[eventType], { + __proto__: null, + callback: callback, + capture: !!capture, + }); + }, + + // TODO(dtseng/aboxhall): Check this impl against spec. + removeEventListener: function(eventType, callback) { + if (this.listeners[eventType]) { + var listeners = this.listeners[eventType]; + for (var i = 0; i < listeners.length; i++) { + if (callback === listeners[i].callback) + $Array.splice(listeners, i, 1); + } + } + }, + + toJSON: function() { + return { treeID: this.treeID, + id: this.id, + role: this.role, + attributes: this.attributes }; + }, + + dispatchEvent: function(eventType, eventFrom, mouseX, mouseY) { + var path = []; + var parent = this.parent; + while (parent) { + $Array.push(path, parent); + parent = parent.parent; + } + var event = new AutomationEvent(eventType, this.wrapper, eventFrom); + event.mouseX = mouseX; + event.mouseY = mouseY; + + // Dispatch the event through the propagation path in three phases: + // - capturing: starting from the root and going down to the target's parent + // - targeting: dispatching the event on the target itself + // - bubbling: starting from the target's parent, going back up to the root. + // At any stage, a listener may call stopPropagation() on the event, which + // will immediately stop event propagation through this path. + if (this.dispatchEventAtCapturing_(event, path)) { + if (this.dispatchEventAtTargeting_(event, path)) + this.dispatchEventAtBubbling_(event, path); + } + }, + + toString: function() { + var parentID = GetParentID(this.treeID, this.id); + var childTreeID = GetIntAttribute(this.treeID, this.id, 'childTreeId'); + var count = GetChildCount(this.treeID, this.id); + var childIDs = []; + for (var i = 0; i < count; ++i) { + var childID = GetChildIDAtIndex(this.treeID, this.id, i); + $Array.push(childIDs, childID); + } + + var result = 'node id=' + this.id + + ' role=' + this.role + + ' state=' + $JSON.stringify(this.state) + + ' parentID=' + parentID + + ' childIds=' + $JSON.stringify(childIDs); + if (this.hostNode_) { + var hostNodeImpl = privates(this.hostNode_).impl; + result += ' host treeID=' + hostNodeImpl.treeID + + ' host nodeID=' + hostNodeImpl.id; + } + if (childTreeID) + result += ' childTreeID=' + childTreeID; + return result; + }, + + dispatchEventAtCapturing_: function(event, path) { + privates(event).impl.eventPhase = Event.CAPTURING_PHASE; + for (var i = path.length - 1; i >= 0; i--) { + this.fireEventListeners_(path[i], event); + if (privates(event).impl.propagationStopped) + return false; + } + return true; + }, + + dispatchEventAtTargeting_: function(event) { + privates(event).impl.eventPhase = Event.AT_TARGET; + this.fireEventListeners_(this.wrapper, event); + return !privates(event).impl.propagationStopped; + }, + + dispatchEventAtBubbling_: function(event, path) { + privates(event).impl.eventPhase = Event.BUBBLING_PHASE; + for (var i = 0; i < path.length; i++) { + this.fireEventListeners_(path[i], event); + if (privates(event).impl.propagationStopped) + return false; + } + return true; + }, + + fireEventListeners_: function(node, event) { + var nodeImpl = privates(node).impl; + if (!nodeImpl.rootImpl) + return; + + var listeners = nodeImpl.listeners[event.type]; + if (!listeners) + return; + var eventPhase = event.eventPhase; + for (var i = 0; i < listeners.length; i++) { + if (eventPhase == Event.CAPTURING_PHASE && !listeners[i].capture) + continue; + if (eventPhase == Event.BUBBLING_PHASE && listeners[i].capture) + continue; + + try { + listeners[i].callback(event); + } catch (e) { + exceptionHandler.handle('Error in event handler for ' + event.type + + ' during phase ' + eventPhase, e); + } + } + }, + + performAction_: function(actionType, opt_args, opt_callback) { + if (!this.rootImpl) + return; + + // Not yet initialized. + if (this.rootImpl.treeID === undefined || + this.id === undefined) { + return; + } + + // Check permissions. + if (!IsInteractPermitted()) { + throw new Error(actionType + ' requires {"desktop": true} or' + + ' {"interact": true} in the "automation" manifest key.'); + } + var requestID = -1; + if (opt_callback) { + requestID = this.rootImpl.addActionResultCallback(opt_callback); + } + + automationInternal.performAction({ treeID: this.rootImpl.treeID, + automationNodeID: this.id, + actionType: actionType, + requestID: requestID}, + opt_args || {}); + }, + + domQuerySelectorCallback_: function(userCallback, resultAutomationNodeID) { + // resultAutomationNodeID could be zero or undefined or (unlikely) null; + // they all amount to the same thing here, which is that no node was + // returned. + if (!resultAutomationNodeID || !this.rootImpl) { + userCallback(null); + return; + } + var resultNode = this.rootImpl.get(resultAutomationNodeID); + if (!resultNode) { + logging.WARNING('Query selector result not in tree: ' + + resultAutomationNodeID); + userCallback(null); + } + userCallback(resultNode); + }, + + findInternal_: function(params, opt_results) { + var result = null; + this.forAllDescendants_(function(node) { + if (privates(node).impl.matchInternal_(params)) { + if (opt_results) + $Array.push(opt_results, node); + else + result = node; + return !opt_results; + } + }); + if (opt_results) + return opt_results; + return result; + }, + + /** + * Executes a closure for all of this node's descendants, in pre-order. + * Early-outs if the closure returns true. + * @param {Function(AutomationNode):boolean} closure Closure to be executed + * for each node. Return true to early-out the traversal. + */ + forAllDescendants_: function(closure) { + var stack = $Array.reverse(this.wrapper.children); + while (stack.length > 0) { + var node = $Array.pop(stack); + if (closure(node)) + return; + + var children = node.children; + for (var i = children.length - 1; i >= 0; i--) + $Array.push(stack, children[i]); + } + }, + + matchInternal_: function(params) { + if ($Object.keys(params).length === 0) + return false; + + if ('role' in params && this.role != params.role) + return false; + + if ('state' in params) { + for (var state in params.state) { + if (params.state[state] != (state in this.state)) + return false; + } + } + if ('attributes' in params) { + for (var attribute in params.attributes) { + var attrValue = params.attributes[attribute]; + if (typeof attrValue != 'object') { + if (this[attribute] !== attrValue) + return false; + } else if (attrValue instanceof $RegExp.self) { + if (typeof this[attribute] != 'string') + return false; + if (!attrValue.test(this[attribute])) + return false; + } else { + // TODO(aboxhall): handle intlist case. + return false; + } + } + } + return true; + } +}; + +var stringAttributes = [ + 'accessKey', + 'ariaInvalidValue', + 'autoComplete', + 'className', + 'containerLiveRelevant', + 'containerLiveStatus', + 'description', + 'display', + 'htmlTag', + 'imageDataUrl', + 'language', + 'liveRelevant', + 'liveStatus', + 'name', + 'placeholder', + 'roleDescription', + 'textInputType', + 'url', + 'value']; + +var boolAttributes = [ + 'busy', + 'clickable', + 'containerLiveAtomic', + 'containerLiveBusy', + 'liveAtomic', + 'modal', + 'scrollable', + 'selected' +]; + +var intAttributes = [ + 'backgroundColor', + 'color', + 'colorValue', + 'hierarchicalLevel', + 'posInSet', + 'scrollX', + 'scrollXMax', + 'scrollXMin', + 'scrollY', + 'scrollYMax', + 'scrollYMin', + 'setSize', + 'tableCellColumnIndex', + 'ariaCellColumnIndex', + 'tableCellColumnSpan', + 'tableCellRowIndex', + 'ariaCellRowIndex', + 'tableCellRowSpan', + 'tableColumnCount', + 'ariaColumnCount', + 'tableColumnIndex', + 'tableRowCount', + 'ariaRowCount', + 'tableRowIndex', + 'textSelEnd', + 'textSelStart']; + +// Int attribute, relation property to expose, reverse relation to expose. +var nodeRefAttributes = [ + ['activedescendantId', 'activeDescendant', null], + ['detailsId', 'details', 'detailsFor'], + ['errorMessageId', 'errorMessage', 'errorMessageFor'], + ['inPageLinkTargetId', 'inPageLinkTarget', null], + ['nextFocusId', 'nextFocus', null], + ['nextOnLineId', 'nextOnLine', null], + ['previousFocusId', 'previousFocus', null], + ['previousOnLineId', 'previousOnLine', null], + ['tableColumnHeaderId', 'tableColumnHeader', null], + ['tableHeaderId', 'tableHeader', null], + ['tableRowHeaderId', 'tableRowHeader', null]]; + +var intListAttributes = [ + 'lineBreaks', + 'markerEnds', + 'markerStarts', + 'markerTypes', + 'wordEnds', + 'wordStarts']; + +// Intlist attribute, relation property to expose, reverse relation to expose. +var nodeRefListAttributes = [ + ['controlsIds', 'controls', 'controlledBy'], + ['describedbyIds', 'describedBy', 'descriptionFor'], + ['flowtoIds', 'flowTo', 'flowFrom'], + ['labelledbyIds', 'labelledBy', 'labelFor']]; + +var floatAttributes = [ + 'valueForRange', + 'minValueForRange', + 'maxValueForRange']; + +var htmlAttributes = [ + ['type', 'inputType']]; + +var publicAttributes = []; + +$Array.forEach(stringAttributes, function(attributeName) { + $Array.push(publicAttributes, attributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { + __proto__: null, + get: function() { + return GetStringAttribute(this.treeID, this.id, attributeName); + } + }); +}); + +$Array.forEach(boolAttributes, function(attributeName) { + $Array.push(publicAttributes, attributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { + __proto__: null, + get: function() { + return GetBoolAttribute(this.treeID, this.id, attributeName); + } + }); +}); + +$Array.forEach(intAttributes, function(attributeName) { + $Array.push(publicAttributes, attributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { + __proto__: null, + get: function() { + return GetIntAttribute(this.treeID, this.id, attributeName); + } + }); +}); + +$Array.forEach(nodeRefAttributes, function(params) { + var srcAttributeName = params[0]; + var dstAttributeName = params[1]; + var dstReverseAttributeName = params[2]; + $Array.push(publicAttributes, dstAttributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, { + __proto__: null, + get: function() { + var id = GetIntAttribute(this.treeID, this.id, srcAttributeName); + if (id && this.rootImpl) + return this.rootImpl.get(id); + else + return undefined; + } + }); + if (dstReverseAttributeName) { + $Array.push(publicAttributes, dstReverseAttributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, + dstReverseAttributeName, { + __proto__: null, + get: function() { + var ids = GetIntAttributeReverseRelations( + this.treeID, this.id, srcAttributeName); + if (!ids || !this.rootImpl) + return undefined; + var result = []; + for (var i = 0; i < ids.length; ++i) { + var node = this.rootImpl.get(ids[i]); + if (node) + $Array.push(result, node); + } + return result; + } + }); + } +}); + +$Array.forEach(intListAttributes, function(attributeName) { + $Array.push(publicAttributes, attributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { + __proto__: null, + get: function() { + return GetIntListAttribute(this.treeID, this.id, attributeName); + } + }); +}); + +$Array.forEach(nodeRefListAttributes, function(params) { + var srcAttributeName = params[0]; + var dstAttributeName = params[1]; + var dstReverseAttributeName = params[2]; + $Array.push(publicAttributes, dstAttributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, { + __proto__: null, + get: function() { + var ids = GetIntListAttribute(this.treeID, this.id, srcAttributeName); + if (!ids || !this.rootImpl) + return undefined; + var result = []; + for (var i = 0; i < ids.length; ++i) { + var node = this.rootImpl.get(ids[i]); + if (node) + $Array.push(result, node); + } + return result; + } + }); + if (dstReverseAttributeName) { + $Array.push(publicAttributes, dstReverseAttributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, + dstReverseAttributeName, { + __proto__: null, + get: function() { + var ids = GetIntListAttributeReverseRelations( + this.treeID, this.id, srcAttributeName); + if (!ids || !this.rootImpl) + return undefined; + var result = []; + for (var i = 0; i < ids.length; ++i) { + var node = this.rootImpl.get(ids[i]); + if (node) + $Array.push(result, node); + } + return result; + } + }); + } +}); + +$Array.forEach(floatAttributes, function(attributeName) { + $Array.push(publicAttributes, attributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { + __proto__: null, + get: function() { + return GetFloatAttribute(this.treeID, this.id, attributeName); + } + }); +}); + +$Array.forEach(htmlAttributes, function(params) { + var srcAttributeName = params[0]; + var dstAttributeName = params[1]; + $Array.push(publicAttributes, dstAttributeName); + $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, { + __proto__: null, + get: function() { + return GetHtmlAttribute(this.treeID, this.id, srcAttributeName); + } + }); +}); + +/** + * AutomationRootNode. + * + * An AutomationRootNode is the javascript end of an AXTree living in the + * browser. AutomationRootNode handles unserializing incremental updates from + * the source AXTree. Each update contains node data that form a complete tree + * after applying the update. + * + * A brief note about ids used through this class. The source AXTree assigns + * unique ids per node and we use these ids to build a hash to the actual + * AutomationNode object. + * Thus, tree traversals amount to a lookup in our hash. + * + * The tree itself is identified by the accessibility tree id of the + * renderer widget host. + * @constructor + */ +function AutomationRootNodeImpl(treeID) { + $Function.call(AutomationNodeImpl, this, this); + this.treeID = treeID; + this.axNodeDataCache_ = {__proto__: null}; + this.actionRequestIDToCallback_ = {__proto__: null}; +} + +utils.defineProperty(AutomationRootNodeImpl, 'idToAutomationRootNode_', + {__proto__: null}); + +utils.defineProperty(AutomationRootNodeImpl, 'get', function(treeID) { + var result = AutomationRootNodeImpl.idToAutomationRootNode_[treeID]; + return result || undefined; +}); + +utils.defineProperty(AutomationRootNodeImpl, 'getOrCreate', function(treeID) { + if (AutomationRootNodeImpl.idToAutomationRootNode_[treeID]) + return AutomationRootNodeImpl.idToAutomationRootNode_[treeID]; + var result = new AutomationRootNode(treeID); + AutomationRootNodeImpl.idToAutomationRootNode_[treeID] = result; + return result; +}); + +utils.defineProperty(AutomationRootNodeImpl, 'destroy', function(treeID) { + delete AutomationRootNodeImpl.idToAutomationRootNode_[treeID]; +}); + +AutomationRootNodeImpl.prototype = { + __proto__: AutomationNodeImpl.prototype, + + /** + * @type {boolean} + */ + isRootNode: true, + + /** + * @type {number} + */ + treeID: -1, + + /** + * The parent of this node from a different tree. + * @type {?AutomationNode} + * @private + */ + hostNode_: null, + + /** + * A map from id to AutomationNode. + * @type {Object.<number, AutomationNode>} + * @private + */ + axNodeDataCache_: null, + + actionRequestCounter_: 0, + + actionRequestIDToCallback_: null, + + get id() { + var result = GetRootID(this.treeID); + + // Don't return undefined, because the id is often passed directly + // as an argument to a native binding that expects only a valid number. + if (result === undefined) + return -1; + + return result; + }, + + get chromeChannel() { + return GetStringAttribute(this.treeID, this.id, 'chromeChannel'); + }, + + get docUrl() { + return GetDocURL(this.treeID); + }, + + get docTitle() { + return GetDocTitle(this.treeID); + }, + + get docLoaded() { + return GetDocLoaded(this.treeID); + }, + + get docLoadingProgress() { + return GetDocLoadingProgress(this.treeID); + }, + + get anchorObject() { + var id = GetAnchorObjectID(this.treeID); + if (id && id != -1) + return this.get(id); + else + return undefined; + }, + + get anchorOffset() { + var id = GetAnchorObjectID(this.treeID); + if (id && id != -1) + return GetAnchorOffset(this.treeID); + }, + + get anchorAffinity() { + var id = GetAnchorObjectID(this.treeID); + if (id && id != -1) + return GetAnchorAffinity(this.treeID); + }, + + get focusObject() { + var id = GetFocusObjectID(this.treeID); + if (id && id != -1) + return this.get(id); + else + return undefined; + }, + + get focusOffset() { + var id = GetFocusObjectID(this.treeID); + if (id && id != -1) + return GetFocusOffset(this.treeID); + }, + + get focusAffinity() { + var id = GetFocusObjectID(this.treeID); + if (id && id != -1) + return GetFocusAffinity(this.treeID); + }, + + get: function(id) { + if (id == undefined) + return undefined; + + if (id == this.id) + return this.wrapper; + + var obj = this.axNodeDataCache_[id]; + if (obj) + return obj; + + // Validate the backing AXTree has the specified node. + if (!GetRole(this.treeID, id)) + return; + + obj = new AutomationNode(this); + privates(obj).impl.treeID = this.treeID; + privates(obj).impl.id = id; + this.axNodeDataCache_[id] = obj; + + return obj; + }, + + remove: function(id) { + if (this.axNodeDataCache_[id]) + privates(this.axNodeDataCache_[id]).impl.detach(); + delete this.axNodeDataCache_[id]; + }, + + destroy: function() { + this.dispatchEvent('destroyed', 'none'); + for (var id in this.axNodeDataCache_) + this.remove(id); + this.detach(); + }, + + setHostNode(hostNode) { + this.hostNode_ = hostNode; + }, + + onAccessibilityEvent: function(eventParams) { + var targetNode = this.get(eventParams.targetID); + if (targetNode) { + var targetNodeImpl = privates(targetNode).impl; + targetNodeImpl.dispatchEvent( + eventParams.eventType, eventParams.eventFrom, + eventParams.mouseX, eventParams.mouseY); + + if (eventParams.actionRequestID != -1) { + this.onActionResult(eventParams.actionRequestID, targetNode); + } + } else { + logging.WARNING('Got ' + eventParams.eventType + + ' event on unknown node: ' + eventParams.targetID + + '; this: ' + this.id); + } + return true; + }, + + addActionResultCallback: function(callback) { + this.actionRequestIDToCallback_[++this.actionRequestCounter_] = callback; + return this.actionRequestCounter_; + }, + + onActionResult: function(requestID, result) { + if (requestID in this.actionRequestIDToCallback_) { + this.actionRequestIDToCallback_[requestID](result); + delete this.actionRequestIDToCallback_[requestID]; + } + }, + + toString: function() { + function toStringInternal(nodeImpl, indent) { + if (!nodeImpl) + return ''; + var output = ''; + if (nodeImpl.isRootNode) + output += indent + 'tree id=' + nodeImpl.treeID + '\n'; + output += indent + + $Function.call(AutomationNodeImpl.prototype.toString, nodeImpl) + '\n'; + indent += ' '; + var children = nodeImpl.children; + for (var i = 0; i < children.length; ++i) + output += toStringInternal(privates(children[i]).impl, indent); + return output; + } + return toStringInternal(this, ''); + }, +}; + +function AutomationNode() { + privates(AutomationNode).constructPrivate(this, arguments); +} +utils.expose(AutomationNode, AutomationNodeImpl, { + functions: [ + 'doDefault', + 'find', + 'findAll', + 'focus', + 'getImageData', + 'hitTest', + 'hitTestWithReply', + 'makeVisible', + 'matches', + 'performCustomAction', + 'performStandardAction', + 'replaceSelectedText', + 'resumeMedia', + 'scrollBackward', + 'scrollForward', + 'scrollUp', + 'scrollDown', + 'scrollLeft', + 'scrollRight', + 'setSelection', + 'setSequentialFocusNavigationStartingPoint', + 'setValue', + 'showContextMenu', + 'startDuckingMedia', + 'stopDuckingMedia', + 'suspendMedia', + 'addEventListener', + 'removeEventListener', + 'domQuerySelector', + 'toString', + 'boundsForRange', + ], + readonly: $Array.concat(publicAttributes, [ + 'parent', + 'firstChild', + 'lastChild', + 'children', + 'previousSibling', + 'nextSibling', + 'isRootNode', + 'role', + 'checked', + 'defaultActionVerb', + 'restriction', + 'state', + 'location', + 'indexInParent', + 'lineStartOffsets', + 'root', + 'htmlAttributes', + 'nameFrom', + 'bold', + 'italic', + 'underline', + 'lineThrough', + 'customActions', + 'standardActions', + 'unclippedLocation', + ]), +}); + +function AutomationRootNode() { + privates(AutomationRootNode).constructPrivate(this, arguments); +} +utils.expose(AutomationRootNode, AutomationRootNodeImpl, { + superclass: AutomationNode, + readonly: [ + 'chromeChannel', + 'docTitle', + 'docUrl', + 'docLoaded', + 'docLoadingProgress', + 'anchorObject', + 'anchorOffset', + 'anchorAffinity', + 'focusObject', + 'focusOffset', + 'focusAffinity', + ], +}); + +utils.defineProperty(AutomationRootNode, 'get', function(treeID) { + return AutomationRootNodeImpl.get(treeID); +}); + +utils.defineProperty(AutomationRootNode, 'getOrCreate', function(treeID) { + return AutomationRootNodeImpl.getOrCreate(treeID); +}); + +utils.defineProperty(AutomationRootNode, 'destroy', function(treeID) { + AutomationRootNodeImpl.destroy(treeID); +}); + +exports.$set('AutomationNode', AutomationNode); +exports.$set('AutomationRootNode', AutomationRootNode);
diff --git a/chromecast/renderer/resources/extensions/automation_custom_bindings.js b/chromecast/renderer/resources/extensions/automation_custom_bindings.js new file mode 100644 index 0000000..8ec1c9c --- /dev/null +++ b/chromecast/renderer/resources/extensions/automation_custom_bindings.js
@@ -0,0 +1,373 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Custom bindings for the automation API. +var AutomationNode = require('automationNode').AutomationNode; +var AutomationRootNode = require('automationNode').AutomationRootNode; +var automation = apiBridge || require('binding').Binding.create('automation'); +var automationInternal = + getInternalApi ? + getInternalApi('automationInternal') : + require('binding').Binding.create('automationInternal').generate(); +var exceptionHandler = require('uncaught_exception_handler'); +var logging = requireNative('logging'); +var nativeAutomationInternal = requireNative('automationInternal'); +var DestroyAccessibilityTree = + nativeAutomationInternal.DestroyAccessibilityTree; +var GetIntAttribute = nativeAutomationInternal.GetIntAttribute; +var StartCachingAccessibilityTrees = + nativeAutomationInternal.StartCachingAccessibilityTrees; +var AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver; +var RemoveTreeChangeObserver = + nativeAutomationInternal.RemoveTreeChangeObserver; +var GetFocusNative = nativeAutomationInternal.GetFocus; + +var jsLastError = bindingUtil ? undefined : require('lastError'); +function hasLastError() { + return bindingUtil ? + bindingUtil.hasLastError() : jsLastError.hasError(chrome); +} + +/** + * A namespace to export utility functions to other files in automation. + */ +window.automationUtil = function() {}; + +// TODO(aboxhall): Look into using WeakMap +var idToCallback = {}; + +var DESKTOP_TREE_ID = 0; + +automationUtil.storeTreeCallback = function(id, callback) { + if (!callback) + return; + + var targetTree = AutomationRootNode.get(id); + if (!targetTree) { + // If we haven't cached the tree, hold the callback until the tree is + // populated by the initial onAccessibilityEvent call. + if (id in idToCallback) + idToCallback[id].push(callback); + else + idToCallback[id] = [callback]; + } else { + callback(targetTree); + } +}; + +/** + * Global list of tree change observers. + * @type {Object<number, TreeChangeObserver>} + */ +automationUtil.treeChangeObserverMap = {}; + +/** + * The id of the next tree change observer. + * @type {number} + */ +automationUtil.nextTreeChangeObserverId = 1; + +/** + * @type {AutomationNode} The current focused node. This is only updated + * when calling automationUtil.updateFocusedNode. + */ +automationUtil.focusedNode = null; + +/** + * Gets the currently focused AutomationNode. + * @return {AutomationNode} + */ +automationUtil.getFocus = function() { + var focusedNodeInfo = GetFocusNative(DESKTOP_TREE_ID); + if (!focusedNodeInfo) + return null; + var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId); + if (tree) + return privates(tree).impl.get(focusedNodeInfo.nodeId); +}; + +/** + * Update automationUtil.focusedNode to be the node that currently has focus. + */ +automationUtil.updateFocusedNode = function() { + automationUtil.focusedNode = automationUtil.getFocus(); +}; + +/** + * Updates the focus on blur. + */ +automationUtil.updateFocusedNodeOnBlur = function() { + var focus = automationUtil.getFocus(); + automationUtil.focusedNode = focus ? focus.root : null; +}; + +automation.registerCustomHook(function(bindingsAPI) { + var apiFunctions = bindingsAPI.apiFunctions; + + // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj. + apiFunctions.setHandleRequest('getTree', function getTree(tabID, callback) { + StartCachingAccessibilityTrees(); + + // enableTab() ensures the renderer for the active or specified tab has + // accessibility enabled, and fetches its ax tree id to use as + // a key in the idToAutomationRootNode map. The callback to + // enableTab is bound to the callback passed in to getTree(), so that once + // the tree is available (either due to having been cached earlier, or after + // an accessibility event occurs which causes the tree to be populated), the + // callback can be called. + var params = { tabID: tabID }; + automationInternal.enableTab(params, + function onEnable(id) { + if (hasLastError()) { + callback(); + return; + } + automationUtil.storeTreeCallback(id, callback); + }); + }); + + var desktopTree = null; + apiFunctions.setHandleRequest('getDesktop', function(callback) { + StartCachingAccessibilityTrees(); + desktopTree = AutomationRootNode.get(DESKTOP_TREE_ID); + if (!desktopTree) { + if (DESKTOP_TREE_ID in idToCallback) + idToCallback[DESKTOP_TREE_ID].push(callback); + else + idToCallback[DESKTOP_TREE_ID] = [callback]; + + // TODO(dtseng): Disable desktop tree once desktop object goes out of + // scope. + automationInternal.enableDesktop(function() { + if (hasLastError()) { + AutomationRootNode.destroy(DESKTOP_TREE_ID); + callback(); + return; + } + }); + } else { + callback(desktopTree); + } + }); + + apiFunctions.setHandleRequest('getFocus', function(callback) { + callback(automationUtil.getFocus()); + }); + + function removeTreeChangeObserver(observer) { + for (var id in automationUtil.treeChangeObserverMap) { + if (automationUtil.treeChangeObserverMap[id] == observer) { + RemoveTreeChangeObserver(id); + delete automationUtil.treeChangeObserverMap[id]; + return; + } + } + } + apiFunctions.setHandleRequest('removeTreeChangeObserver', function(observer) { + removeTreeChangeObserver(observer); + }); + + function addTreeChangeObserver(filter, observer) { + removeTreeChangeObserver(observer); + var id = automationUtil.nextTreeChangeObserverId++; + AddTreeChangeObserver(id, filter); + automationUtil.treeChangeObserverMap[id] = observer; + } + apiFunctions.setHandleRequest('addTreeChangeObserver', + function(filter, observer) { + addTreeChangeObserver(filter, observer); + }); + + apiFunctions.setHandleRequest('setDocumentSelection', function(params) { + var anchorNodeImpl = privates(params.anchorObject).impl; + var focusNodeImpl = privates(params.focusObject).impl; + if (anchorNodeImpl.treeID !== focusNodeImpl.treeID) + throw new Error('Selection anchor and focus must be in the same tree.'); + if (anchorNodeImpl.treeID === DESKTOP_TREE_ID) { + throw new Error('Use AutomationNode.setSelection to set the selection ' + + 'in the desktop tree.'); + } + automationInternal.performAction({ treeID: anchorNodeImpl.treeID, + automationNodeID: anchorNodeImpl.id, + actionType: 'setSelection'}, + { focusNodeID: focusNodeImpl.id, + anchorOffset: params.anchorOffset, + focusOffset: params.focusOffset }); + }); + +}); + +automationInternal.onChildTreeID.addListener(function(treeID, + nodeID) { + var tree = AutomationRootNode.getOrCreate(treeID); + if (!tree) + return; + + var node = privates(tree).impl.get(nodeID); + if (!node) + return; + + // A WebView in the desktop tree has a different AX tree as its child. + // When we encounter a WebView with a child AX tree id that we don't + // currently have cached, explicitly request that AX tree from the + // browser process and set up a callback when it loads to attach that + // tree as a child of this node and fire appropriate events. + var childTreeID = GetIntAttribute(treeID, nodeID, 'childTreeId'); + if (!childTreeID) + return; + + var subroot = AutomationRootNode.get(childTreeID); + if (!subroot || subroot.role == 'unknown') { + automationUtil.storeTreeCallback(childTreeID, function(root) { + // Return early if the root has already been attached. + if (root.parent) + return; + + privates(root).impl.setHostNode(node); + + if (root.docLoaded) { + privates(root).impl.dispatchEvent('loadComplete', 'page'); + } + + privates(node).impl.dispatchEvent('childrenChanged', 'none'); + }); + + automationInternal.enableFrame(childTreeID); + } else { + privates(subroot).impl.setHostNode(node); + } +}); + +automationInternal.onTreeChange.addListener(function(observerID, + treeID, + nodeID, + changeType) { + var tree = AutomationRootNode.getOrCreate(treeID); + if (!tree) + return; + + var node = privates(tree).impl.get(nodeID); + if (!node) + return; + + var observer = automationUtil.treeChangeObserverMap[observerID]; + if (!observer) + return; + + try { + observer({target: node, type: changeType}); + } catch (e) { + exceptionHandler.handle('Error in tree change observer for ' + + treeChange.type, e); + } +}); + +automationInternal.onNodesRemoved.addListener(function(treeID, nodeIDs) { + var tree = AutomationRootNode.getOrCreate(treeID); + if (!tree) + return; + + for (var i = 0; i < nodeIDs.length; i++) { + privates(tree).impl.remove(nodeIDs[i]); + } +}); + +/** + * Dispatch accessibility events fired on individual nodes to its + * corresponding AutomationNode. Handle focus events specially + * (see below). + */ +automationInternal.onAccessibilityEvent.addListener(function(eventParams) { + var id = eventParams.treeID; + var targetTree = AutomationRootNode.getOrCreate(id); + if (eventParams.eventType == 'blur') { + // Work around an issue where Chrome sends us 'blur' events on the + // root node when nothing has focus, we need to treat those as focus + // events but otherwise not handle blur events specially. + var node = privates(targetTree).impl.get(eventParams.targetID); + if (node == node.root) + automationUtil.updateFocusedNodeOnBlur(); + } else if (eventParams.eventType == 'mediaStartedPlaying' || + eventParams.eventType == 'mediaStoppedPlaying') { + // These events are global to the tree. + eventParams.targetID = privates(targetTree).impl.id; + } else { + var previousFocusedNode = automationUtil.focusedNode; + automationUtil.updateFocusedNode(); + + // Fire focus events if necessary. + if (automationUtil.focusedNode && + automationUtil.focusedNode != previousFocusedNode) { + var eventParamsCopy = {}; + for (var key in eventParams) + eventParamsCopy[key] = eventParams[key]; + eventParamsCopy['eventType'] = 'focus'; + eventParamsCopy['treeID'] = + privates(automationUtil.focusedNode.root).impl.treeID; + eventParamsCopy['targetID'] = + privates(automationUtil.focusedNode).impl.id; + privates(automationUtil.focusedNode.root) + .impl.onAccessibilityEvent(eventParamsCopy); + } + } + + // Note that focus type events have already been handled above if there was a + // focused node. All other events, even non-focus events that triggered a + // focus dispatch, still need to have their original event fired. + if ((!automationUtil.focusedNode || eventParams.eventType != 'focus') && + !privates(targetTree).impl.onAccessibilityEvent(eventParams)) + return; + + // If we're not waiting on a callback to getTree(), we can early out here. + if (!(id in idToCallback)) + return; + + // We usually get a 'placeholder' tree first, which doesn't have any url + // attribute or child nodes. If we've got that, wait for the full tree before + // calling the callback. + // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553) + if (id != DESKTOP_TREE_ID && !targetTree.url && + targetTree.children.length == 0) + return; + + // If the tree wasn't available when getTree() was called, the callback will + // have been cached in idToCallback, so call and delete it now that we + // have the complete tree. + for (var i = 0; i < idToCallback[id].length; i++) { + var callback = idToCallback[id][i]; + callback(targetTree); + } + delete idToCallback[id]; +}); + +automationInternal.onAccessibilityTreeDestroyed.addListener(function(id) { + // Destroy the AutomationRootNode. + var targetTree = AutomationRootNode.get(id); + if (targetTree) { + privates(targetTree).impl.destroy(); + AutomationRootNode.destroy(id); + } else { + logging.WARNING('no targetTree to destroy'); + } + + // Destroy the native cache of the accessibility tree. + DestroyAccessibilityTree(id); +}); + +automationInternal.onAccessibilityTreeSerializationError.addListener( + function(id) { + automationInternal.enableFrame(id); +}); + +automationInternal.onActionResult.addListener( + function(treeID, requestID, result) { + var targetTree = AutomationRootNode.get(treeID); + if (!targetTree) + return; + + privates(targetTree).impl.onActionResult(requestID, result); + }); + +if (!apiBridge) + exports.$set('binding', automation.generate());
diff --git a/chromecast/renderer/resources/extensions_renderer_resources.grd b/chromecast/renderer/resources/extensions_renderer_resources.grd new file mode 100644 index 0000000..17bc2fbd --- /dev/null +++ b/chromecast/renderer/resources/extensions_renderer_resources.grd
@@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/extensions_renderer_resources.h" type="rc_header" context="default"> + <emit emit_type='prepend'></emit> + </output> + <output filename="extensions_renderer_resources.pak" type="data_package" context="default" /> + </outputs> + <release seq="1"> + <includes> + <!-- Custom bindings for extension APIs. --> + <include name="IDR_AUTOMATION_CUSTOM_BINDINGS_JS" file="extensions\automation_custom_bindings.js" type="BINDATA" /> + <include name="IDR_AUTOMATION_EVENT_JS" file="extensions\automation\automation_event.js" type="BINDATA" /> + <include name="IDR_AUTOMATION_NODE_JS" file="extensions\automation\automation_node.js" type="BINDATA" /> + </includes> + </release> +</grit>
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 04e26a4e..b4f5914 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -7,7 +7,6 @@ #include <string> #include "base/command_line.h" -#include "base/feature_list.h" #include "base/metrics/field_trial.h" #include "third_party/icu/source/common/unicode/locid.h" @@ -28,10 +27,6 @@ // all stored user keys will be converted to GaiaId) const char kTestCrosGaiaIdMigrationStarted[] = "started"; -// Controls whether enable Google Assistant feature. -const base::Feature kAssistantFeature{"ChromeOSAssistant", - base::FEATURE_DISABLED_BY_DEFAULT}; - // Controls whether enable assistant for locale. const base::Feature kAssistantFeatureForLocale{ "ChromeOSAssistantForLocale", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -48,6 +43,10 @@ } // namespace +// Controls whether enable Google Assistant feature. +const base::Feature kAssistantFeature{"ChromeOSAssistant", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Please keep the order of these switches synchronized with the header file // (i.e. in alphabetical order).
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 01b07ed..c09dff7 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -5,6 +5,7 @@ #ifndef CHROMEOS_CHROMEOS_SWITCHES_H_ #define CHROMEOS_CHROMEOS_SWITCHES_H_ +#include "base/feature_list.h" #include "base/memory/memory_pressure_monitor_chromeos.h" #include "chromeos/chromeos_export.h" @@ -159,6 +160,9 @@ CHROMEOS_EXPORT extern const char kWaitForInitialPolicyFetchForTest[]; CHROMEOS_EXPORT extern const char kWakeOnWifiPacket[]; +// Controls whether enable Google Assistant feature. +CHROMEOS_EXPORT extern const base::Feature kAssistantFeature; + // Returns true if the system should wake in response to wifi traffic. CHROMEOS_EXPORT bool WakeOnWifiEnabled();
diff --git a/chromeos/dbus/fake_smb_provider_client.cc b/chromeos/dbus/fake_smb_provider_client.cc index 2f0e89b..7fd6f7924 100644 --- a/chromeos/dbus/fake_smb_provider_client.cc +++ b/chromeos/dbus/fake_smb_provider_client.cc
@@ -158,4 +158,10 @@ base::BindOnce(std::move(callback), smbprovider::ERROR_OK, entry_list)); } +void FakeSmbProviderClient::SetupKerberos(const std::string& account_id, + SetupKerberosCallback callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), true /* success */)); +} + } // namespace chromeos
diff --git a/chromeos/dbus/fake_smb_provider_client.h b/chromeos/dbus/fake_smb_provider_client.h index 537390a..9599440 100644 --- a/chromeos/dbus/fake_smb_provider_client.h +++ b/chromeos/dbus/fake_smb_provider_client.h
@@ -91,6 +91,9 @@ void GetShares(const base::FilePath& server_url, ReadDirectoryCallback callback) override; + void SetupKerberos(const std::string& account_id, + SetupKerberosCallback callback) override; + private: DISALLOW_COPY_AND_ASSIGN(FakeSmbProviderClient); };
diff --git a/chromeos/dbus/smb_provider_client.cc b/chromeos/dbus/smb_provider_client.cc index f9a6cae..6ae80c8 100644 --- a/chromeos/dbus/smb_provider_client.cc +++ b/chromeos/dbus/smb_provider_client.cc
@@ -259,6 +259,16 @@ &callback); } + void SetupKerberos(const std::string& account_id, + SetupKerberosCallback callback) override { + dbus::MethodCall method_call(smbprovider::kSmbProviderInterface, + smbprovider::kSetupKerberosMethod); + dbus::MessageWriter writer(&method_call); + writer.AppendString(account_id); + CallMethod(&method_call, + &SmbProviderClientImpl::HandleSetupKerberosCallback, &callback); + } + protected: // DBusClient override. void Init(dbus::Bus* bus) override { @@ -419,6 +429,19 @@ std::move(callback).Run(smbprovider::ERROR_OK, delete_list); } + // Handles D-Bus callback for SetupKerberos. + void HandleSetupKerberosCallback(SetupKerberosCallback callback, + dbus::Response* response) { + dbus::MessageReader reader(response); + bool result; + if (!reader.PopBool(&result)) { + LOG(ERROR) << "SetupKerberos: parse failure."; + std::move(callback).Run(false /* success */); + } + + std::move(callback).Run(result); + } + // Default callback handler for D-Bus calls. void HandleDefaultCallback(const std::string& method_name, StatusCallback callback,
diff --git a/chromeos/dbus/smb_provider_client.h b/chromeos/dbus/smb_provider_client.h index c5c88bb..b28a042a 100644 --- a/chromeos/dbus/smb_provider_client.h +++ b/chromeos/dbus/smb_provider_client.h
@@ -40,6 +40,7 @@ using GetDeleteListCallback = base::OnceCallback<void(smbprovider::ErrorType error, const smbprovider::DeleteListProto& delete_list)>; + using SetupKerberosCallback = base::OnceCallback<void(bool success)>; ~SmbProviderClient() override; @@ -173,6 +174,12 @@ virtual void GetShares(const base::FilePath& server_url, ReadDirectoryCallback callback) = 0; + // Calls SetupKerberos. This sets up Kerberos for the user |account_id|, + // fetching the user's Kerberos files from AuthPolicy. The user must be + // ChromAD enrolled. + virtual void SetupKerberos(const std::string& account_id, + SetupKerberosCallback callback) = 0; + protected: // Create() should be used instead. SmbProviderClient();
diff --git a/chromeos/login/auth/stub_authenticator.cc b/chromeos/login/auth/stub_authenticator.cc index cb619ab1..835251d4 100644 --- a/chromeos/login/auth/stub_authenticator.cc +++ b/chromeos/login/auth/stub_authenticator.cc
@@ -79,7 +79,8 @@ void StubAuthenticator::LoginAsKioskAccount( const AccountId& /* app_account_id */, bool use_guest_mount) { - UserContext user_context(expected_user_context_.GetAccountId()); + UserContext user_context(user_manager::UserType::USER_TYPE_KIOSK_APP, + expected_user_context_.GetAccountId()); user_context.SetIsUsingOAuth(false); user_context.SetUserIDHash( expected_user_context_.GetAccountId().GetUserEmail() + kUserIdHashSuffix); @@ -88,7 +89,8 @@ void StubAuthenticator::LoginAsArcKioskAccount( const AccountId& /* app_account_id */) { - UserContext user_context(expected_user_context_.GetAccountId()); + UserContext user_context(user_manager::USER_TYPE_ARC_KIOSK_APP, + expected_user_context_.GetAccountId()); user_context.SetIsUsingOAuth(false); user_context.SetUserIDHash( expected_user_context_.GetAccountId().GetUserEmail() + kUserIdHashSuffix);
diff --git a/chromeos/login/auth/user_context.cc b/chromeos/login/auth/user_context.cc index 1e58b8c9..e4db1c96 100644 --- a/chromeos/login/auth/user_context.cc +++ b/chromeos/login/auth/user_context.cc
@@ -3,35 +3,23 @@ // found in the LICENSE file. #include "chromeos/login/auth/user_context.h" +#include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_names.h" namespace chromeos { -namespace { - -user_manager::UserType CalculateUserType(const AccountId& account_id) { - // UserManager is not initialized in unit tests. - if (!user_manager::UserManager::IsInitialized()) - return user_manager::USER_TYPE_REGULAR; - - if (user_manager::UserManager::Get()->IsSupervisedAccountId(account_id)) - return user_manager::USER_TYPE_SUPERVISED; - - if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) - return user_manager::USER_TYPE_ACTIVE_DIRECTORY; - - return user_manager::USER_TYPE_REGULAR; -} - -} // anonymous namespace - UserContext::UserContext() : account_id_(EmptyAccountId()) {} UserContext::UserContext(const UserContext& other) = default; -UserContext::UserContext(const AccountId& account_id) - : UserContext(CalculateUserType(account_id), account_id) {} +UserContext::UserContext(const user_manager::User& user) + : account_id_(user.GetAccountId()), user_type_(user.GetType()) { + if (user_type_ == user_manager::USER_TYPE_REGULAR) { + account_id_.SetUserEmail( + user_manager::CanonicalizeUserID(account_id_.GetUserEmail())); + } +} UserContext::UserContext(user_manager::UserType user_type, const AccountId& account_id)
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h index 26d1f7e..6159022 100644 --- a/chromeos/login/auth/user_context.h +++ b/chromeos/login/auth/user_context.h
@@ -17,6 +17,10 @@ class AccountId; +namespace user_manager { +class User; +} + namespace chromeos { // Information that is passed around while authentication is in progress. The @@ -42,7 +46,7 @@ UserContext(); UserContext(const UserContext& other); - explicit UserContext(const AccountId& account_id); + explicit UserContext(const user_manager::User& user); UserContext(user_manager::UserType user_type, const AccountId& account_id); ~UserContext();
diff --git a/components/app_modal_strings_grdp/OWNERS b/components/app_modal_strings_grdp/OWNERS new file mode 100644 index 0000000..d092bde --- /dev/null +++ b/components/app_modal_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/app_modal/OWNERS
diff --git a/components/app_modal_strings_grdp/README.md b/components/app_modal_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/app_modal_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/assist_ranker/fake_ranker_model_loader.cc b/components/assist_ranker/fake_ranker_model_loader.cc index b1804ce..9097243 100644 --- a/components/assist_ranker/fake_ranker_model_loader.cc +++ b/components/assist_ranker/fake_ranker_model_loader.cc
@@ -19,7 +19,7 @@ FakeRankerModelLoader::~FakeRankerModelLoader() {} void FakeRankerModelLoader::NotifyOfRankerActivity() { - if (validate_model_cb_.Run(*ranker_model_.get()) == RankerModelStatus::OK) { + if (validate_model_cb_.Run(*ranker_model_) == RankerModelStatus::OK) { on_model_available_cb_.Run(std::move(ranker_model_)); } }
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc index 1db77a6c..f5dabe4 100644 --- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc +++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -131,7 +131,7 @@ class FormAutofillUtilsTest : public content::RenderViewTest { public: - FormAutofillUtilsTest() : content::RenderViewTest() {} + FormAutofillUtilsTest() {} ~FormAutofillUtilsTest() override {} };
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index b163be5..0432318 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -662,7 +662,6 @@ content::RenderFrame* render_frame, service_manager::BinderRegistry* registry) : content::RenderFrameObserver(render_frame), - web_input_to_password_info_(), last_supplied_password_info_iter_(web_input_to_password_info_.end()), logging_state_active_(false), was_username_autofilled_(false),
diff --git a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc index 8737792..30058360 100644 --- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc +++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -191,7 +191,7 @@ class MAYBE_PasswordFormConversionUtilsTest : public content::RenderViewTest { public: - MAYBE_PasswordFormConversionUtilsTest() : content::RenderViewTest() {} + MAYBE_PasswordFormConversionUtilsTest() {} ~MAYBE_PasswordFormConversionUtilsTest() override {} protected:
diff --git a/components/autofill/core/browser/address.cc b/components/autofill/core/browser/address.cc index 04f2d8c..f3ab3a3 100644 --- a/components/autofill/core/browser/address.cc +++ b/components/autofill/core/browser/address.cc
@@ -27,7 +27,7 @@ Address::Address() {} -Address::Address(const Address& address) : FormGroup() { +Address::Address(const Address& address) { *this = address; }
diff --git a/components/autofill/core/browser/autocomplete_history_manager.cc b/components/autofill/core/browser/autocomplete_history_manager.cc index 1a4f54a..f9f06cf 100644 --- a/components/autofill/core/browser/autocomplete_history_manager.cc +++ b/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -68,7 +68,7 @@ return; } - if (database_.get()) { + if (database_) { pending_query_handle_ = database_->GetFormValuesForElementName( name, prefix, kMaxAutocompleteMenuItems, this); } @@ -108,7 +108,7 @@ void AutocompleteHistoryManager::OnRemoveAutocompleteEntry( const base::string16& name, const base::string16& value) { - if (database_.get()) + if (database_) database_->RemoveFormValueForElementName(name, value); } @@ -119,7 +119,7 @@ void AutocompleteHistoryManager::CancelPendingQuery() { if (pending_query_handle_) { - if (database_.get()) + if (database_) database_->CancelRequest(pending_query_handle_); pending_query_handle_ = 0; }
diff --git a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc index 369d298..c22cf0c4 100644 --- a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc +++ b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -101,7 +101,7 @@ valid_cc.form_control_type = "text"; form.fields.push_back(valid_cc); - EXPECT_CALL(*web_data_service_.get(), AddFormFields(_)).Times(0); + EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0); autocomplete_manager_->OnWillSubmitForm(form); } @@ -140,7 +140,7 @@ ssn.form_control_type = "text"; form.fields.push_back(ssn); - EXPECT_CALL(*web_data_service_.get(), AddFormFields(_)).Times(0); + EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0); autocomplete_manager_->OnWillSubmitForm(form); } @@ -182,7 +182,7 @@ field.should_autocomplete = false; form.fields.push_back(field); - EXPECT_CALL(*web_data_service_.get(), AddFormFields(_)).Times(0); + EXPECT_CALL(*web_data_service_, AddFormFields(_)).Times(0); autocomplete_manager_->OnWillSubmitForm(form); }
diff --git a/components/autofill/core/browser/autofill_ie_toolbar_import_win.cc b/components/autofill/core/browser/autofill_ie_toolbar_import_win.cc index 15ad630..1edd5bd 100644 --- a/components/autofill/core/browser/autofill_ie_toolbar_import_win.cc +++ b/components/autofill/core/browser/autofill_ie_toolbar_import_win.cc
@@ -79,7 +79,7 @@ const wchar_t* value_name) { DWORD data_type = REG_BINARY; DWORD data_size = 0; - LONG result = key.ReadValue(value_name, NULL, &data_size, &data_type); + LONG result = key.ReadValue(value_name, nullptr, &data_size, &data_type); if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY) return base::string16(); std::string data; @@ -284,8 +284,8 @@ RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); CreditCard credit_card; credit_card.set_origin(kIEToolbarImportOrigin); - if (ImportSingleFormGroup( - key, reg_to_field, app_locale, &credit_card, NULL)) { + if (ImportSingleFormGroup(key, reg_to_field, app_locale, &credit_card, + nullptr)) { base::string16 cc_number = credit_card.GetRawInfo(CREDIT_CARD_NUMBER); if (!cc_number.empty()) credit_cards->push_back(credit_card);
diff --git a/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc b/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc index aba32f1..abc0088 100644 --- a/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc +++ b/components/autofill/core/browser/autofill_ie_toolbar_import_win_unittest.cc
@@ -141,7 +141,7 @@ } void AutofillIeToolbarImportTest::TearDown() { - EXPECT_EQ(ERROR_SUCCESS, RegOverridePredefKey(HKEY_CURRENT_USER, NULL)); + EXPECT_EQ(ERROR_SUCCESS, RegOverridePredefKey(HKEY_CURRENT_USER, nullptr)); temp_hkcu_hive_key_.Close(); RegKey key(HKEY_CURRENT_USER, kUnitTestRegistrySubKey, KEY_ALL_ACCESS); key.DeleteKey(L"");
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index dc7f14a..b60bec26 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -108,11 +108,11 @@ } MATCHER(CompareMetricsIgnoringMillisecondsSinceFormParsed, "") { - const ukm::mojom::UkmMetric* lhs = ::testing::get<0>(arg).get(); + const auto& lhs = ::testing::get<0>(arg); const std::pair<const char*, int64_t>& rhs = ::testing::get<1>(arg); - return lhs->metric_hash == base::HashMetricName(rhs.first) && - (lhs->value == rhs.second || - (lhs->value > 0 && + return lhs.first == base::HashMetricName(rhs.first) && + (lhs.second == rhs.second || + (lhs.second > 0 && rhs.first == UkmSuggestionFilledType::kMillisecondsSinceFormParsedName)); }
diff --git a/components/autofill/core/browser/contact_info.cc b/components/autofill/core/browser/contact_info.cc index 7d54216..105d135c 100644 --- a/components/autofill/core/browser/contact_info.cc +++ b/components/autofill/core/browser/contact_info.cc
@@ -20,7 +20,7 @@ NameInfo::NameInfo() {} -NameInfo::NameInfo(const NameInfo& info) : FormGroup() { +NameInfo::NameInfo(const NameInfo& info) { *this = info; } @@ -181,7 +181,7 @@ EmailInfo::EmailInfo() {} -EmailInfo::EmailInfo(const EmailInfo& info) : FormGroup() { +EmailInfo::EmailInfo(const EmailInfo& info) { *this = info; } @@ -217,7 +217,7 @@ CompanyInfo::CompanyInfo() {} -CompanyInfo::CompanyInfo(const CompanyInfo& info) : FormGroup() { +CompanyInfo::CompanyInfo(const CompanyInfo& info) { *this = info; }
diff --git a/components/autofill/core/browser/country_combobox_model.cc b/components/autofill/core/browser/country_combobox_model.cc index 5fe8095..280c0234 100644 --- a/components/autofill/core/browser/country_combobox_model.cc +++ b/components/autofill/core/browser/country_combobox_model.cc
@@ -89,7 +89,7 @@ } bool CountryComboboxModel::IsItemSeparatorAt(int index) { - return !countries_[index].get(); + return !countries_[index]; } std::string CountryComboboxModel::GetDefaultCountryCode() const {
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc index 4809b10..a012ab2 100644 --- a/components/autofill/core/browser/form_data_importer.cc +++ b/components/autofill/core/browser/form_data_importer.cc
@@ -300,7 +300,7 @@ const FormStructure& form, bool should_return_local_card, std::unique_ptr<CreditCard>* imported_credit_card) { - DCHECK(!imported_credit_card->get()); + DCHECK(!*imported_credit_card); // The candidate for credit card import. There are many ways for the candidate // to be rejected (see everywhere this function returns false, below).
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 23c69b4..43fdcc0 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -378,7 +378,7 @@ AutofillMetrics::LogIsAutofillEnabledAtStartup(IsAutofillEnabled()); // WebDataService may not be available in tests. - if (!database_.get()) + if (!database_) return; LoadProfiles(); @@ -402,7 +402,7 @@ CancelPendingQuery(&pending_creditcards_query_); CancelPendingQuery(&pending_server_creditcards_query_); - if (database_.get()) + if (database_) database_->RemoveObserver(this); } @@ -548,7 +548,7 @@ } void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) { - if (is_off_the_record_ || !database_.get()) + if (is_off_the_record_ || !database_) return; CreditCard* credit_card = GetCreditCardByGUID(data_model.guid()); @@ -588,7 +588,7 @@ if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid())) return; - if (!database_.get()) + if (!database_) return; // Don't add a duplicate. @@ -619,7 +619,7 @@ return; } - if (!database_.get()) + if (!database_) return; // Make the update. @@ -653,7 +653,7 @@ if (FindByGUID<CreditCard>(local_credit_cards_, credit_card.guid())) return; - if (!database_.get()) + if (!database_) return; // Don't add a duplicate. @@ -688,7 +688,7 @@ // Update the cached version. *existing_credit_card = credit_card; - if (!database_.get()) + if (!database_) return; // Make the update. @@ -704,7 +704,7 @@ DCHECK(!credit_card.IsEmpty(app_locale_)); DCHECK(!credit_card.server_id().empty()); - if (is_off_the_record_ || !database_.get()) + if (is_off_the_record_ || !database_) return; // Don't add a duplicate. @@ -723,7 +723,7 @@ const CreditCard& credit_card) { DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type()); - if (is_off_the_record_ || !database_.get()) + if (is_off_the_record_ || !database_) return; // Look up by server id, not GUID. @@ -752,7 +752,7 @@ const CreditCard& credit_card) { DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type()); - if (is_off_the_record_ || !database_.get()) + if (is_off_the_record_ || !database_) return; database_->UpdateServerCardMetadata(credit_card); @@ -842,7 +842,7 @@ if (!is_credit_card && !is_profile) return; - if (!database_.get()) + if (!database_) return; if (is_credit_card) { @@ -1348,7 +1348,7 @@ IsEmptyFunctor<AutofillProfile>(app_locale_)), profiles->end()); - if (!database_.get()) + if (!database_) return; // Any profiles that are not in the new profile list should be removed from @@ -1391,7 +1391,7 @@ IsEmptyFunctor<CreditCard>(app_locale_)), credit_cards->end()); - if (!database_.get()) + if (!database_) return; // Any credit cards that are not in the new credit card list should be @@ -1424,7 +1424,7 @@ } void PersonalDataManager::LoadProfiles() { - if (!database_.get()) { + if (!database_) { NOTREACHED(); return; } @@ -1437,7 +1437,7 @@ } void PersonalDataManager::LoadCreditCards() { - if (!database_.get()) { + if (!database_) { NOTREACHED(); return; } @@ -1452,7 +1452,7 @@ void PersonalDataManager::CancelPendingQuery( WebDataServiceBase::Handle* handle) { if (*handle) { - if (!database_.get()) { + if (!database_) { NOTREACHED(); return; }
diff --git a/components/autofill/core/browser/phone_number_i18n.cc b/components/autofill/core/browser/phone_number_i18n.cc index 6fdd966..e849e44 100644 --- a/components/autofill/core/browser/phone_number_i18n.cc +++ b/components/autofill/core/browser/phone_number_i18n.cc
@@ -241,14 +241,14 @@ // Parse phone numbers based on the region ::i18n::phonenumbers::PhoneNumber i18n_number1; - if (phone_util->Parse(base::UTF16ToUTF8(number_a), region.c_str(), - &i18n_number1) != PhoneNumberUtil::NO_PARSING_ERROR) { + if (phone_util->Parse(base::UTF16ToUTF8(number_a), region, &i18n_number1) != + PhoneNumberUtil::NO_PARSING_ERROR) { return false; } ::i18n::phonenumbers::PhoneNumber i18n_number2; - if (phone_util->Parse(base::UTF16ToUTF8(number_b), region.c_str(), - &i18n_number2) != PhoneNumberUtil::NO_PARSING_ERROR) { + if (phone_util->Parse(base::UTF16ToUTF8(number_b), region, &i18n_number2) != + PhoneNumberUtil::NO_PARSING_ERROR) { return false; } @@ -379,7 +379,7 @@ region_ = other.region_; - if (other.i18n_number_.get()) + if (other.i18n_number_) i18n_number_.reset( new ::i18n::phonenumbers::PhoneNumber(*other.i18n_number_)); else
diff --git a/components/autofill/core/browser/region_data_loader_impl.cc b/components/autofill/core/browser/region_data_loader_impl.cc index 4dbe7a91..9415cc2 100644 --- a/components/autofill/core/browser/region_data_loader_impl.cc +++ b/components/autofill/core/browser/region_data_loader_impl.cc
@@ -31,7 +31,7 @@ int64_t timeout_ms) { callback_ = callback; region_data_supplier_.LoadRules(country_code, - *region_data_supplier_callback_.get()); + *region_data_supplier_callback_); timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(timeout_ms), base::Bind(&RegionDataLoaderImpl::OnRegionDataLoaded,
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc index 08aad8eb9..349a5b9 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
@@ -95,9 +95,9 @@ std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!sync_processor_.get()); - DCHECK(sync_processor.get()); - DCHECK(sync_error_factory.get()); + DCHECK(!sync_processor_); + DCHECK(sync_processor); + DCHECK(sync_error_factory); DVLOG(1) << "Associating Autofill: MergeDataAndStartSyncing"; syncer::SyncMergeResult merge_result(type); @@ -216,7 +216,7 @@ syncer::SyncDataList AutofillProfileSyncableService::GetAllSyncData( syncer::ModelType type) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(sync_processor_.get()); + DCHECK(sync_processor_); DCHECK_EQ(type, syncer::AUTOFILL_PROFILE); syncer::SyncDataList current_data; @@ -229,7 +229,7 @@ const base::Location& from_here, const syncer::SyncChangeList& change_list) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!sync_processor_.get()) { + if (!sync_processor_) { syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, "Models not yet associated.", @@ -279,7 +279,7 @@ // up we are going to process all when MergeData..() is called. If we receive // notification after the sync exited, it will be sinced next time Chrome // starts. - if (sync_processor_.get()) { + if (sync_processor_) { ActOnChange(change); } else if (!flare_.is_null()) { flare_.Run(syncer::AUTOFILL_PROFILE); @@ -579,7 +579,7 @@ (change.type() == AutofillProfileChange::REMOVE && !change.data_model()) || (change.type() != AutofillProfileChange::REMOVE && change.data_model())); - DCHECK(sync_processor_.get()); + DCHECK(sync_processor_); if (change.data_model() && change.data_model()->record_type() != AutofillProfile::LOCAL_PROFILE) {
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc index 27f562f9..d48dd08 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -49,7 +49,7 @@ } AutofillWebDataBackendImpl::~AutofillWebDataBackendImpl() { - DCHECK(!user_data_.get()); // Forgot to call ResetUserData? + DCHECK(!user_data_); // Forgot to call ResetUserData? } WebDatabase* AutofillWebDataBackendImpl::GetDatabase() {
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc index f81b0b5f..c9d3d8a5 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -261,14 +261,14 @@ void AutofillWebDataService::AddObserver( AutofillWebDataServiceObserverOnDBSequence* observer) { DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); - if (autofill_backend_.get()) + if (autofill_backend_) autofill_backend_->AddObserver(observer); } void AutofillWebDataService::RemoveObserver( AutofillWebDataServiceObserverOnDBSequence* observer) { DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); - if (autofill_backend_.get()) + if (autofill_backend_) autofill_backend_->RemoveObserver(observer); }
diff --git a/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/components/autofill/core/browser/webdata/web_data_service_unittest.cc index 1afac62..528064c 100644 --- a/components/autofill/core/browser/webdata/web_data_service_unittest.cc +++ b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -133,8 +133,7 @@ class WebDataServiceAutofillTest : public WebDataServiceTest { public: WebDataServiceAutofillTest() - : WebDataServiceTest(), - unique_id1_(1), + : unique_id1_(1), unique_id2_(2), test_timeout_(TimeDelta::FromSeconds(kWebDataServiceTimeoutSeconds)), done_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
diff --git a/components/autofill_strings_grdp/OWNERS b/components/autofill_strings_grdp/OWNERS new file mode 100644 index 0000000..50a21bb --- /dev/null +++ b/components/autofill_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/autofill/OWNERS
diff --git a/components/autofill_strings_grdp/README.md b/components/autofill_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/autofill_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/bookmark_bar_strings_grdp/OWNERS b/components/bookmark_bar_strings_grdp/OWNERS new file mode 100644 index 0000000..166b0f10 --- /dev/null +++ b/components/bookmark_bar_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/bookmarks/OWNERS
diff --git a/components/bookmark_bar_strings_grdp/README.md b/components/bookmark_bar_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/bookmark_bar_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index 58d9823..147ea6e 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -148,7 +148,7 @@ for (BookmarkModelObserver& observer : observers_) observer.BookmarkModelBeingDeleted(this); - if (store_.get()) { + if (store_) { // The store maintains a reference back to us. We need to tell it we're gone // so that it doesn't try and invoke a method back on us again. store_->BookmarkModelDeleted(); @@ -261,7 +261,7 @@ } } EndExtensiveChanges(); - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -311,7 +311,7 @@ BookmarkNode* mutable_new_parent = AsMutable(new_parent); mutable_new_parent->Add(std::move(owned_node), index); - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -339,7 +339,7 @@ // don't need to send notifications here. CloneBookmarkNode(this, drag_data.elements, new_parent, index, true); - if (store_.get()) + if (store_) store_->ScheduleSave(); } @@ -383,7 +383,7 @@ if (node->is_url()) index_->Add(node); - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -410,7 +410,7 @@ AddNodeToInternalMaps(mutable_node); } - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -446,7 +446,7 @@ observer.OnWillChangeBookmarkMetaInfo(this, node); AsMutable(node)->SetMetaInfoMap(meta_info_map); - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -482,7 +482,7 @@ return; AsMutable(node)->set_sync_transaction_version(sync_transaction_version); - if (store_.get()) + if (store_) store_->ScheduleSave(); } @@ -531,7 +531,7 @@ if (date_added > node->parent()->date_folder_modified()) { // Will trigger store_->ScheduleSave(). SetDateFolderModified(node->parent(), date_added); - } else if (store_.get()) { + } else if (store_) { store_->ScheduleSave(); } } @@ -682,7 +682,7 @@ mutable_parent->children().end(), SortComparator(collator.get())); - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -716,7 +716,7 @@ } mutable_parent->children().swap(new_children); - if (store_.get()) + if (store_) store_->ScheduleSave(); } @@ -729,7 +729,7 @@ DCHECK(parent); AsMutable(parent)->set_date_folder_modified(time); - if (store_.get()) + if (store_) store_->ScheduleSave(); } @@ -888,7 +888,7 @@ node = RemoveNodeAndGetRemovedUrls(node_ptr, &removed_urls); } - if (store_.get()) + if (store_) store_->ScheduleSave(); for (BookmarkModelObserver& observer : observers_) @@ -946,7 +946,7 @@ BookmarkNode* node_ptr = node.get(); parent->Add(std::move(node), index); - if (store_.get()) + if (store_) store_->ScheduleSave(); {
diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index d1af975..fb493a9 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc
@@ -69,14 +69,14 @@ std::unique_ptr<base::Value> root = deserializer.Deserialize(nullptr, nullptr); - if (root.get()) { + if (root) { // Building the index can take a while, so we do it on the background // thread. int64_t max_node_id = 0; BookmarkCodec codec; TimeTicks start_time = TimeTicks::Now(); codec.Decode(details->bb_node(), details->other_folder_node(), - details->mobile_folder_node(), &max_node_id, *root.get()); + details->mobile_folder_node(), &max_node_id, *root); details->set_max_id(std::max(max_node_id, details->max_id())); details->set_computed_checksum(codec.computed_checksum()); details->set_stored_checksum(codec.stored_checksum());
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index f7bf4c7..f70196f 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -945,7 +945,7 @@ ClearUnrecoverableError(); last_actionable_error_ = SyncProtocolError(); // Clear the data type errors as well. - if (data_type_manager_.get()) + if (data_type_manager_) data_type_manager_->ResetDataTypeErrors(); }
diff --git a/components/browser_watcher/endsession_watcher_window_win.cc b/components/browser_watcher/endsession_watcher_window_win.cc index cf4bb82..8f6d313 100644 --- a/components/browser_watcher/endsession_watcher_window_win.cc +++ b/components/browser_watcher/endsession_watcher_window_win.cc
@@ -21,16 +21,15 @@ WNDCLASSEX window_class = {0}; base::win::InitializeWindowClass( kWindowClassName, - &base::win::WrappedWindowProc<EndSessionWatcherWindow::WndProcThunk>, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, - &window_class); + &base::win::WrappedWindowProc<EndSessionWatcherWindow::WndProcThunk>, 0, + 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr, &window_class); instance_ = window_class.hInstance; ATOM clazz = ::RegisterClassEx(&window_class); DCHECK(clazz); // TODO(siggi): will a message window do here? - window_ = ::CreateWindow(kWindowClassName, - 0, 0, 0, 0, 0, 0, 0, 0, instance_, 0); + window_ = ::CreateWindow(kWindowClassName, nullptr, 0, 0, 0, 0, 0, nullptr, + nullptr, instance_, nullptr); ::SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); DCHECK_EQ(::GetWindowLongPtr(window_, GWLP_USERDATA), reinterpret_cast<LONG_PTR>(this));
diff --git a/components/browser_watcher/exit_code_watcher_win_unittest.cc b/components/browser_watcher/exit_code_watcher_win_unittest.cc index 9c1a074..e5edaa28 100644 --- a/components/browser_watcher/exit_code_watcher_win_unittest.cc +++ b/components/browser_watcher/exit_code_watcher_win_unittest.cc
@@ -123,7 +123,7 @@ ExitCodeWatcher watcher(kRegistryPath); // A waitable event has a non process-handle. - base::Process event(::CreateEvent(NULL, false, false, NULL)); + base::Process event(::CreateEvent(nullptr, false, false, nullptr)); // A non-process handle should fail. EXPECT_FALSE(watcher.Initialize(std::move(event)));
diff --git a/components/browser_watcher/watcher_metrics_provider_win_unittest.cc b/components/browser_watcher/watcher_metrics_provider_win_unittest.cc index af78d5d..65ba549a 100644 --- a/components/browser_watcher/watcher_metrics_provider_win_unittest.cc +++ b/components/browser_watcher/watcher_metrics_provider_win_unittest.cc
@@ -84,7 +84,7 @@ base::FilePath(), GetExecutableDetailsCallback()); - provider.ProvideStabilityMetrics(NULL); + provider.ProvideStabilityMetrics(nullptr); histogram_tester_.ExpectBucketCount( WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 0, 11); histogram_tester_.ExpectBucketCount( @@ -108,7 +108,7 @@ base::FilePath(), GetExecutableDetailsCallback()); - provider.ProvideStabilityMetrics(NULL); + provider.ProvideStabilityMetrics(nullptr); histogram_tester_.ExpectUniqueSample( WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 0, 11);
diff --git a/components/browser_watcher/window_hang_monitor_win.cc b/components/browser_watcher/window_hang_monitor_win.cc index 96cadb62..ca89e6a 100644 --- a/components/browser_watcher/window_hang_monitor_win.cc +++ b/components/browser_watcher/window_hang_monitor_win.cc
@@ -151,8 +151,8 @@ // The ping is still outstanding, the window is hung or has vanished. // Orphan the outstanding ping. If the callback arrives late, it will // delete it, or if the callback never arrives it'll leak. - outstanding_ping_->monitor = NULL; - outstanding_ping_ = NULL; + outstanding_ping_->monitor = nullptr; + outstanding_ping_ = nullptr; if (hwnd != FindChromeMessageWindow(window_process_.Pid())) { // The window vanished.
diff --git a/components/browser_watcher/window_hang_monitor_win_unittest.cc b/components/browser_watcher/window_hang_monitor_win_unittest.cc index da0baa81f..0ccf8a7 100644 --- a/components/browser_watcher/window_hang_monitor_win_unittest.cc +++ b/components/browser_watcher/window_hang_monitor_win_unittest.cc
@@ -193,7 +193,7 @@ *success = message_window_->CreateNamed( base::Bind(&MonitoredProcessClient::EmptyMessageCallback, base::Unretained(this)), - existing_dir.value().c_str()); + existing_dir.value()); created->Signal(); } @@ -251,7 +251,7 @@ thread_("Hang monitor thread") {} ~HangMonitorThread() { - if (hang_monitor_.get()) + if (hang_monitor_) DestroyWatcher(); }
diff --git a/components/browsing_data/content/conditional_cache_counting_helper.cc b/components/browsing_data/content/conditional_cache_counting_helper.cc index 3e00187..b9b360b 100644 --- a/components/browsing_data/content/conditional_cache_counting_helper.cc +++ b/components/browsing_data/content/conditional_cache_counting_helper.cc
@@ -82,8 +82,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); next_cache_state_ = CacheState::NONE; DCHECK_EQ(CacheState::NONE, next_cache_state_); - DCHECK(main_context_getter_.get()); - DCHECK(media_context_getter_.get()); + DCHECK(main_context_getter_); + DCHECK(media_context_getter_); next_cache_state_ = CacheState::CREATE_MAIN; DoCountCache(net::OK);
diff --git a/components/browsing_data_strings_grdp/OWNERS b/components/browsing_data_strings_grdp/OWNERS new file mode 100644 index 0000000..93c7250 --- /dev/null +++ b/components/browsing_data_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/browsing_data/OWNERS
diff --git a/components/browsing_data_strings_grdp/README.md b/components/browsing_data_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/browsing_data_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/captive_portal/captive_portal_detector.cc b/components/captive_portal/captive_portal_detector.cc index b9397c0..90a39046 100644 --- a/components/captive_portal/captive_portal_detector.cc +++ b/components/captive_portal/captive_portal_detector.cc
@@ -159,7 +159,7 @@ } bool CaptivePortalDetector::FetchingURL() const { - return simple_loader_.get() != nullptr; + return simple_loader_ != nullptr; } } // namespace captive_portal
diff --git a/components/cast_channel/cast_auth_util_unittest.cc b/components/cast_channel/cast_auth_util_unittest.cc index d1493f2..5a9df90 100644 --- a/components/cast_channel/cast_auth_util_unittest.cc +++ b/components/cast_channel/cast_auth_util_unittest.cc
@@ -174,7 +174,7 @@ scoped_feature_list.InitAndEnableFeature( base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT}); AuthContext context = AuthContext::Create(); - std::string received_nonce = ""; + std::string received_nonce; EXPECT_FALSE(context.nonce().empty()); AuthResult result = context.VerifySenderNonce(received_nonce); EXPECT_FALSE(result.success());
diff --git a/components/cast_channel/cast_socket.cc b/components/cast_channel/cast_socket.cc index 01ff7ed4a1..5ef5fb1 100644 --- a/components/cast_channel/cast_socket.cc +++ b/components/cast_channel/cast_socket.cc
@@ -168,7 +168,7 @@ cert_verifier_ = base::WrapUnique(new FakeCertVerifier); transport_security_state_.reset(new net::TransportSecurityState); cert_transparency_verifier_.reset(new net::MultiLogCTVerifier()); - ct_policy_enforcer_.reset(new net::CTPolicyEnforcer()); + ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer()); // Note that |context| fields remain owned by CastSocketImpl. net::SSLClientSocketContext context; @@ -189,7 +189,7 @@ scoped_refptr<net::X509Certificate> CastSocketImpl::ExtractPeerCert() { net::SSLInfo ssl_info; - if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) + if (!socket_->GetSSLInfo(&ssl_info) || !ssl_info.cert) return nullptr; return ssl_info.cert; @@ -430,7 +430,7 @@ } // SSL connection succeeded. - if (!transport_.get()) { + if (!transport_) { // Create a channel transport if one wasn't already set (e.g. by test // code). transport_.reset(new CastTransportImpl(
diff --git a/components/cast_channel/cast_socket_unittest.cc b/components/cast_channel/cast_socket_unittest.cc index eedc797..75c4635 100644 --- a/components/cast_channel/cast_socket_unittest.cc +++ b/components/cast_channel/cast_socket_unittest.cc
@@ -357,7 +357,7 @@ MockCastSocketTest() {} void TearDown() override { - if (socket_.get()) { + if (socket_) { EXPECT_CALL(handler_, OnCloseComplete(net::OK)); socket_->Close(base::Bind(&CompleteHandler::OnCloseComplete, base::Unretained(&handler_))); @@ -396,7 +396,7 @@ SslCastSocketTest() {} void TearDown() override { - if (socket_.get()) { + if (socket_) { EXPECT_CALL(handler_, OnCloseComplete(net::OK)); socket_->Close(base::Bind(&CompleteHandler::OnCloseComplete, base::Unretained(&handler_)));
diff --git a/components/cast_channel/cast_test_util.cc b/components/cast_channel/cast_test_util.cc index f90d13d..d7f2796 100644 --- a/components/cast_channel/cast_test_util.cc +++ b/components/cast_channel/cast_test_util.cc
@@ -30,8 +30,7 @@ MockCastSocketObserver::~MockCastSocketObserver() {} MockCastSocketService::MockCastSocketService( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) - : CastSocketService() { + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { SetTaskRunnerForTest(task_runner); } MockCastSocketService::~MockCastSocketService() {}
diff --git a/components/certificate_transparency/BUILD.gn b/components/certificate_transparency/BUILD.gn index a2dae9e..1e71b52 100644 --- a/components/certificate_transparency/BUILD.gn +++ b/components/certificate_transparency/BUILD.gn
@@ -4,6 +4,8 @@ static_library("certificate_transparency") { sources = [ + "chrome_ct_policy_enforcer.cc", + "chrome_ct_policy_enforcer.h", "ct_policy_manager.cc", "ct_policy_manager.h", "features.cc", @@ -36,6 +38,7 @@ source_set("unit_tests") { testonly = true sources = [ + "chrome_ct_policy_enforcer_unittest.cc", "ct_policy_manager_unittest.cc", "log_dns_client_unittest.cc", "mock_log_dns_traffic.cc",
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer.cc b/components/certificate_transparency/chrome_ct_policy_enforcer.cc new file mode 100644 index 0000000..d09c1d3 --- /dev/null +++ b/components/certificate_transparency/chrome_ct_policy_enforcer.cc
@@ -0,0 +1,307 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/certificate_transparency/chrome_ct_policy_enforcer.h" + +#include <stdint.h> + +#include <algorithm> +#include <memory> +#include <utility> + +#include "base/bind.h" +#include "base/build_time.h" +#include "base/callback_helpers.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/histogram_macros.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_number_conversions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "base/version.h" +#include "net/cert/ct_known_logs.h" +#include "net/cert/ct_policy_status.h" +#include "net/cert/signed_certificate_timestamp.h" +#include "net/cert/x509_certificate.h" +#include "net/cert/x509_certificate_net_log_param.h" +#include "net/log/net_log_capture_mode.h" +#include "net/log/net_log_event_type.h" +#include "net/log/net_log_parameters_callback.h" +#include "net/log/net_log_with_source.h" + +using net::ct::CTPolicyCompliance; + +namespace certificate_transparency { + +namespace { + +// Returns true if the current build is recent enough to ensure that +// built-in security information (e.g. CT Logs) is fresh enough. +// TODO(eranm): Move to base or net/base +bool IsBuildTimely() { + const base::Time build_time = base::GetBuildTime(); + // We consider built-in information to be timely for 10 weeks. + return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; +} + +// Returns a rounded-down months difference of |start| and |end|, +// together with an indication of whether the last month was +// a full month, because the range starts specified in the policy +// are not consistent in terms of including the range start value. +void RoundedDownMonthDifference(const base::Time& start, + const base::Time& end, + size_t* rounded_months_difference, + bool* has_partial_month) { + DCHECK(rounded_months_difference); + DCHECK(has_partial_month); + base::Time::Exploded exploded_start; + base::Time::Exploded exploded_expiry; + start.UTCExplode(&exploded_start); + end.UTCExplode(&exploded_expiry); + if (end < start) { + *rounded_months_difference = 0; + *has_partial_month = false; + return; + } + + *has_partial_month = true; + uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 + + (exploded_expiry.month - exploded_start.month); + if (exploded_expiry.day_of_month < exploded_start.day_of_month) + --month_diff; + else if (exploded_expiry.day_of_month == exploded_start.day_of_month) + *has_partial_month = false; + + *rounded_months_difference = month_diff; +} + +const char* CTPolicyComplianceToString(CTPolicyCompliance status) { + switch (status) { + case CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS: + return "COMPLIES_VIA_SCTS"; + case CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS: + return "NOT_ENOUGH_SCTS"; + case CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS: + return "NOT_DIVERSE_SCTS"; + case CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY: + return "BUILD_NOT_TIMELY"; + case CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE: + case CTPolicyCompliance::CT_POLICY_MAX: + NOTREACHED(); + return "unknown"; + } + + NOTREACHED(); + return "unknown"; +} + +std::unique_ptr<base::Value> NetLogCertComplianceCheckResultCallback( + net::X509Certificate* cert, + bool build_timely, + CTPolicyCompliance compliance, + net::NetLogCaptureMode capture_mode) { + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + dict->Set("certificate", + net::NetLogX509CertificateCallback(cert, capture_mode)); + dict->SetBoolean("build_timely", build_timely); + dict->SetString("ct_compliance_status", + CTPolicyComplianceToString(compliance)); + return std::move(dict); +} + +// Evaluates against the policy specified at +// https://sites.google.com/a/chromium.org/dev/Home/chromium-security/root-ca-policy/EVCTPlanMay2015edition.pdf?attredirects=0 +CTPolicyCompliance CheckCTPolicyCompliance( + const net::X509Certificate& cert, + const net::ct::SCTList& verified_scts) { + // Cert is outside the bounds of parsable; reject it. + if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || + cert.valid_start().is_max() || cert.valid_expiry().is_max()) { + return CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; + } + + // Scan for the earliest SCT. This is used to determine whether to enforce + // log diversity requirements, as well as whether to enforce whether or not + // a log was qualified or pending qualification at time of issuance (in the + // case of embedded SCTs). It's acceptable to ignore the origin of the SCT, + // because SCTs delivered via OCSP/TLS extension will cover the full + // certificate, which necessarily will exist only after the precertificate + // has been logged and the actual certificate issued. + // Note: Here, issuance date is defined as the earliest of all SCTs, rather + // than the latest of embedded SCTs, in order to give CAs the benefit of + // the doubt in the event a log is revoked in the midst of processing + // a precertificate and issuing the certificate. + base::Time issuance_date = base::Time::Max(); + for (const auto& sct : verified_scts) { + base::Time unused; + if (net::ct::IsLogDisqualified(sct->log_id, &unused)) + continue; + issuance_date = std::min(sct->timestamp, issuance_date); + } + + bool has_valid_google_sct = false; + bool has_valid_nongoogle_sct = false; + bool has_valid_embedded_sct = false; + bool has_valid_nonembedded_sct = false; + bool has_embedded_google_sct = false; + bool has_embedded_nongoogle_sct = false; + std::vector<base::StringPiece> embedded_log_ids; + for (const auto& sct : verified_scts) { + base::Time disqualification_date; + bool is_disqualified = + net::ct::IsLogDisqualified(sct->log_id, &disqualification_date); + if (is_disqualified && + sct->origin != net::ct::SignedCertificateTimestamp::SCT_EMBEDDED) { + // For OCSP and TLS delivered SCTs, only SCTs that are valid at the + // time of check are accepted. + continue; + } + + if (net::ct::IsLogOperatedByGoogle(sct->log_id)) { + has_valid_google_sct |= !is_disqualified; + if (sct->origin == net::ct::SignedCertificateTimestamp::SCT_EMBEDDED) + has_embedded_google_sct = true; + } else { + has_valid_nongoogle_sct |= !is_disqualified; + if (sct->origin == net::ct::SignedCertificateTimestamp::SCT_EMBEDDED) + has_embedded_nongoogle_sct = true; + } + if (sct->origin != net::ct::SignedCertificateTimestamp::SCT_EMBEDDED) { + has_valid_nonembedded_sct = true; + } else { + has_valid_embedded_sct |= !is_disqualified; + // If the log is disqualified, it only counts towards quorum if + // the certificate was issued before the log was disqualified, and the + // SCT was obtained before the log was disqualified. + if (!is_disqualified || (issuance_date < disqualification_date && + sct->timestamp < disqualification_date)) { + embedded_log_ids.push_back(sct->log_id); + } + } + } + + // Option 1: + // An SCT presented via the TLS extension OR embedded within a stapled OCSP + // response is from a log qualified at time of check; + // AND there is at least one SCT from a Google Log that is qualified at + // time of check, presented via any method; + // AND there is at least one SCT from a non-Google Log that is qualified + // at the time of check, presented via any method. + // + // Note: Because SCTs embedded via TLS or OCSP can be updated on the fly, + // the issuance date is irrelevant, as any policy changes can be + // accomodated. + if (has_valid_nonembedded_sct && has_valid_google_sct && + has_valid_nongoogle_sct) { + return CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; + } + // Note: If has_valid_nonembedded_sct was true, but Option 2 isn't met, + // then the result will be that there weren't diverse enough SCTs, as that + // the only other way for the conditional above to fail). Because Option 1 + // has the diversity requirement, it's implicitly a minimum number of SCTs + // (specifically, 2), but that's not explicitly specified in the policy. + + // Option 2: + // There is at least one embedded SCT from a log qualified at the time of + // check ... + if (!has_valid_embedded_sct) { + // Under Option 2, there weren't enough SCTs, and potentially under + // Option 1, there weren't diverse enough SCTs. Try to signal the error + // that is most easily fixed. + return has_valid_nonembedded_sct + ? CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS + : CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; + } + + // ... AND there is at least one embedded SCT from a Google Log once or + // currently qualified; + // AND there is at least one embedded SCT from a non-Google Log once or + // currently qualified; + // ... + // + // Note: This policy language is only enforced after the below issuance + // date, as that's when the diversity policy first came into effect for + // SCTs embedded in certificates. + // The date when diverse SCTs requirement is effective from. + // 2015-07-01 00:00:00 UTC. + const base::Time kDiverseSCTRequirementStartDate = + base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1435708800); + if (issuance_date >= kDiverseSCTRequirementStartDate && + !(has_embedded_google_sct && has_embedded_nongoogle_sct)) { + // Note: This also covers the case for non-embedded SCTs, as it's only + // possible to reach here if both sets are not diverse enough. + return CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; + } + + size_t lifetime_in_months = 0; + bool has_partial_month = false; + RoundedDownMonthDifference(cert.valid_start(), cert.valid_expiry(), + &lifetime_in_months, &has_partial_month); + + // ... AND the certificate embeds SCTs from AT LEAST the number of logs + // once or currently qualified shown in Table 1 of the CT Policy. + size_t num_required_embedded_scts = 5; + if (lifetime_in_months > 39 || + (lifetime_in_months == 39 && has_partial_month)) { + num_required_embedded_scts = 5; + } else if (lifetime_in_months > 27 || + (lifetime_in_months == 27 && has_partial_month)) { + num_required_embedded_scts = 4; + } else if (lifetime_in_months >= 15) { + num_required_embedded_scts = 3; + } else { + num_required_embedded_scts = 2; + } + + // Sort the embedded log IDs and remove duplicates, so that only a single + // SCT from each log is accepted. This is to handle the case where a given + // log returns different SCTs for the same precertificate (which is + // permitted, but advised against). + std::sort(embedded_log_ids.begin(), embedded_log_ids.end()); + auto sorted_end = + std::unique(embedded_log_ids.begin(), embedded_log_ids.end()); + size_t num_embedded_scts = + std::distance(embedded_log_ids.begin(), sorted_end); + + if (num_embedded_scts >= num_required_embedded_scts) + return CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; + + // Under Option 2, there weren't enough SCTs, and potentially under Option + // 1, there weren't diverse enough SCTs. Try to signal the error that is + // most easily fixed. + return has_valid_nonembedded_sct + ? CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS + : CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; +} + +} // namespace + +CTPolicyCompliance ChromeCTPolicyEnforcer::CheckCompliance( + net::X509Certificate* cert, + const net::ct::SCTList& verified_scts, + const net::NetLogWithSource& net_log) { + // If the build is not timely, no certificate is considered compliant + // with CT policy. The reasoning is that, for example, a log might + // have been pulled and is no longer considered valid; thus, a client + // needs up-to-date information about logs to consider certificates to + // be compliant with policy. + bool build_timely = IsBuildTimely(); + CTPolicyCompliance compliance; + if (!build_timely) { + compliance = CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY; + } else { + compliance = CheckCTPolicyCompliance(*cert, verified_scts); + } + + net::NetLogParametersCallback net_log_callback = + base::BindRepeating(&NetLogCertComplianceCheckResultCallback, + base::Unretained(cert), build_timely, compliance); + + net_log.AddEvent(net::NetLogEventType::CERT_CT_COMPLIANCE_CHECKED, + net_log_callback); + + return compliance; +} + +} // namespace certificate_transparency
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer.h b/components/certificate_transparency/chrome_ct_policy_enforcer.h new file mode 100644 index 0000000..f61ff0d --- /dev/null +++ b/components/certificate_transparency/chrome_ct_policy_enforcer.h
@@ -0,0 +1,33 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_CHROME_CT_POLICY_ENFORCER_H_ +#define COMPONENTS_CERTIFICATE_TRANSPARENCY_CHROME_CT_POLICY_ENFORCER_H_ + +#include "net/cert/ct_policy_enforcer.h" + +namespace certificate_transparency { + +// A CTPolicyEnforcer that enforces the "Certificate Transparency in Chrome" +// policies detailed at +// https://github.com/chromium/ct-policy/blob/master/ct_policy.md +// +// This should only be used when there is a reliable, rapid update mechanism +// for the set of known, qualified logs - either through a reliable binary +// updating mechanism or through out-of-band delivery. See +// //net/docs/certificate-transparency.md for more details. +class ChromeCTPolicyEnforcer : public net::CTPolicyEnforcer { + public: + ChromeCTPolicyEnforcer() = default; + ~ChromeCTPolicyEnforcer() override = default; + + net::ct::CTPolicyCompliance CheckCompliance( + net::X509Certificate* cert, + const net::ct::SCTList& verified_scts, + const net::NetLogWithSource& net_log) override; +}; + +} // namespace certificate_transparency + +#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_CHROME_CT_POLICY_ENFORCER_H_
diff --git a/net/cert/ct_policy_enforcer_unittest.cc b/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc similarity index 64% rename from net/cert/ct_policy_enforcer_unittest.cc rename to components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc index 906cfc9cb..8a5d48ea 100644 --- a/net/cert/ct_policy_enforcer_unittest.cc +++ b/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc
@@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/cert/ct_policy_enforcer.h" +#include "components/certificate_transparency/chrome_ct_policy_enforcer.h" #include <memory> #include <string> +#include "base/stl_util.h" #include "base/time/time.h" #include "base/version.h" #include "crypto/rsa_private_key.h" @@ -22,22 +23,28 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -namespace net { +using net::ct::CTPolicyCompliance; +using net::ct::SCTList; +using net::ct::SignedCertificateTimestamp; +using net::NetLogWithSource; +using net::X509Certificate; + +namespace certificate_transparency { namespace { const char kGoogleAviatorLogID[] = "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc\x71\x51" "\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\xfb\xc4"; -static_assert(arraysize(kGoogleAviatorLogID) - 1 == crypto::kSHA256Length, +static_assert(base::size(kGoogleAviatorLogID) - 1 == crypto::kSHA256Length, "Incorrect log ID length."); -class CTPolicyEnforcerTest : public ::testing::Test { +class ChromeCTPolicyEnforcerTest : public ::testing::Test { public: void SetUp() override { - policy_enforcer_.reset(new CTPolicyEnforcer); + policy_enforcer_.reset(new ChromeCTPolicyEnforcer); - std::string der_test_cert(ct::GetDerEncodedX509Cert()); + std::string der_test_cert(net::ct::GetDerEncodedX509Cert()); chain_ = X509Certificate::CreateFromBytes(der_test_cert.data(), der_test_cert.size()); ASSERT_TRUE(chain_.get()); @@ -46,14 +53,14 @@ } void FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::Origin desired_origin, + SignedCertificateTimestamp::Origin desired_origin, size_t num_scts, const std::vector<std::string>& desired_log_keys, bool timestamp_past_enforcement_date, - ct::SCTList* verified_scts) { + SCTList* verified_scts) { for (size_t i = 0; i < num_scts; ++i) { - scoped_refptr<ct::SignedCertificateTimestamp> sct( - new ct::SignedCertificateTimestamp()); + scoped_refptr<SignedCertificateTimestamp> sct( + new SignedCertificateTimestamp()); sct->origin = desired_origin; if (i < desired_log_keys.size()) sct->log_id = desired_log_keys[i]; @@ -72,18 +79,17 @@ } } - void AddDisqualifiedLogSCT( - ct::SignedCertificateTimestamp::Origin desired_origin, - bool timestamp_after_disqualification_date, - ct::SCTList* verified_scts) { + void AddDisqualifiedLogSCT(SignedCertificateTimestamp::Origin desired_origin, + bool timestamp_after_disqualification_date, + SCTList* verified_scts) { static const char kCertlyLogID[] = "\xcd\xb5\x17\x9b\x7f\xc1\xc0\x46\xfe\xea\x31\x13\x6a\x3f\x8f\x00\x2e" "\x61\x82\xfa\xf8\x89\x6f\xec\xc8\xb2\xf5\xb5\xab\x60\x49\x00"; - static_assert(arraysize(kCertlyLogID) - 1 == crypto::kSHA256Length, + static_assert(base::size(kCertlyLogID) - 1 == crypto::kSHA256Length, "Incorrect log ID length."); - scoped_refptr<ct::SignedCertificateTimestamp> sct( - new ct::SignedCertificateTimestamp()); + scoped_refptr<SignedCertificateTimestamp> sct( + new SignedCertificateTimestamp()); sct->origin = desired_origin; sct->log_id = std::string(kCertlyLogID, crypto::kSHA256Length); if (timestamp_after_disqualification_date) { @@ -98,9 +104,9 @@ } void FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::Origin desired_origin, + SignedCertificateTimestamp::Origin desired_origin, size_t num_scts, - ct::SCTList* verified_scts) { + SCTList* verified_scts) { std::vector<std::string> desired_log_ids; desired_log_ids.push_back(google_log_id_); FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true, @@ -116,261 +122,243 @@ } protected: - std::unique_ptr<CTPolicyEnforcer> policy_enforcer_; + std::unique_ptr<net::CTPolicyEnforcer> policy_enforcer_; scoped_refptr<X509Certificate> chain_; std::string google_log_id_; std::string non_google_log_id_; }; -#if defined(OS_ANDROID) -#define MAYBE_DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle \ - DISABLED_DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle -#else -#define MAYBE_DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle \ - DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle -#endif -TEST_F(CTPolicyEnforcerTest, - MAYBE_DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle) { - ct::SCTList scts; +TEST_F(ChromeCTPolicyEnforcerTest, + DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle) { + SCTList scts; std::vector<std::string> desired_log_ids(2, google_log_id_); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - desired_log_ids.size(), desired_log_ids, true, &scts); - - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - policy_enforcer_->CheckCompliance(chain_.get(), scts, - NetLogWithSource())); -} - -TEST_F(CTPolicyEnforcerTest, - DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllNonGoogle) { - ct::SCTList scts; - std::vector<std::string> desired_log_ids(2, non_google_log_id_); - - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - desired_log_ids.size(), desired_log_ids, true, &scts); - - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - policy_enforcer_->CheckCompliance(chain_.get(), scts, - NetLogWithSource())); -} - -TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyIfSCTBeforeEnforcementDate) { - ct::SCTList scts; - // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - // All 5 SCTs will be from non-Google logs. - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5, - std::vector<std::string>(), false, &scts); - - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - policy_enforcer_->CheckCompliance(chain_.get(), scts, - NetLogWithSource())); -} - -TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithNonEmbeddedSCTs) { - ct::SCTList scts; - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, &scts); - - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - policy_enforcer_->CheckCompliance(chain_.get(), scts, - NetLogWithSource())); -} - -TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithEmbeddedSCTs) { - // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - ct::SCTList scts; - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + desired_log_ids.size(), desired_log_ids, true, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithPooledNonEmbeddedSCTs) { - ct::SCTList scts; +TEST_F(ChromeCTPolicyEnforcerTest, + DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllNonGoogle) { + SCTList scts; + std::vector<std::string> desired_log_ids(2, non_google_log_id_); + + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + desired_log_ids.size(), desired_log_ids, true, + &scts); + + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, + policy_enforcer_->CheckCompliance(chain_.get(), scts, + NetLogWithSource())); +} + +TEST_F(ChromeCTPolicyEnforcerTest, + ConformsToCTPolicyIfSCTBeforeEnforcementDate) { + SCTList scts; + // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. + // All 5 SCTs will be from non-Google logs. + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, + std::vector<std::string>(), false, &scts); + + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + policy_enforcer_->CheckCompliance(chain_.get(), scts, + NetLogWithSource())); +} + +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToCTPolicyWithNonEmbeddedSCTs) { + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + 2, &scts); + + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + policy_enforcer_->CheckCompliance(chain_.get(), scts, + NetLogWithSource())); +} + +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToCTPolicyWithEmbeddedSCTs) { + // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5, &scts); + + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + policy_enforcer_->CheckCompliance(chain_.get(), scts, + NetLogWithSource())); +} + +TEST_F(ChromeCTPolicyEnforcerTest, + ConformsToCTPolicyWithPooledNonEmbeddedSCTs) { + SCTList scts; std::vector<std::string> desired_logs; // One Google log, delivered via OCSP. desired_logs.clear(); desired_logs.push_back(google_log_id_); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, - desired_logs.size(), desired_logs, true, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, + desired_logs.size(), desired_logs, true, &scts); // One non-Google log, delivered via TLS. desired_logs.clear(); desired_logs.push_back(non_google_log_id_); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, - desired_logs.size(), desired_logs, true, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + desired_logs.size(), desired_logs, true, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithPooledEmbeddedSCTs) { - ct::SCTList scts; +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToCTPolicyWithPooledEmbeddedSCTs) { + SCTList scts; std::vector<std::string> desired_logs; // One Google log, delivered embedded. desired_logs.clear(); desired_logs.push_back(google_log_id_); - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, desired_logs.size(), desired_logs, true, &scts); // One non-Google log, delivered via OCSP. desired_logs.clear(); desired_logs.push_back(non_google_log_id_); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, - desired_logs.size(), desired_logs, true, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, + desired_logs.size(), desired_logs, true, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughSCTs) { +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughSCTs) { // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - ct::SCTList scts; - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 2, - &scts); + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 2, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) { - ct::SCTList scts; +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) { + SCTList scts; // The results should be the same before and after disqualification, // regardless of the delivery method. // SCT from before disqualification. scts.clear(); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 1, &scts); - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + 1, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, false, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); // SCT from after disqualification. scts.clear(); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 1, &scts); - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + 1, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, true, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); // Embedded SCT from before disqualification. scts.clear(); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 1, &scts); - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_EMBEDDED, false, - &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + 1, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, &scts); + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); // Embedded SCT from after disqualification. scts.clear(); - FillListWithSCTsOfOrigin( - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 1, &scts); - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_EMBEDDED, true, - &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + 1, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, &scts); + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, +TEST_F(ChromeCTPolicyEnforcerTest, ConformsWithDisqualifiedLogBeforeDisqualificationDate) { - ct::SCTList scts; - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 4, - &scts); - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_EMBEDDED, false, - &scts); + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 4, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, &scts); // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformWithDisqualifiedLogAfterDisqualificationDate) { - ct::SCTList scts; - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 4, - &scts); - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_EMBEDDED, true, - &scts); + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 4, &scts); + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, &scts); // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformWithIssuanceDateAfterDisqualificationDate) { - ct::SCTList scts; - AddDisqualifiedLogSCT(ct::SignedCertificateTimestamp::SCT_EMBEDDED, true, - &scts); - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 4, - &scts); + SCTList scts; + AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, &scts); + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 4, &scts); // Make sure all SCTs are after the disqualification date. for (size_t i = 1; i < scts.size(); ++i) scts[i]->timestamp = scts[0]->timestamp; // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, +TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughUniqueEmbeddedLogs) { - ct::SCTList scts; + SCTList scts; std::vector<std::string> desired_logs; // One Google Log. desired_logs.clear(); desired_logs.push_back(google_log_id_); - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, desired_logs.size(), desired_logs, true, &scts); // Two distinct non-Google logs. desired_logs.clear(); desired_logs.push_back(std::string(crypto::kSHA256Length, 'A')); desired_logs.push_back(std::string(crypto::kSHA256Length, 'B')); - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, desired_logs.size(), desired_logs, true, &scts); // Two unique SCTs from the same non-Google log. desired_logs.clear(); desired_logs.push_back(std::string(crypto::kSHA256Length, 'C')); desired_logs.push_back(std::string(crypto::kSHA256Length, 'C')); - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, desired_logs.size(), desired_logs, true, &scts); // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. // However, there are only 4 SCTs are from distinct logs. - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, policy_enforcer_->CheckCompliance(chain_.get(), scts, NetLogWithSource())); } -TEST_F(CTPolicyEnforcerTest, +TEST_F(ChromeCTPolicyEnforcerTest, ConformsToPolicyExactNumberOfSCTsForValidityPeriod) { std::unique_ptr<crypto::RSAPrivateKey> private_key( crypto::RSAPrivateKey::Create(1024)); @@ -422,7 +410,7 @@ {// Cert valid for over 39 months, needs 5 SCTs. time_2015_3_0_25_11_25_0_0, time_2018_6_0_27_11_25_0_0, 5}}; - for (size_t i = 0; i < arraysize(kTestData); ++i) { + for (size_t i = 0; i < base::size(kTestData); ++i) { SCOPED_TRACE(i); const base::Time& start = kTestData[i].validity_start; const base::Time& end = kTestData[i].validity_end; @@ -430,29 +418,29 @@ // Create a self-signed certificate with exactly the validity period. std::string cert_data; - ASSERT_TRUE(x509_util::CreateSelfSignedCert( - private_key->key(), x509_util::DIGEST_SHA256, "CN=test", + ASSERT_TRUE(net::x509_util::CreateSelfSignedCert( + private_key->key(), net::x509_util::DIGEST_SHA256, "CN=test", i * 10 + required_scts, start, end, &cert_data)); scoped_refptr<X509Certificate> cert( X509Certificate::CreateFromBytes(cert_data.data(), cert_data.size())); ASSERT_TRUE(cert); for (size_t i = 0; i < required_scts - 1; ++i) { - ct::SCTList scts; - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, i, + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, i, std::vector<std::string>(), false, &scts); - EXPECT_EQ(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, policy_enforcer_->CheckCompliance(cert.get(), scts, NetLogWithSource())) << " for: " << (end - start).InDays() << " and " << required_scts << " scts=" << scts.size() << " i=" << i; } - ct::SCTList scts; - FillListWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, required_scts, std::vector<std::string>(), false, &scts); EXPECT_EQ( - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, policy_enforcer_->CheckCompliance(cert.get(), scts, NetLogWithSource())) << " for: " << (end - start).InDays() << " and " << required_scts << " scts=" << scts.size(); @@ -461,4 +449,4 @@ } // namespace -} // namespace net +} // namespace certificate_transparency
diff --git a/components/client_update_protocol/ecdsa_unittest.cc b/components/client_update_protocol/ecdsa_unittest.cc index 8c1e933..71c7441 100644 --- a/components/client_update_protocol/ecdsa_unittest.cc +++ b/components/client_update_protocol/ecdsa_unittest.cc
@@ -46,7 +46,7 @@ ASSERT_TRUE(cup_.get()); } - Ecdsa& CUP() { return *cup_.get(); } + Ecdsa& CUP() { return *cup_; } private: std::unique_ptr<Ecdsa> cup_;
diff --git a/components/component_updater/component_installer.cc b/components/component_updater/component_installer.cc index d428b217..285f2739 100644 --- a/components/component_updater/component_installer.cc +++ b/components/component_updater/component_installer.cc
@@ -250,7 +250,7 @@ void ComponentInstaller::StartRegistration( scoped_refptr<RegistrationInfo> registration_info) { VLOG(1) << __func__ << " for " << installer_policy_->GetName(); - DCHECK(task_runner_.get()); + DCHECK(task_runner_); DCHECK(task_runner_->RunsTasksInCurrentSequence()); base::Version latest_version(kNullVersion); @@ -353,7 +353,7 @@ } void ComponentInstaller::UninstallOnTaskRunner() { - DCHECK(task_runner_.get()); + DCHECK(task_runner_); DCHECK(task_runner_->RunsTasksInCurrentSequence()); // Only try to delete any files that are in our user-level install path.
diff --git a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc index 8bb2f986..a8758321 100644 --- a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc +++ b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc
@@ -41,7 +41,7 @@ DCHECK(current_rule_->second.value.get()); Rule to_return(current_rule_->first.primary_pattern, current_rule_->first.secondary_pattern, - current_rule_->second.value.get()->DeepCopy()); + current_rule_->second.value->DeepCopy()); ++current_rule_; return to_return; } @@ -83,7 +83,7 @@ std::tie(other.primary_pattern, other.secondary_pattern); } -OriginIdentifierValueMap::ValueEntry::ValueEntry() : last_modified(), value(){}; +OriginIdentifierValueMap::ValueEntry::ValueEntry(){}; OriginIdentifierValueMap::ValueEntry::~ValueEntry(){};
diff --git a/components/content_settings/core/browser/content_settings_pref.cc b/components/content_settings/core/browser/content_settings_pref.cc index 7f91a3c..4565d0f 100644 --- a/components/content_settings/core/browser/content_settings_pref.cc +++ b/components/content_settings/core/browser/content_settings_pref.cc
@@ -130,7 +130,7 @@ { base::AutoLock auto_lock(lock_); - if (value.get()) { + if (value) { map_to_modify->SetValue(primary_pattern, secondary_pattern, content_type_, resource_identifier, modified_time, value->DeepCopy());
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc index 1c23860..a1252ad4 100644 --- a/components/content_settings/core/browser/cookie_settings.cc +++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -189,7 +189,7 @@ net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES); // We should always have a value, at least from the default provider. - DCHECK(value.get()); + DCHECK(value); ContentSetting setting = ValueToContentSetting(value.get()); bool block = block_third && policy.CanAccessCookies(url, first_party_url) != net::OK;
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc index c14f0919..d45b95a 100644 --- a/components/content_settings/core/browser/host_content_settings_map.cc +++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -850,7 +850,7 @@ *primary_pattern = rule.primary_pattern; if (secondary_pattern) *secondary_pattern = rule.secondary_pattern; - return base::WrapUnique(rule.value.get()->DeepCopy()); + return base::WrapUnique(rule.value->DeepCopy()); } } }
diff --git a/components/contextual_search/browser/ctr_aggregator_unittest.cc b/components/contextual_search/browser/ctr_aggregator_unittest.cc index 9e3d791..1fc9e49e 100644 --- a/components/contextual_search/browser/ctr_aggregator_unittest.cc +++ b/components/contextual_search/browser/ctr_aggregator_unittest.cc
@@ -48,7 +48,7 @@ void SetUp() override { storage_.reset(new WeeklyActivityStorageStub()); - aggregator_.reset(new CtrAggregator(*storage_.get(), kTestWeek)); + aggregator_.reset(new CtrAggregator(*storage_, kTestWeek)); } void TearDown() override {}
diff --git a/components/crash/content/app/breakpad_win.cc b/components/crash/content/app/breakpad_win.cc index 06e38f9..382b79e 100644 --- a/components/crash/content/app/breakpad_win.cc +++ b/components/crash/content/app/breakpad_win.cc
@@ -91,8 +91,8 @@ // This is the well known SID for the system principal. const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; -google_breakpad::ExceptionHandler* g_breakpad = NULL; -google_breakpad::ExceptionHandler* g_dumphandler_no_crash = NULL; +google_breakpad::ExceptionHandler* g_breakpad = nullptr; +google_breakpad::ExceptionHandler* g_dumphandler_no_crash = nullptr; #if !defined(_WIN64) EXCEPTION_POINTERS g_surrogate_exception_pointers = {0}; @@ -102,7 +102,7 @@ typedef NTSTATUS (WINAPI* NtTerminateProcessPtr)(HANDLE ProcessHandle, NTSTATUS ExitStatus); -char* g_real_terminate_process_stub = NULL; +char* g_real_terminate_process_stub = nullptr; } // namespace @@ -133,8 +133,8 @@ HANDLE process) { // |serialized_crash_keys| is not propagated in breakpad but is in crashpad // since breakpad is deprecated. - return CreateRemoteThread(process, NULL, 0, DumpProcessWithoutCrashThread, - 0, 0, NULL); + return CreateRemoteThread(process, nullptr, 0, DumpProcessWithoutCrashThread, + nullptr, 0, nullptr); } // Returns a string containing a list of all modifiers for the loaded profile. @@ -198,8 +198,9 @@ // Now we just start chrome browser with the same command line. STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi; - if (::CreateProcessW(NULL, ::GetCommandLineW(), NULL, NULL, FALSE, - CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi)) { + if (::CreateProcessW(nullptr, ::GetCommandLineW(), nullptr, nullptr, FALSE, + CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr, &si, + &pi)) { ::CloseHandle(pi.hProcess); ::CloseHandle(pi.hThread); } @@ -234,12 +235,12 @@ // Previous unhandled filter. Will be called if not null when we // intercept a crash. -LPTOP_LEVEL_EXCEPTION_FILTER previous_filter = NULL; +LPTOP_LEVEL_EXCEPTION_FILTER previous_filter = nullptr; // Exception filter used when breakpad is not enabled. We just display // the "Do you want to restart" message and then we call the previous filter. long WINAPI ChromeExceptionFilter(EXCEPTION_POINTERS* info) { - DumpDoneCallback(NULL, NULL, NULL, info, NULL, false); + DumpDoneCallback(nullptr, nullptr, nullptr, info, nullptr, false); if (previous_filter) return previous_filter(info); @@ -251,7 +252,7 @@ // not enabled. We just display the "Do you want to restart" message and then // die (without calling the previous filter). long WINAPI CloudPrintServiceExceptionFilter(EXCEPTION_POINTERS* info) { - DumpDoneCallback(NULL, NULL, NULL, info, NULL, false); + DumpDoneCallback(nullptr, nullptr, nullptr, info, nullptr, false); return EXCEPTION_EXECUTE_HANDLER; } @@ -289,7 +290,7 @@ // machines with CursorXP, PeaDict or with FontExplorer installed it crashes // uncontrollably here. Being this a best effort deal we better go away. __try { - *exit_now = (IDOK != ::MessageBoxW(NULL, text, caption, flags)); + *exit_now = (IDOK != ::MessageBoxW(nullptr, text, caption, flags)); } __except(EXCEPTION_EXECUTE_HANDLER) { // Its not safe to continue executing, exit silently here. ::TerminateProcess(::GetCurrentProcess(), @@ -324,7 +325,7 @@ // Patched stub exists based on conditions (See InitCrashReporter). // As a side note this function also gets called from // WindowProcExceptionFilter. - if (g_real_terminate_process_stub == NULL) { + if (g_real_terminate_process_stub == nullptr) { ::TerminateProcess(::GetCurrentProcess(), content::RESULT_CODE_KILLED); } else { NtTerminateProcessPtr real_terminate_proc = @@ -488,7 +489,7 @@ wchar_t exe_path[MAX_PATH]; exe_path[0] = 0; - GetModuleFileNameW(NULL, exe_path, MAX_PATH); + GetModuleFileNameW(nullptr, exe_path, MAX_PATH); // This is intentionally leaked. CrashKeysWin* keeper = new CrashKeysWin(); @@ -498,8 +499,8 @@ base::CommandLine::ForCurrentProcess(), GetCrashReporterClient()); - google_breakpad::ExceptionHandler::MinidumpCallback callback = NULL; - LPTOP_LEVEL_EXCEPTION_FILTER default_filter = NULL; + google_breakpad::ExceptionHandler::MinidumpCallback callback = nullptr; + LPTOP_LEVEL_EXCEPTION_FILTER default_filter = nullptr; // We install the post-dump callback only for the browser and service // processes. It spawns a new browser/service process. if (process_type == L"browser") { @@ -546,21 +547,20 @@ else if (GetCrashReporterClient()->GetShouldDumpLargerDumps()) dump_type = kLargerDumpType; - g_breakpad = new google_breakpad::ExceptionHandler(temp_dir, &FilterCallback, - callback, NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL, - dump_type, pipe_name.c_str(), custom_info); + g_breakpad = new google_breakpad::ExceptionHandler( + temp_dir, &FilterCallback, callback, nullptr, + google_breakpad::ExceptionHandler::HANDLER_ALL, dump_type, + pipe_name.c_str(), custom_info); // Now initialize the non crash dump handler. - g_dumphandler_no_crash = new google_breakpad::ExceptionHandler(temp_dir, - &FilterCallbackWhenNoCrash, - &DumpDoneCallbackWhenNoCrash, - NULL, + g_dumphandler_no_crash = new google_breakpad::ExceptionHandler( + temp_dir, &FilterCallbackWhenNoCrash, &DumpDoneCallbackWhenNoCrash, + nullptr, // Set the handler to none so this handler would not be added to // |handler_stack_| in |ExceptionHandler| which is a list of exception // handlers. - google_breakpad::ExceptionHandler::HANDLER_NONE, - dump_type, pipe_name.c_str(), custom_info); + google_breakpad::ExceptionHandler::HANDLER_NONE, dump_type, + pipe_name.c_str(), custom_info); // Set the DumpWithoutCrashingFunction for this instance of base.lib. Other // executable images linked with base should set this again for
diff --git a/components/crash/content/app/crash_keys_win.cc b/components/crash/content/app/crash_keys_win.cc index 7df7135..bcf8f10 100644 --- a/components/crash/content/app/crash_keys_win.cc +++ b/components/crash/content/app/crash_keys_win.cc
@@ -36,7 +36,7 @@ CrashKeysWin::~CrashKeysWin() { DCHECK_EQ(this, keeper_); - keeper_ = NULL; + keeper_ = nullptr; } // Appends the plugin path to |g_custom_entries|. @@ -167,7 +167,7 @@ base::AutoLock lock(lock_); DynamicEntriesMap::iterator it = dynamic_entries_.find(safe_key); - google_breakpad::CustomInfoEntry* entry = NULL; + google_breakpad::CustomInfoEntry* entry = nullptr; if (it == dynamic_entries_.end()) { if (dynamic_entries_.size() >= kMaxDynamicEntries) return; @@ -188,7 +188,7 @@ if (it == dynamic_entries_.end()) return; - it->second->set_value(NULL); + it->second->set_value(nullptr); } } // namespace breakpad
diff --git a/components/crash/content/app/crash_keys_win_unittest.cc b/components/crash/content/app/crash_keys_win_unittest.cc index f7c387f..c9ad5c9 100644 --- a/components/crash/content/app/crash_keys_win_unittest.cc +++ b/components/crash/content/app/crash_keys_win_unittest.cc
@@ -123,8 +123,8 @@ &cmd_line, &crash_client_); - ASSERT_TRUE(info != NULL); - ASSERT_TRUE(info->entries != NULL); + ASSERT_TRUE(info != nullptr); + ASSERT_TRUE(info->entries != nullptr); // We expect 7 fixed keys and a "freeboard" of 256 keys for dynamic entries. EXPECT_EQ(256U + 7U, info->count);
diff --git a/components/crash/content/app/hard_error_handler_win.cc b/components/crash/content/app/hard_error_handler_win.cc index 11eca1c..dec998f 100644 --- a/components/crash/content/app/hard_error_handler_win.cc +++ b/components/crash/content/app/hard_error_handler_win.cc
@@ -41,16 +41,12 @@ return; HMODULE ntdll = ::GetModuleHandleA("NTDLL.DLL"); - wchar_t* msg_template = NULL; + wchar_t* msg_template = nullptr; size_t count = ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_HMODULE, - ntdll, - nt_status, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast<wchar_t*>(&msg_template), - 0, - NULL); + FORMAT_MESSAGE_FROM_HMODULE, + ntdll, nt_status, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast<wchar_t*>(&msg_template), 0, nullptr); if (!count) return; @@ -61,8 +57,7 @@ // The MB_SERVICE_NOTIFICATION causes this message to be displayed by // csrss. This means that we are not creating windows or pumping WM messages // in this process. - ::MessageBox(NULL, message.c_str(), - L"chrome.exe", + ::MessageBox(nullptr, message.c_str(), L"chrome.exe", MB_OK | MB_SERVICE_NOTIFICATION); ::LocalFree(msg_template); }
diff --git a/components/crash_strings_grdp/OWNERS b/components/crash_strings_grdp/OWNERS new file mode 100644 index 0000000..21fa106 --- /dev/null +++ b/components/crash_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/crash/OWNERS
diff --git a/components/crash_strings_grdp/README.md b/components/crash_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/crash_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/cronet/ios/cronet_metrics.h b/components/cronet/ios/cronet_metrics.h index f21b5bf..f8a25dd 100644 --- a/components/cronet/ios/cronet_metrics.h +++ b/components/cronet/ios/cronet_metrics.h
@@ -97,13 +97,8 @@ // nullptr. static std::unique_ptr<Metrics> MetricsForTask(NSURLSessionTask* task); - // Used by tests to query the size of the |task_metrics_map_| map. + // Used by tests to query the size of the |gTaskMetricsMap| map. static size_t GetMetricsMapSize(); - - private: - static NSObject* task_metrics_map_lock_; - static std::map<NSURLSessionTask*, std::unique_ptr<Metrics>> - task_metrics_map_; }; // This is the swizzling function that Cronet (in its startInternal
diff --git a/components/cronet/ios/cronet_metrics.mm b/components/cronet/ios/cronet_metrics.mm index e121237..cce453ad 100644 --- a/components/cronet/ios/cronet_metrics.mm +++ b/components/cronet/ios/cronet_metrics.mm
@@ -6,6 +6,7 @@ #include <objc/runtime.h> +#include "base/lazy_instance.h" #include "base/strings/sys_string_conversions.h" @implementation CronetTransactionMetrics @@ -92,6 +93,17 @@ using Metrics = net::MetricsDelegate::Metrics; +// Synchronizes access to |gTaskMetricsMap|. +base::LazyInstance<base::Lock>::Leaky gTaskMetricsMapLock = + LAZY_INSTANCE_INITIALIZER; + +// A global map that contains metrics information for pending URLSessionTasks. +// The map has to be "leaky"; otherwise, it will be destroyed on the main thread +// when the client app terminates. When the client app terminates, the network +// thread may still be finishing some work that requires access to the map. +base::LazyInstance<std::map<NSURLSessionTask*, std::unique_ptr<Metrics>>>::Leaky + gTaskMetricsMap = LAZY_INSTANCE_INITIALIZER; + // Helper method that converts the ticks data found in LoadTimingInfo to an // NSDate value to be used in client-side data. NSDate* TicksToDate(const net::LoadTimingInfo& reference, @@ -272,7 +284,7 @@ // Regardless whether the underlying session delegate handles // URLSession:task:didFinishCollectingMetrics: or not, always // return 'YES' for that selector. Otherwise, the method may - // not be called, causing unbounded growth of |task_metrics_map_|. + // not be called, causing unbounded growth of |gTaskMetricsMap|. if (aSelector == @selector(URLSession:task:didFinishCollectingMetrics:)) { return YES; } @@ -301,52 +313,42 @@ namespace cronet { -// static -NSObject* CronetMetricsDelegate::task_metrics_map_lock_ = - [[NSObject alloc] init]; -std::map<NSURLSessionTask*, std::unique_ptr<Metrics>> - CronetMetricsDelegate::task_metrics_map_; - std::unique_ptr<Metrics> CronetMetricsDelegate::MetricsForTask( NSURLSessionTask* task) { - @synchronized(task_metrics_map_lock_) { - auto metrics_search = task_metrics_map_.find(task); - if (metrics_search == task_metrics_map_.end()) { - return nullptr; - } - - std::unique_ptr<Metrics> metrics = std::move(metrics_search->second); - // Remove the entry to free memory. - task_metrics_map_.erase(metrics_search); - - return metrics; + base::AutoLock auto_lock(gTaskMetricsMapLock.Get()); + auto metrics_search = gTaskMetricsMap.Get().find(task); + if (metrics_search == gTaskMetricsMap.Get().end()) { + return nullptr; } + + std::unique_ptr<Metrics> metrics = std::move(metrics_search->second); + // Remove the entry to free memory. + gTaskMetricsMap.Get().erase(metrics_search); + + return metrics; } void CronetMetricsDelegate::OnStartNetRequest(NSURLSessionTask* task) { if (@available(iOS 10, *)) { - @synchronized(task_metrics_map_lock_) { - if ([task state] == NSURLSessionTaskStateRunning) { - task_metrics_map_[task] = nullptr; - } + base::AutoLock auto_lock(gTaskMetricsMapLock.Get()); + if ([task state] == NSURLSessionTaskStateRunning) { + gTaskMetricsMap.Get()[task] = nullptr; } } } void CronetMetricsDelegate::OnStopNetRequest(std::unique_ptr<Metrics> metrics) { if (@available(iOS 10, *)) { - @synchronized(task_metrics_map_lock_) { - auto metrics_search = task_metrics_map_.find(metrics->task); - if (metrics_search != task_metrics_map_.end()) - metrics_search->second = std::move(metrics); - } + base::AutoLock auto_lock(gTaskMetricsMapLock.Get()); + auto metrics_search = gTaskMetricsMap.Get().find(metrics->task); + if (metrics_search != gTaskMetricsMap.Get().end()) + metrics_search->second = std::move(metrics); } } size_t CronetMetricsDelegate::GetMetricsMapSize() { - @synchronized(task_metrics_map_lock_) { - return task_metrics_map_.size(); - } + base::AutoLock auto_lock(gTaskMetricsMapLock.Get()); + return gTaskMetricsMap.Get().size(); } #pragma mark - Swizzle
diff --git a/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc b/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc index 08bf09e..45b7f9a0 100644 --- a/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc +++ b/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc
@@ -66,7 +66,7 @@ CHECK(test); test->GetData_called_ = true; - return static_cast<Cronet_RawDataPtr>(0); + return static_cast<Cronet_RawDataPtr>(nullptr); } } // namespace @@ -276,7 +276,7 @@ CHECK(test); test->GetVersionString_called_ = true; - return static_cast<Cronet_String>(0); + return static_cast<Cronet_String>(nullptr); } Cronet_String TestCronet_Engine_GetDefaultUserAgent(Cronet_EnginePtr self) { CHECK(self); @@ -285,7 +285,7 @@ CHECK(test); test->GetDefaultUserAgent_called_ = true; - return static_cast<Cronet_String>(0); + return static_cast<Cronet_String>(nullptr); } } // namespace
diff --git a/components/cronet/stale_host_resolver.cc b/components/cronet/stale_host_resolver.cc index 3f014e30..3ce28df 100644 --- a/components/cronet/stale_host_resolver.cc +++ b/components/cronet/stale_host_resolver.cc
@@ -361,10 +361,7 @@ } StaleHostResolver::StaleOptions::StaleOptions() - : delay(), - max_expired_time(), - allow_other_network(false), - max_stale_uses(0) {} + : allow_other_network(false), max_stale_uses(0) {} StaleHostResolver::StaleHostResolver( std::unique_ptr<net::HostResolverImpl> inner_resolver,
diff --git a/components/cronet/test/test_server.cc b/components/cronet/test/test_server.cc index 6b6b164..bba65bfa 100644 --- a/components/cronet/test/test_server.cc +++ b/components/cronet/test/test_server.cc
@@ -199,13 +199,13 @@ /* static */ int TestServer::GetPort() { - DCHECK(g_test_server.get()); + DCHECK(g_test_server); return g_test_server->port(); } /* static */ std::string TestServer::GetHostPort() { - DCHECK(g_test_server.get()); + DCHECK(g_test_server); return net::HostPortPair::FromURL(g_test_server->base_url()).ToString(); }
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 72130a5..3c0083c3 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -126,20 +126,6 @@ const char kSSLKeyLogFile[] = "ssl_key_log_file"; -// A CTPolicyEnforcer that accepts all certificates. -class DoNothingCTPolicyEnforcer : public net::CTPolicyEnforcer { - public: - DoNothingCTPolicyEnforcer() = default; - ~DoNothingCTPolicyEnforcer() override = default; - - net::ct::CTPolicyCompliance CheckCompliance( - net::X509Certificate* cert, - const net::SCTList& verified_scts, - const net::NetLogWithSource& net_log) override { - return net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } -}; - } // namespace URLRequestContextConfig::QuicHint::QuicHint(const std::string& host, @@ -231,8 +217,7 @@ StaleHostResolver::StaleOptions stale_dns_options; std::string host_resolver_rules_string; - for (base::DictionaryValue::Iterator it(*dict.get()); !it.IsAtEnd(); - it.Advance()) { + for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { if (it.key() == kQuicFieldTrialName) { const base::DictionaryValue* quic_args = nullptr; if (!it.value().GetAsDictionary(&quic_args)) { @@ -591,7 +576,7 @@ context_builder->set_ct_verifier( std::make_unique<net::DoNothingCTVerifier>()); context_builder->set_ct_policy_enforcer( - std::make_unique<DoNothingCTPolicyEnforcer>()); + std::make_unique<net::DefaultCTPolicyEnforcer>()); // TODO(mef): Use |config| to set cookies. }
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc index ed6203c..8c11b05 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -230,15 +230,15 @@ std::unique_ptr<net::URLRequest> request = CreateRequest(true /* is main */, content::PREVIEWS_OFF); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); request = CreateRequest(true /* is main */, content::PREVIEWS_NO_TRANSFORM); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); request = CreateRequest(true /* is main */, content::PREVIEWS_UNSPECIFIED); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); } @@ -255,12 +255,12 @@ std::unique_ptr<net::URLRequest> request = CreateRequestByType(content::RESOURCE_TYPE_MAIN_FRAME, true /* https */, both_previews_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); request = CreateRequestByType(content::RESOURCE_TYPE_IMAGE, true /* https */, both_previews_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); } @@ -275,11 +275,11 @@ // Verify accepting lite-page per resource type. std::unique_ptr<net::URLRequest> request = CreateRequest(true /* is main */, lite_page_enabled); - VerifyAcceptTransformHeader(*request.get(), true /* lite-page */, + VerifyAcceptTransformHeader(*request, true /* lite-page */, false /* empty-image */); request = CreateRequest(false /* is main */, lite_page_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); } @@ -294,27 +294,27 @@ // Verify accepting empty-image per resource type. std::unique_ptr<net::URLRequest> request = CreateRequestByType( content::RESOURCE_TYPE_MAIN_FRAME, false /* https */, lofi_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); request = CreateRequestByType(content::RESOURCE_TYPE_IMAGE, false /* https */, lofi_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, true /* empty-image */); request = CreateRequestByType(content::RESOURCE_TYPE_FAVICON, false /* https */, lofi_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, true /* empty-image */); request = CreateRequestByType(content::RESOURCE_TYPE_SCRIPT, false /* https */, lofi_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); request = CreateRequestByType(content::RESOURCE_TYPE_STYLESHEET, false /* https */, lofi_enabled); - VerifyAcceptTransformHeader(*request.get(), false /* lite-page */, + VerifyAcceptTransformHeader(*request, false /* lite-page */, false /* empty-image */); } @@ -466,13 +466,13 @@ new data_reduction_proxy::ContentLoFiDecider()); std::unique_ptr<net::URLRequest> request1 = CreateRequestByType( content::RESOURCE_TYPE_IMAGE, false, content::SERVER_LOFI_ON); - EXPECT_TRUE(lofi_decider->ShouldRecordLoFiUMA(*request1.get())); + EXPECT_TRUE(lofi_decider->ShouldRecordLoFiUMA(*request1)); std::unique_ptr<net::URLRequest> request2 = CreateRequestByType( content::RESOURCE_TYPE_MAIN_FRAME, false, content::PREVIEWS_OFF); - EXPECT_FALSE(lofi_decider->ShouldRecordLoFiUMA(*request2.get())); + EXPECT_FALSE(lofi_decider->ShouldRecordLoFiUMA(*request2)); std::unique_ptr<net::URLRequest> request3 = CreateRequestByType( content::RESOURCE_TYPE_MAIN_FRAME, false, content::SERVER_LITE_PAGE_ON); - EXPECT_TRUE(lofi_decider->ShouldRecordLoFiUMA(*request3.get())); + EXPECT_TRUE(lofi_decider->ShouldRecordLoFiUMA(*request3)); } TEST_F(ContentLoFiDeciderTest, NoTransformDoesNotAddHeader) {
diff --git a/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc b/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc index f6fc2463..025379c9 100644 --- a/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc +++ b/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
@@ -337,7 +337,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); PageloadMetrics* pageload_metrics = metrics_request_.add_pageloads(); AddDataToPageloadMetrics(request_data, timing, crash_type, pageload_metrics); - if (current_fetcher_.get()) + if (current_fetcher_) return; DCHECK_EQ(1, metrics_request_.pageloads_size()); CreateFetcherForDataAndStart();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc index bc20df0d..460aceb4 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
@@ -15,6 +15,8 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "net/base/load_flags.h" #include "net/base/proxy_server.h" #include "net/http/http_response_headers.h" @@ -33,38 +35,38 @@ namespace { -// Adds non-empty entries in |data_reduction_proxies| to the retry map -// maintained by the proxy service of the request. Adds -// |data_reduction_proxies.second| to the retry list only if |bypass_all| is -// true. -void MarkProxiesAsBadUntil( - net::URLRequest* request, - const base::TimeDelta& bypass_duration, - bool bypass_all, - const std::vector<net::ProxyServer>& data_reduction_proxies) { - DCHECK(!data_reduction_proxies.empty()); +// Adds the Data Reduction Proxy servers in |proxy_type_info| that should be +// marked bad according to |data_reduction_proxy_info| to the retry map +// maintained by the proxy resolution service of the |request|. +void MarkProxiesAsBad(const net::URLRequest& request, + const DataReductionProxyInfo& data_reduction_proxy_info, + const DataReductionProxyTypeInfo& proxy_type_info) { + DCHECK_GT(proxy_type_info.proxy_servers.size(), proxy_type_info.proxy_index); + // Synthesize a suitable |ProxyInfo| to add the proxies to the // |ProxyRetryInfoMap| of the proxy service. net::ProxyList proxy_list; - std::vector<net::ProxyServer> additional_bad_proxies; - for (const net::ProxyServer& proxy_server : data_reduction_proxies) { - DCHECK(proxy_server.is_valid()); - proxy_list.AddProxyServer(proxy_server); - if (!bypass_all) - break; - additional_bad_proxies.push_back(proxy_server); + + const size_t bad_proxy_end_index = data_reduction_proxy_info.bypass_all + ? proxy_type_info.proxy_servers.size() + : proxy_type_info.proxy_index + 1U; + + for (size_t i = proxy_type_info.proxy_index; i < bad_proxy_end_index; ++i) { + const net::ProxyServer& bad_proxy = + proxy_type_info.proxy_servers[i].proxy_server(); + DCHECK(bad_proxy.is_valid()); + DCHECK(!bad_proxy.is_direct()); + proxy_list.AddProxyServer(bad_proxy); } + std::vector<net::ProxyServer> bad_proxies = proxy_list.GetAll(); proxy_list.AddProxyServer(net::ProxyServer::Direct()); net::ProxyInfo proxy_info; proxy_info.UseProxyList(proxy_list); - DCHECK(request->context()); - net::ProxyResolutionService* proxy_resolution_service = - request->context()->proxy_resolution_service(); - DCHECK(proxy_resolution_service); - proxy_resolution_service->MarkProxiesAsBadUntil( - proxy_info, bypass_duration, additional_bad_proxies, request->net_log()); + request.context()->proxy_resolution_service()->MarkProxiesAsBadUntil( + proxy_info, data_reduction_proxy_info.bypass_duration, bad_proxies, + request.net_log()); } } // namespace @@ -85,7 +87,6 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(request); - DataReductionProxyTypeInfo data_reduction_proxy_type_info; DataReductionProxyBypassType bypass_type; const net::HttpResponseHeaders* response_headers = @@ -93,21 +94,19 @@ bool retry; if (!response_headers) { retry = HandleInvalidResponseHeadersCase( - *request, data_reduction_proxy_info, &data_reduction_proxy_type_info, - &bypass_type); - + *request, data_reduction_proxy_info, &bypass_type); } else { retry = HandleValidResponseHeadersCase( - *request, proxy_bypass_type, data_reduction_proxy_info, - &data_reduction_proxy_type_info, &bypass_type); + *request, proxy_bypass_type, data_reduction_proxy_info, &bypass_type); } if (!retry) return false; if (data_reduction_proxy_info->mark_proxies_as_bad) { - MarkProxiesAsBadUntil(request, data_reduction_proxy_info->bypass_duration, - data_reduction_proxy_info->bypass_all, - data_reduction_proxy_type_info.proxy_servers); + base::Optional<DataReductionProxyTypeInfo> proxy_type_info = + config_->FindConfiguredDataReductionProxy(request->proxy_server()); + DCHECK(proxy_type_info); + MarkProxiesAsBad(*request, *data_reduction_proxy_info, *proxy_type_info); } else { request->SetLoadFlags(request->load_flags() | net::LOAD_BYPASS_CACHE | net::LOAD_BYPASS_PROXY); @@ -120,7 +119,6 @@ bool DataReductionProxyBypassProtocol::HandleInvalidResponseHeadersCase( const net::URLRequest& request, DataReductionProxyInfo* data_reduction_proxy_info, - DataReductionProxyTypeInfo* data_reduction_proxy_type_info, DataReductionProxyBypassType* bypass_type) const { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(nullptr, request.response_info().headers.get()); @@ -132,10 +130,8 @@ return false; } - if (!config_->WasDataReductionProxyUsed(&request, - data_reduction_proxy_type_info)) { + if (!config_->FindConfiguredDataReductionProxy(request.proxy_server())) return false; - } DCHECK(request.url().SchemeIs(url::kHttpScheme)); @@ -179,7 +175,6 @@ const net::URLRequest& request, DataReductionProxyBypassType* proxy_bypass_type, DataReductionProxyInfo* data_reduction_proxy_info, - DataReductionProxyTypeInfo* data_reduction_proxy_type_info, DataReductionProxyBypassType* bypass_type) const { DCHECK(thread_checker_.CalledOnValidThread()); @@ -190,15 +185,15 @@ DCHECK(response_headers); - if (!config_->WasDataReductionProxyUsed(&request, - data_reduction_proxy_type_info)) { + base::Optional<DataReductionProxyTypeInfo> data_reduction_proxy_type_info = + config_->FindConfiguredDataReductionProxy(request.proxy_server()); + if (!data_reduction_proxy_type_info) return false; - } // At this point, the response is expected to have the data reduction proxy // via header, so detect and report cases where the via header is missing. DataReductionProxyBypassStats::DetectAndRecordMissingViaHeaderResponseCode( - data_reduction_proxy_type_info->proxy_index == 0, *response_headers); + data_reduction_proxy_type_info->proxy_index == 0U, *response_headers); // GetDataReductionProxyBypassType will only log a net_log event if a bypass // command was sent via the data reduction proxy headers. @@ -212,16 +207,20 @@ DCHECK(request.context()); DCHECK(request.context()->proxy_resolution_service()); - DCHECK_LT(0U, data_reduction_proxy_type_info->proxy_servers.size()); - net::ProxyServer proxy_server = - data_reduction_proxy_type_info->proxy_servers.front(); + DCHECK_GT(data_reduction_proxy_type_info->proxy_servers.size(), + data_reduction_proxy_type_info->proxy_index); + + const net::ProxyServer& proxy_server = + data_reduction_proxy_type_info + ->proxy_servers[data_reduction_proxy_type_info->proxy_index] + .proxy_server(); // Only record UMA if the proxy isn't already on the retry list. if (!config_->IsProxyBypassed( - request.context()->proxy_resolution_service()->proxy_retry_info(), proxy_server, - nullptr)) { + request.context()->proxy_resolution_service()->proxy_retry_info(), + proxy_server, nullptr)) { DataReductionProxyBypassStats::RecordDataReductionProxyBypassInfo( - data_reduction_proxy_type_info->proxy_index == 0, + data_reduction_proxy_type_info->proxy_index == 0U, data_reduction_proxy_info->bypass_all, proxy_server, *bypass_type); } return true;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h index c0eff9e..af3bd0b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
@@ -16,7 +16,6 @@ namespace data_reduction_proxy { class DataReductionProxyConfig; -struct DataReductionProxyTypeInfo; // Class responsible for determining when a response should or should not cause // the data reduction proxy to be bypassed, and to what degree. Owned by the @@ -48,7 +47,6 @@ bool HandleInvalidResponseHeadersCase( const net::URLRequest& request, DataReductionProxyInfo* data_reduction_proxy_info, - DataReductionProxyTypeInfo* data_reduction_proxy_type_info, DataReductionProxyBypassType* bypass_type) const; // Decides whether to mark the data reduction proxy as temporarily bad and @@ -59,7 +57,6 @@ const net::URLRequest& request, DataReductionProxyBypassType* proxy_bypass_type, DataReductionProxyInfo* data_reduction_proxy_info, - DataReductionProxyTypeInfo* data_reduction_proxy_type_info, DataReductionProxyBypassType* bypass_type) const; // Must outlive |this|.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc index 47b69e4..04b5c04 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -355,8 +355,8 @@ std::string response2; std::string request2; - std::string response2_via_header = ""; - std::string request2_connection_type = ""; + std::string response2_via_header; + std::string request2_connection_type; std::string request2_path = "/"; if (expected_bad_proxy_count == 1) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc index 0c52cf82..1c47b73d 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -11,6 +11,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/proxy_server.h" @@ -119,14 +120,16 @@ bool started, int net_error) { DCHECK(thread_checker_.CalledOnValidThread()); - DataReductionProxyTypeInfo proxy_info; + + base::Optional<DataReductionProxyTypeInfo> proxy_info = + data_reduction_proxy_config_->FindConfiguredDataReductionProxy( + request->proxy_server()); + // Ignore requests that did not use the data reduction proxy. The check for // LOAD_BYPASS_PROXY is necessary because the proxy_server() in the |request| // might still be set to the data reduction proxy if |request| was retried // over direct and a network error occurred while retrying it. - if (!data_reduction_proxy_config_->WasDataReductionProxyUsed(request, - &proxy_info) || - (request->load_flags() & net::LOAD_BYPASS_PROXY) != 0 || + if (!proxy_info || (request->load_flags() & net::LOAD_BYPASS_PROXY) != 0 || net_error != net::OK) { return; } @@ -136,15 +139,11 @@ // Report the success counts. UMA_HISTOGRAM_COUNTS_100( "DataReductionProxy.SuccessfulRequestCompletionCounts", - proxy_info.proxy_index); - - DCHECK(request->proxy_server().host_port_pair().Equals( - proxy_info.proxy_servers.front().host_port_pair())); + proxy_info->proxy_index); // It is possible that the scheme of request->proxy_server() is different // from the scheme of proxy_info.proxy_servers.front(). The former may be set // to QUIC by the network stack, while the latter may be set to HTTPS. - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ProxySchemeUsed", util::ConvertNetProxySchemeToProxyScheme( request->proxy_server().scheme()), @@ -152,8 +151,8 @@ if (request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) { UMA_HISTOGRAM_COUNTS_100( "DataReductionProxy.SuccessfulRequestCompletionCounts.MainFrame", - proxy_info.proxy_index); - } + proxy_info->proxy_index); + } } void DataReductionProxyBypassStats::SetBypassType( @@ -173,35 +172,33 @@ const net::ProxyServer& bypassed_proxy, int net_error) { DCHECK(thread_checker_.CalledOnValidThread()); - DataReductionProxyTypeInfo data_reduction_proxy_info; - if (bypassed_proxy.is_valid() && !bypassed_proxy.is_direct() && - data_reduction_proxy_config_->IsDataReductionProxy( - bypassed_proxy, &data_reduction_proxy_info)) { - proxy_net_errors_count_++; + if (!bypassed_proxy.is_valid() || bypassed_proxy.is_direct()) + return; - // To account for the case when the proxy is reachable for sometime, and - // then gets blocked, we reset counts when number of errors exceed - // the threshold. - if (proxy_net_errors_count_ >= kMaxFailedRequestsBeforeReset && - successful_requests_through_proxy_count_ > - kMaxSuccessfulRequestsWhenUnavailable) { - ClearRequestCounts(); - } else { - NotifyUnavailabilityIfChanged(); - } + base::Optional<DataReductionProxyTypeInfo> proxy_type_info = + data_reduction_proxy_config_->FindConfiguredDataReductionProxy( + bypassed_proxy); + if (!proxy_type_info) + return; - if (data_reduction_proxy_info.proxy_index == 0) { - RecordDataReductionProxyBypassInfo( - true, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); - RecordDataReductionProxyBypassOnNetworkError( - true, bypassed_proxy, net_error); - } else { - RecordDataReductionProxyBypassInfo( - false, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); - RecordDataReductionProxyBypassOnNetworkError( - false, bypassed_proxy, net_error); - } + proxy_net_errors_count_++; + + // To account for the case when the proxy is reachable for sometime, and + // then gets blocked, we reset counts when number of errors exceed + // the threshold. + if (proxy_net_errors_count_ >= kMaxFailedRequestsBeforeReset && + successful_requests_through_proxy_count_ > + kMaxSuccessfulRequestsWhenUnavailable) { + ClearRequestCounts(); + } else { + NotifyUnavailabilityIfChanged(); } + + const bool is_first_proxy = proxy_type_info->proxy_index == 0U; + RecordDataReductionProxyBypassInfo(is_first_proxy, false, bypassed_proxy, + BYPASS_EVENT_TYPE_NETWORK_ERROR); + RecordDataReductionProxyBypassOnNetworkError(is_first_proxy, bypassed_proxy, + net_error); } void DataReductionProxyBypassStats::ClearRequestCounts() { @@ -237,9 +234,8 @@ if (!request.url().SchemeIsHTTPOrHTTPS()) return; - DataReductionProxyTypeInfo data_reduction_proxy_type_info; - if (data_reduction_proxy_config_->WasDataReductionProxyUsed( - &request, &data_reduction_proxy_type_info)) { + if (data_reduction_proxy_config_->FindConfiguredDataReductionProxy( + request.proxy_server())) { RecordBypassedBytes(last_bypass_type_, DataReductionProxyBypassStats::NOT_BYPASSED, content_length); @@ -256,7 +252,6 @@ // Now that the data reduction proxy is a best effort proxy, if the effective // proxy configuration resolves to anything other than direct:// for a URL, // the data reduction proxy will not be used. - DCHECK(data_reduction_proxy_type_info.proxy_servers.empty()); if (!request.proxy_server().is_valid() || !request.proxy_server().is_direct()) { RecordBypassedBytes(last_bypass_type_,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc index 549cc91d..338c3a8 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -40,6 +40,7 @@ #include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" +#include "net/log/test_net_log.h" #include "net/socket/socket_test_util.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request.h" @@ -375,38 +376,6 @@ net::TestDelegate* delegate() { return &delegate_; } - // Marks a data reduction proxy as bypassed if - // |bypassed_proxy_server_is_data_reduction_proxy| is true. Then, runs a - // request via data reduction proxy if |is_data_reduction_proxy| is true, - // and verifies that proxy is unreachable only if |is_unreachable| is true. - void VerifyProxyReachablity( - bool bypassed_proxy_server_is_data_reduction_proxy, - bool is_data_reduction_proxy, - bool is_unreachable) { - InitializeContext(); - - std::string proxy = bypassed_proxy_server_is_data_reduction_proxy - ? "origin.net:80" - : "foo.net:80"; - net::ProxyServer fallback_proxy_server = - net::ProxyServer::FromURI(proxy, net::ProxyServer::SCHEME_HTTP); - - bypass_stats()->OnProxyFallback(fallback_proxy_server, - net::ERR_PROXY_CONNECTION_FAILED); - drp_test_context()->RunUntilIdle(); - - if (!is_data_reduction_proxy) - config()->SetWasDataReductionProxyNotUsed(); - - CreateAndExecuteRequest(GURL("http://bar.com"), net::LOAD_NORMAL, net::OK, - "HTTP/1.1 200 OK\r\n" - "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n", - kNextBody.c_str(), nullptr, nullptr); - - drp_test_context()->RunUntilIdle(); - EXPECT_EQ(is_unreachable, IsUnreachable()); - } - private: base::MessageLoopForIO message_loop_; net::TestDelegate delegate_; @@ -746,26 +715,6 @@ } TEST_F(DataReductionProxyBypassStatsEndToEndTest, - IsDataReductionProxyUnreachable_Unreachable) { - VerifyProxyReachablity(true, false, true); -} - -TEST_F(DataReductionProxyBypassStatsEndToEndTest, - IsDataReductionProxyUnreachable_Unreachable_Then_Reachable) { - VerifyProxyReachablity(true, true, false); -} - -TEST_F(DataReductionProxyBypassStatsEndToEndTest, - IsDataReductionProxyUnreachable_Not_A_data_reduction_proxy_1) { - VerifyProxyReachablity(false, true, false); -} - -TEST_F(DataReductionProxyBypassStatsEndToEndTest, - IsDataReductionProxyUnreachableNot_A_data_reduction_proxy_2) { - VerifyProxyReachablity(false, false, false); -} - -TEST_F(DataReductionProxyBypassStatsEndToEndTest, ProxyUnreachableThenReachable) { net::ProxyServer fallback_proxy_server = net::ProxyServer::FromURI("origin.net:80", net::ProxyServer::SCHEME_HTTP); @@ -867,72 +816,124 @@ } } -TEST_F(DataReductionProxyBypassStatsEndToEndTest, SuccessfulRequestCompletion) { - const std::string kPrimaryHistogramName = +TEST_F(DataReductionProxyBypassStatsEndToEndTest, + SuccessfulPrimaryProxyRequestCompletion) { + const std::string kHistogramName = "DataReductionProxy.SuccessfulRequestCompletionCounts"; - const std::string kPrimaryMainFrameHistogramName = + const std::string kMainFrameHistogramName = "DataReductionProxy.SuccessfulRequestCompletionCounts.MainFrame"; InitializeContext(); + const struct { - bool was_proxy_used; - bool is_load_bypass_proxy; - size_t proxy_index; - bool is_main_frame; + int load_flags; net::Error net_error; - } tests[] = {{false, true, 0, true, net::OK}, - {false, true, 0, false, net::ERR_TOO_MANY_REDIRECTS}, - {false, false, 0, true, net::OK}, - {false, false, 0, false, net::ERR_TOO_MANY_REDIRECTS}, - {true, false, 0, true, net::OK}, - {true, false, 0, true, net::ERR_TOO_MANY_REDIRECTS}, - {true, false, 0, false, net::OK}, - {true, false, 0, false, net::ERR_TOO_MANY_REDIRECTS}, - {true, false, 1, true, net::OK}, - {true, false, 1, true, net::ERR_TOO_MANY_REDIRECTS}, - {true, false, 1, false, net::OK}, - {true, false, 1, false, net::ERR_TOO_MANY_REDIRECTS}}; + bool expect_histogram_sample; + bool expect_main_frame_histogram_sample; + } tests[] = { + {net::LOAD_BYPASS_PROXY | net::LOAD_MAIN_FRAME_DEPRECATED, net::OK, false, + false}, + {net::LOAD_BYPASS_PROXY | net::LOAD_MAIN_FRAME_DEPRECATED, + net::ERR_TOO_MANY_REDIRECTS, false, false}, + {net::LOAD_BYPASS_PROXY, net::OK, false, false}, + {net::LOAD_BYPASS_PROXY, net::ERR_TOO_MANY_REDIRECTS, false, false}, + {net::LOAD_MAIN_FRAME_DEPRECATED, net::OK, true, true}, + {net::LOAD_MAIN_FRAME_DEPRECATED, net::ERR_TOO_MANY_REDIRECTS, false, + false}, + {0, net::OK, true, false}, + {0, net::ERR_TOO_MANY_REDIRECTS, false, false}, + }; for (const auto& test : tests) { - config()->ResetWasDataReductionProxyUsed(); base::HistogramTester histogram_tester; - - // Proxy succeeds. - int load_flags = net::LOAD_NORMAL; - if (test.is_load_bypass_proxy) { - load_flags |= net::LOAD_BYPASS_PROXY; - } - if (test.is_main_frame) { - load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; - } - - if (!test.was_proxy_used) - config()->SetWasDataReductionProxyNotUsed(); - else { - config()->SetWasDataReductionProxyUsedProxyIndex(test.proxy_index); - } - - CreateAndExecuteRequest(GURL("http://bar.com"), load_flags, test.net_error, + CreateAndExecuteRequest(GURL("http://foo.com"), test.load_flags, + test.net_error, "HTTP/1.1 200 OK\r\n" "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n", kNextBody.c_str(), nullptr, nullptr); drp_test_context()->RunUntilIdle(); - if (test.was_proxy_used && !test.is_load_bypass_proxy && - test.net_error == net::OK) { - histogram_tester.ExpectUniqueSample(kPrimaryHistogramName, - test.proxy_index, 1); - } else { - histogram_tester.ExpectTotalCount(kPrimaryHistogramName, 0); - } + if (test.expect_histogram_sample) + histogram_tester.ExpectUniqueSample(kHistogramName, 0, 1); + else + histogram_tester.ExpectTotalCount(kHistogramName, 0); - if (test.was_proxy_used && !test.is_load_bypass_proxy && - test.is_main_frame && test.net_error == net::OK) { - histogram_tester.ExpectUniqueSample(kPrimaryMainFrameHistogramName, - test.proxy_index, 1); - } else { - histogram_tester.ExpectTotalCount(kPrimaryMainFrameHistogramName, 0); - } + if (test.expect_main_frame_histogram_sample) + histogram_tester.ExpectUniqueSample(kMainFrameHistogramName, 0, 1); + else + histogram_tester.ExpectTotalCount(kMainFrameHistogramName, 0); + } +} + +TEST_F(DataReductionProxyBypassStatsEndToEndTest, + SuccessfulFallbackProxyRequestCompletion) { + const std::string kHistogramName = + "DataReductionProxy.SuccessfulRequestCompletionCounts"; + const std::string kMainFrameHistogramName = + "DataReductionProxy.SuccessfulRequestCompletionCounts.MainFrame"; + + // Explicitly set primary and fallback Data Reduction Proxies to use. + config()->test_params()->SetProxiesForHttp( + std::vector<DataReductionProxyServer>( + {DataReductionProxyServer( + net::ProxyServer::FromURI("http://origin.net", + net::ProxyServer::SCHEME_HTTP), + ProxyServer::CORE), + DataReductionProxyServer( + net::ProxyServer::FromURI("http://fallback.net", + net::ProxyServer::SCHEME_HTTP), + ProxyServer::CORE)})); + + // Make the first Data Reduction Proxy host in the list of Data Reduction + // Proxies to use fail to resolve, so that the tests below will use the + // fallback proxy. + std::unique_ptr<net::MockHostResolver> host_resolver( + new net::MockHostResolver()); + const DataReductionProxyServer& primary_proxy = + config()->test_params()->proxies_for_http().front(); + host_resolver->rules()->AddSimulatedFailure( + primary_proxy.proxy_server().host_port_pair().host()); + + set_host_resolver(host_resolver.get()); + InitializeContext(); + + const struct { + int load_flags; + net::Error net_error; + bool expect_histogram_sample; + bool expect_main_frame_histogram_sample; + } tests[] = { + {net::LOAD_BYPASS_PROXY | net::LOAD_MAIN_FRAME_DEPRECATED, net::OK, false, + false}, + {net::LOAD_BYPASS_PROXY | net::LOAD_MAIN_FRAME_DEPRECATED, + net::ERR_TOO_MANY_REDIRECTS, false, false}, + {net::LOAD_BYPASS_PROXY, net::OK, false, false}, + {net::LOAD_BYPASS_PROXY, net::ERR_TOO_MANY_REDIRECTS, false, false}, + {net::LOAD_MAIN_FRAME_DEPRECATED, net::OK, true, true}, + {net::LOAD_MAIN_FRAME_DEPRECATED, net::ERR_TOO_MANY_REDIRECTS, false, + false}, + {0, net::OK, true, false}, + {0, net::ERR_TOO_MANY_REDIRECTS, false, false}, + }; + + for (const auto& test : tests) { + base::HistogramTester histogram_tester; + CreateAndExecuteRequest(GURL("http://foo.com"), test.load_flags, + test.net_error, + "HTTP/1.1 200 OK\r\n" + "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n", + kNextBody.c_str(), nullptr, nullptr); + drp_test_context()->RunUntilIdle(); + + if (test.expect_histogram_sample) + histogram_tester.ExpectUniqueSample(kHistogramName, 1, 1); + else + histogram_tester.ExpectTotalCount(kHistogramName, 0); + + if (test.expect_main_frame_histogram_sample) + histogram_tester.ExpectUniqueSample(kMainFrameHistogramName, 1, 1); + else + histogram_tester.ExpectTotalCount(kMainFrameHistogramName, 0); } }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc index dd6402d..4d12e6c6 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include <algorithm> #include <utility> #include "base/bind.h" @@ -33,6 +32,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/previews/core/previews_decider.h" #include "components/variations/variations_associated_data.h" @@ -247,73 +247,11 @@ } } -bool DataReductionProxyConfig::WasDataReductionProxyUsed( - const net::URLRequest* request, - DataReductionProxyTypeInfo* proxy_info) const { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(request); - return IsDataReductionProxy(request->proxy_server(), proxy_info); -} - -bool DataReductionProxyConfig::IsDataReductionProxyServerCore( +base::Optional<DataReductionProxyTypeInfo> +DataReductionProxyConfig::FindConfiguredDataReductionProxy( const net::ProxyServer& proxy_server) const { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(IsDataReductionProxy(proxy_server, nullptr /* proxy_info */)); - - const net::HostPortPair& host_port_pair = proxy_server.host_port_pair(); - - const std::vector<DataReductionProxyServer>& data_reduction_proxy_servers = - config_values_->proxies_for_http(); - - const auto proxy_it = std::find_if( - data_reduction_proxy_servers.begin(), data_reduction_proxy_servers.end(), - [&host_port_pair](const DataReductionProxyServer& proxy) { - return proxy.proxy_server().is_valid() && - proxy.proxy_server().host_port_pair().Equals(host_port_pair); - }); - - return proxy_it->IsCoreProxy(); -} - -bool DataReductionProxyConfig::IsDataReductionProxy( - const net::ProxyServer& proxy_server, - DataReductionProxyTypeInfo* proxy_info) const { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!proxy_server.is_valid() || proxy_server.is_direct()) - return false; - - // Only compare the host port pair of the |proxy_server| since the proxy - // scheme of the stored data reduction proxy may be different than the proxy - // scheme of |proxy_server|. This may happen even when the |proxy_server| is a - // valid data reduction proxy. As an example, the stored data reduction proxy - // may have a proxy scheme of HTTPS while |proxy_server| may have QUIC as the - // proxy scheme. - const net::HostPortPair& host_port_pair = proxy_server.host_port_pair(); - - const std::vector<DataReductionProxyServer>& data_reduction_proxy_servers = - config_values_->proxies_for_http(); - - const auto proxy_it = std::find_if( - data_reduction_proxy_servers.begin(), data_reduction_proxy_servers.end(), - [&host_port_pair](const DataReductionProxyServer& proxy) { - return proxy.proxy_server().is_valid() && - proxy.proxy_server().host_port_pair().Equals(host_port_pair); - }); - - if (proxy_it == data_reduction_proxy_servers.end()) - return false; - - if (!proxy_info) - return true; - - proxy_info->proxy_servers = - DataReductionProxyServer::ConvertToNetProxyServers( - std::vector<DataReductionProxyServer>( - proxy_it, data_reduction_proxy_servers.end())); - proxy_info->proxy_index = - static_cast<size_t>(proxy_it - data_reduction_proxy_servers.begin()); - return true; + return config_values_->FindConfiguredDataReductionProxy(proxy_server); } bool DataReductionProxyConfig::IsBypassedByDataReductionProxyLocalRules( @@ -329,7 +267,7 @@ return true; if (result.proxy_server().is_direct()) return true; - return !IsDataReductionProxy(result.proxy_server(), nullptr); + return !FindConfiguredDataReductionProxy(result.proxy_server()); } bool DataReductionProxyConfig::AreDataReductionProxiesBypassed( @@ -374,7 +312,7 @@ continue; base::TimeDelta delay; - if (IsDataReductionProxy(proxy, nullptr)) { + if (FindConfiguredDataReductionProxy(proxy)) { if (!IsProxyBypassed(retry_map, proxy, &delay)) return false; if (delay < min_delay) @@ -418,7 +356,7 @@ proxy_rules.MapUrlSchemeToProxyList("http"); if (http_proxy_list && !http_proxy_list->IsEmpty() && // Sufficient to check only the first proxy. - IsDataReductionProxy(http_proxy_list->Get(), nullptr)) { + FindConfiguredDataReductionProxy(http_proxy_list->Get())) { return true; } @@ -501,7 +439,7 @@ const std::vector<DataReductionProxyServer>& proxies = DataReductionProxyConfig::GetProxiesForHttp(); - for (const auto proxy_server : proxies) { + for (const DataReductionProxyServer& proxy_server : proxies) { // First find a proxy server that has never been probed before. Proxies that // have been probed before successfully do not need to be probed. On the // other hand, proxies that have been probed before unsuccessfully are @@ -516,7 +454,7 @@ } } - for (const auto proxy_server : proxies) { + for (const DataReductionProxyServer& proxy_server : proxies) { // Now find any proxy server that can be probed. This would return proxies // that were probed before, the result was unsuccessful, but they have not // yet hit the maximum probe retry limit. @@ -544,9 +482,11 @@ (success_response == WarmupURLFetcher::FetchResult::kTimedOut && !proxy_server.is_valid()); + base::Optional<DataReductionProxyTypeInfo> proxy_type_info = + FindConfiguredDataReductionProxy(proxy_server); + // Check the proxy server used. - if (!timed_out_with_no_proxy_data && - !IsDataReductionProxy(proxy_server, nullptr)) { + if (!timed_out_with_no_proxy_data && !proxy_type_info) { // No need to do anything here since the warmup fetch did not go through // the data saver proxy. return; @@ -557,7 +497,11 @@ if (!timed_out_with_no_proxy_data) { is_secure_proxy = proxy_server.is_https() || proxy_server.is_quic(); - is_core_proxy = IsDataReductionProxyServerCore(proxy_server); + + DCHECK(proxy_type_info); + is_core_proxy = proxy_type_info->proxy_servers[proxy_type_info->proxy_index] + .IsCoreProxy(); + // The proxy server through which the warmup URL was fetched should match // the proxy server for which the warmup URL is in-flight. DCHECK(GetInFlightWarmupProxyDetails());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h index 986045b..46ad672 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -16,11 +16,13 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/secure_proxy_checker.h" #include "components/data_reduction_proxy/core/browser/warmup_url_fetcher.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "components/previews/core/previews_experiments.h" #include "net/base/network_change_notifier.h" @@ -119,27 +121,11 @@ // InitDataReductionProxySettings. void SetProxyConfig(bool enabled, bool at_startup); - // Returns true if a Data Reduction Proxy was used for the given |request|. - // If true, |proxy_info.proxy_servers.front()| will contain the name of the - // proxy that was used. Subsequent entries in |proxy_info.proxy_servers| will - // contain the names of the Data Reduction Proxy servers that would be used if - // |proxy_info.proxy_servers.front()| is bypassed, if any exist. In addition, - // |proxy_info| will note if the proxy used was a fallback. |proxy_info| can - // be NULL if the caller isn't interested in its values. Virtualized for - // testing. - virtual bool WasDataReductionProxyUsed( - const net::URLRequest* request, - DataReductionProxyTypeInfo* proxy_info) const; - - // Returns true if the specified |proxy_server| matches a Data Reduction - // Proxy. If true, |proxy_info.proxy_servers.front()| will contain the name of - // the proxy that matches. Subsequent entries in |proxy_info.proxy_servers| - // will contain the name of the Data Reduction Proxy servers that would be - // used if |proxy_info.proxy_servers.front()| is bypassed, if any exist. In - // addition, |proxy_info| will note if the proxy was a fallback. |proxy_info| - // can be NULL if the caller isn't interested in its values. - bool IsDataReductionProxy(const net::ProxyServer& proxy_server, - DataReductionProxyTypeInfo* proxy_info) const; + // If the specified |proxy_server| matches a Data Reduction Proxy, returns the + // DataReductionProxyTypeInfo showing where that proxy is in the list of + // configured proxies, otherwise returns an empty optional value. + base::Optional<DataReductionProxyTypeInfo> FindConfiguredDataReductionProxy( + const net::ProxyServer& proxy_server) const; // Returns true if this request would be bypassed by the Data Reduction Proxy // based on applying the |data_reduction_proxy_config| param rules to the @@ -327,12 +313,6 @@ // Fetches the warmup URL. void FetchWarmupProbeURL(); - // Returns true if |proxy_server| is a core data reduction proxy server. - // Should be called only if |proxy_server| is a valid data reduction proxy - // server. - bool IsDataReductionProxyServerCore( - const net::ProxyServer& proxy_server) const; - // URL fetcher used for performing the secure proxy check. std::unique_ptr<SecureProxyChecker> secure_proxy_checker_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc index 2e430008..1706aa7 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -275,69 +275,66 @@ const net::LoadTimingInfo& load_timing_info) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(response_headers); - if (config_->IsDataReductionProxy(proxy_server, nullptr)) { - if (response_headers->response_code() == - net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { - std::string session_key = - request_options_->GetSessionKeyFromRequestHeaders(request_headers); - std::string current_session_key = request_options_->GetSecureSession(); + if (!config_->FindConfiguredDataReductionProxy(proxy_server)) + return false; - // If the session key used in the request is different from the current - // session key, then the current session key does not need to be - // invalidated. - if (session_key != current_session_key) { - RecordAuthExpiredSessionKey(false); - return true; - } - RecordAuthExpiredSessionKey(true); - - // The default backoff logic is to increment the failure count (and - // increase the backoff time) with each response failure to the remote - // config service, and to decrement the failure count (and decrease the - // backoff time) with each response success. In the case where the - // config service returns a success response (decrementing the failure - // count) but the session key is continually invalid (as a response from - // the Data Reduction Proxy and not the config service), the previous - // response should be considered a failure in order to ensure the backoff - // time continues to increase. - if (previous_request_failed_authentication_) - GetBackoffEntry()->InformOfRequest(false); - - // Record that a request resulted in an authentication failure. - RecordAuthExpiredHistogram(true); - previous_request_failed_authentication_ = true; - InvalidateConfig(); - DCHECK(!config_->IsDataReductionProxy(proxy_server, nullptr)); - - if (fetch_in_progress_) { - // If a client config fetch is already in progress, then do not start - // another fetch since starting a new fetch will cause extra data - // usage, and also cancel the ongoing fetch. - return true; - } - - RetrieveConfig(); - - if (!load_timing_info.send_start.is_null() && - !load_timing_info.request_start.is_null() && - net::NetworkChangeNotifier::GetConnectionType() != - net::NetworkChangeNotifier::CONNECTION_NONE && - last_ip_address_change_ < load_timing_info.request_start) { - // Record only if there was no change in the IP address since the - // request started. - UMA_HISTOGRAM_TIMES( - "DataReductionProxy.ConfigService.AuthFailure.LatencyPenalty", - base::TimeTicks::Now() - load_timing_info.request_start); - } - - return true; - } - + if (response_headers->response_code() != + net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { previous_request_failed_authentication_ = false; + return false; } - return false; + // If the session key used in the request is different from the current + // session key, then the current session key does not need to be + // invalidated. + if (request_options_->GetSessionKeyFromRequestHeaders(request_headers) != + request_options_->GetSecureSession()) { + RecordAuthExpiredSessionKey(false); + return true; + } + RecordAuthExpiredSessionKey(true); + + // The default backoff logic is to increment the failure count (and + // increase the backoff time) with each response failure to the remote + // config service, and to decrement the failure count (and decrease the + // backoff time) with each response success. In the case where the + // config service returns a success response (decrementing the failure + // count) but the session key is continually invalid (as a response from + // the Data Reduction Proxy and not the config service), the previous + // response should be considered a failure in order to ensure the backoff + // time continues to increase. + if (previous_request_failed_authentication_) + GetBackoffEntry()->InformOfRequest(false); + + // Record that a request resulted in an authentication failure. + RecordAuthExpiredHistogram(true); + previous_request_failed_authentication_ = true; + InvalidateConfig(); + DCHECK(config_->GetProxiesForHttp().empty()); + + if (fetch_in_progress_) { + // If a client config fetch is already in progress, then do not start + // another fetch since starting a new fetch will cause extra data + // usage, and also cancel the ongoing fetch. + return true; + } + + RetrieveConfig(); + + if (!load_timing_info.send_start.is_null() && + !load_timing_info.request_start.is_null() && + net::NetworkChangeNotifier::GetConnectionType() != + net::NetworkChangeNotifier::CONNECTION_NONE && + last_ip_address_change_ < load_timing_info.request_start) { + // Record only if there was no change in the IP address since the + // request started. + UMA_HISTOGRAM_TIMES( + "DataReductionProxy.ConfigService.AuthFailure.LatencyPenalty", + base::TimeTicks::Now() - load_timing_info.request_start); + } + + return true; } net::BackoffEntry* DataReductionProxyConfigServiceClient::GetBackoffEntry() { @@ -410,7 +407,7 @@ request.SerializeToString(&serialized_request); std::unique_ptr<net::URLFetcher> fetcher = GetURLFetcherForConfig(config_service_url_, serialized_request); - if (!fetcher.get()) { + if (!fetcher) { HandleResponse(std::string(), net::URLRequestStatus::FromError(net::ERR_ABORTED), net::URLFetcher::RESPONSE_CODE_INVALID);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc index 0ddeacf..e0834e1 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -991,7 +991,7 @@ std::string(kSuccessSessionKey) + ", key=value"); // Calling ShouldRetryDueToAuthFailure should trigger fetching of remote // config. - EXPECT_FALSE(config_client()->ShouldRetryDueToAuthFailure( + EXPECT_TRUE(config_client()->ShouldRetryDueToAuthFailure( request_headers, parsed.get(), origin, load_timing_info)); EXPECT_EQ(1, config_client()->GetBackoffErrorCount()); histogram_tester.ExpectBucketCount( @@ -1014,9 +1014,13 @@ EXPECT_GE(persisted_config_retrieval_time() + base::TimeDelta::FromMinutes(2), base::Time::Now()); - histogram_tester.ExpectUniqueSample( + histogram_tester.ExpectBucketCount( + "DataReductionProxy.ConfigService.AuthExpiredSessionKey", + 0 /* AUTH_EXPIRED_SESSION_KEY_MISMATCH */, 1); + histogram_tester.ExpectBucketCount( "DataReductionProxy.ConfigService.AuthExpiredSessionKey", 1 /* AUTH_EXPIRED_SESSION_KEY_MATCH */, 1); + histogram_tester.ExpectBucketCount( "DataReductionProxy.ConfigService.AuthExpired", false, 2); histogram_tester.ExpectBucketCount(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc index 50b69ecb..15832edb 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc
@@ -12,6 +12,7 @@ #include "base/time/tick_clock.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -77,34 +78,6 @@ return DataReductionProxyConfig::GetTicksNow(); } -bool TestDataReductionProxyConfig::WasDataReductionProxyUsed( - const net::URLRequest* request, - DataReductionProxyTypeInfo* proxy_info) const { - if (was_data_reduction_proxy_used_ && - !was_data_reduction_proxy_used_.value()) { - return false; - } - bool was_data_reduction_proxy_used = - DataReductionProxyConfig::WasDataReductionProxyUsed(request, proxy_info); - if (proxy_info && was_data_reduction_proxy_used && proxy_index_) - proxy_info->proxy_index = proxy_index_.value(); - return was_data_reduction_proxy_used; -} - -void TestDataReductionProxyConfig::SetWasDataReductionProxyNotUsed() { - was_data_reduction_proxy_used_ = false; -} - -void TestDataReductionProxyConfig::SetWasDataReductionProxyUsedProxyIndex( - int proxy_index) { - proxy_index_ = proxy_index; -} - -void TestDataReductionProxyConfig::ResetWasDataReductionProxyUsed() { - was_data_reduction_proxy_used_.reset(); - proxy_index_.reset(); -} - void TestDataReductionProxyConfig::SetIsCaptivePortal(bool is_captive_portal) { is_captive_portal_ = is_captive_portal; }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h index 99cf7f9..3612ad2 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
@@ -74,21 +74,6 @@ base::TimeTicks GetTicksNow() const override; - bool WasDataReductionProxyUsed( - const net::URLRequest* request, - DataReductionProxyTypeInfo* proxy_info) const override; - - // Sets the data reduction proxy as not used. Subsequent calls to - // WasDataReductionProxyUsed() would return false. - void SetWasDataReductionProxyNotUsed(); - - // Sets the proxy index of the data reduction proxy. Subsequent calls to - // WasDataReductionProxyUsed are affected. - void SetWasDataReductionProxyUsedProxyIndex(int proxy_index); - - // Resets the behavior of WasDataReductionProxyUsed() calls. - void ResetWasDataReductionProxyUsed(); - // Sets if the captive portal probe has been blocked for the current network. void SetIsCaptivePortal(bool is_captive_portal); @@ -132,9 +117,6 @@ base::Optional<size_t> previous_attempt_counts_; - base::Optional<bool> was_data_reduction_proxy_used_; - base::Optional<int> proxy_index_; - base::Optional<std::string> current_network_id_; base::Optional<std::pair<bool /* is_secure_proxy */, bool /*is_core_proxy */>>
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc index e36f6562..fc1c62c0 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -41,6 +41,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "components/previews/core/previews_experiments.h" #include "components/previews/core/test_previews_decider.h" @@ -771,57 +772,32 @@ EXPECT_EQ(delay, min_retry_delay); } -TEST_F(DataReductionProxyConfigTest, IsDataReductionProxyWithParams) { - const struct { - net::ProxyServer proxy_server; - bool expected_result; - net::ProxyServer expected_first; - net::ProxyServer expected_second; - bool expected_is_fallback; - } tests[] = { - {params()->proxies_for_http().front().proxy_server(), true, - params()->proxies_for_http().front().proxy_server(), - params()->proxies_for_http().at(1).proxy_server(), false}, - {params()->proxies_for_http().at(1).proxy_server(), true, - params()->proxies_for_http().at(1).proxy_server(), net::ProxyServer(), - true}, - }; - for (size_t i = 0; i < arraysize(tests); ++i) { - std::unique_ptr<TestDataReductionProxyParams> params( - new TestDataReductionProxyParams()); - DataReductionProxyTypeInfo proxy_type_info; - std::unique_ptr<DataReductionProxyConfig> config( - new DataReductionProxyConfig(task_runner(), net_log(), - std::move(params), configurator(), - event_creator())); - EXPECT_EQ( - tests[i].expected_result, - config->IsDataReductionProxy(tests[i].proxy_server, &proxy_type_info)) - << i; - EXPECT_EQ(tests[i].expected_first.is_valid(), - proxy_type_info.proxy_servers.size() >= 1 && - proxy_type_info.proxy_servers[0].is_valid()) - << i; - if (proxy_type_info.proxy_servers.size() >= 1 && - proxy_type_info.proxy_servers[0].is_valid()) { - EXPECT_EQ(tests[i].expected_first, proxy_type_info.proxy_servers[0]) << i; - } - EXPECT_EQ(tests[i].expected_second.is_valid(), - proxy_type_info.proxy_servers.size() >= 2 && - proxy_type_info.proxy_servers[1].is_valid()) - << i; - if (proxy_type_info.proxy_servers.size() >= 2 && - proxy_type_info.proxy_servers[1].is_valid()) { - EXPECT_EQ(tests[i].expected_second, proxy_type_info.proxy_servers[1]) - << i; - } +TEST_F(DataReductionProxyConfigTest, + FindConfiguredDataReductionProxyWithParams) { + std::unique_ptr<TestDataReductionProxyParams> params( + new TestDataReductionProxyParams()); - EXPECT_EQ(tests[i].expected_is_fallback, proxy_type_info.proxy_index != 0) - << i; + const std::vector<DataReductionProxyServer> expected_proxies = + params->proxies_for_http(); + ASSERT_LT(0U, expected_proxies.size()); + + DataReductionProxyConfig config(task_runner(), net_log(), std::move(params), + configurator(), event_creator()); + + for (size_t expected_proxy_index = 0U; + expected_proxy_index < expected_proxies.size(); ++expected_proxy_index) { + base::Optional<DataReductionProxyTypeInfo> proxy_type_info = + config.FindConfiguredDataReductionProxy( + expected_proxies[expected_proxy_index].proxy_server()); + + ASSERT_TRUE(proxy_type_info.has_value()); + EXPECT_EQ(expected_proxies, proxy_type_info->proxy_servers); + EXPECT_EQ(expected_proxy_index, proxy_type_info->proxy_index); } } -TEST_F(DataReductionProxyConfigTest, IsDataReductionProxyWithMutableConfig) { +TEST_F(DataReductionProxyConfigTest, + FindConfiguredDataReductionProxyWithMutableConfig) { std::vector<DataReductionProxyServer> proxies_for_http; proxies_for_http.push_back(DataReductionProxyServer( net::ProxyServer::FromURI("https://origin.net:443", @@ -840,65 +816,38 @@ const struct { DataReductionProxyServer proxy_server; bool expected_result; - std::vector<DataReductionProxyServer> expected_proxies; size_t expected_proxy_index; } tests[] = { - { - proxies_for_http[0], true, - std::vector<DataReductionProxyServer>(proxies_for_http.begin(), - proxies_for_http.end()), - 0, - }, - { - proxies_for_http[1], true, - std::vector<DataReductionProxyServer>(proxies_for_http.begin() + 1, - proxies_for_http.end()), - 1, - }, - { - proxies_for_http[2], true, - std::vector<DataReductionProxyServer>(proxies_for_http.begin() + 2, - proxies_for_http.end()), - 2, - }, - { - DataReductionProxyServer(net::ProxyServer(), - ProxyServer::UNSPECIFIED_TYPE), - false, std::vector<DataReductionProxyServer>(), 0, - }, - { - DataReductionProxyServer( - net::ProxyServer( - net::ProxyServer::SCHEME_HTTPS, - net::HostPortPair::FromString("otherorigin.net:443")), - ProxyServer::UNSPECIFIED_TYPE), - false, std::vector<DataReductionProxyServer>(), 0, - }, - { - // Verifies that when determining if a proxy is a valid data reduction - // proxy, only the host port pairs are compared. - DataReductionProxyServer( - net::ProxyServer::FromURI("origin.net:443", - net::ProxyServer::SCHEME_QUIC), - ProxyServer::UNSPECIFIED_TYPE), - true, std::vector<DataReductionProxyServer>(proxies_for_http.begin(), - proxies_for_http.end()), - 0, - }, - { - DataReductionProxyServer( - net::ProxyServer::FromURI("origin2.net:443", - net::ProxyServer::SCHEME_HTTPS), - ProxyServer::UNSPECIFIED_TYPE), - false, std::vector<DataReductionProxyServer>(), 0, - }, - { - DataReductionProxyServer( - net::ProxyServer::FromURI("origin2.net:443", - net::ProxyServer::SCHEME_QUIC), - ProxyServer::UNSPECIFIED_TYPE), - false, std::vector<DataReductionProxyServer>(), 0, - }, + {proxies_for_http[0], true, 0U}, + {proxies_for_http[1], true, 1U}, + {proxies_for_http[2], true, 2U}, + {DataReductionProxyServer(net::ProxyServer(), + ProxyServer::UNSPECIFIED_TYPE), + false, 0U}, + {DataReductionProxyServer(net::ProxyServer(net::ProxyServer::SCHEME_HTTPS, + net::HostPortPair::FromString( + "otherorigin.net:443")), + ProxyServer::UNSPECIFIED_TYPE), + false, 0U}, + + // Verifies that when determining if a proxy is a valid data reduction + // proxy, only the host port pairs are compared. + {DataReductionProxyServer( + net::ProxyServer::FromURI("origin.net:443", + net::ProxyServer::SCHEME_QUIC), + ProxyServer::UNSPECIFIED_TYPE), + true, 0U}, + + {DataReductionProxyServer( + net::ProxyServer::FromURI("origin2.net:443", + net::ProxyServer::SCHEME_HTTPS), + ProxyServer::UNSPECIFIED_TYPE), + false, 0U}, + {DataReductionProxyServer( + net::ProxyServer::FromURI("origin2.net:443", + net::ProxyServer::SCHEME_QUIC), + ProxyServer::UNSPECIFIED_TYPE), + false, 0U}, }; std::unique_ptr<DataReductionProxyMutableConfigValues> config_values = @@ -909,14 +858,15 @@ task_runner(), net_log(), std::move(config_values), configurator(), event_creator())); for (const auto& test : tests) { - DataReductionProxyTypeInfo proxy_type_info; - EXPECT_EQ(test.expected_result, - config->IsDataReductionProxy(test.proxy_server.proxy_server(), - &proxy_type_info)); - EXPECT_EQ(proxy_type_info.proxy_servers, - DataReductionProxyServer::ConvertToNetProxyServers( - test.expected_proxies)); - EXPECT_EQ(test.expected_proxy_index, proxy_type_info.proxy_index); + base::Optional<DataReductionProxyTypeInfo> proxy_type_info = + config->FindConfiguredDataReductionProxy( + test.proxy_server.proxy_server()); + EXPECT_EQ(test.expected_result, proxy_type_info.has_value()); + + if (proxy_type_info) { + EXPECT_EQ(proxies_for_http, proxy_type_info->proxy_servers); + EXPECT_EQ(test.expected_proxy_index, proxy_type_info->proxy_index); + } } } @@ -935,8 +885,8 @@ net::LOAD_MAIN_FRAME_DEPRECATED); std::unique_ptr<previews::TestPreviewsDecider> previews_decider = std::make_unique<previews::TestPreviewsDecider>(true); - EXPECT_FALSE(test_config()->ShouldAcceptServerPreview( - *request.get(), *previews_decider.get())); + EXPECT_FALSE( + test_config()->ShouldAcceptServerPreview(*request, *previews_decider)); } TEST_F(DataReductionProxyConfigTest, @@ -954,8 +904,8 @@ net::LOAD_MAIN_FRAME_DEPRECATED); std::unique_ptr<previews::TestPreviewsDecider> previews_decider = std::make_unique<previews::TestPreviewsDecider>(true); - EXPECT_FALSE(test_config()->ShouldAcceptServerPreview( - *request.get(), *previews_decider.get())); + EXPECT_FALSE( + test_config()->ShouldAcceptServerPreview(*request, *previews_decider)); } TEST_F(DataReductionProxyConfigTest, ShouldAcceptServerPreview) { @@ -979,14 +929,14 @@ std::make_unique<previews::TestPreviewsDecider>(true); // Verify true for no flags. - EXPECT_TRUE(test_config()->ShouldAcceptServerPreview( - *request.get(), *previews_decider.get())); + EXPECT_TRUE( + test_config()->ShouldAcceptServerPreview(*request, *previews_decider)); // Verify PreviewsDecider check. base::CommandLine::ForCurrentProcess()->InitFromArgv(0, nullptr); previews_decider = std::make_unique<previews::TestPreviewsDecider>(false); - EXPECT_FALSE(test_config()->ShouldAcceptServerPreview( - *request.get(), *previews_decider.get())); + EXPECT_FALSE( + test_config()->ShouldAcceptServerPreview(*request, *previews_decider)); histogram_tester.ExpectBucketCount( "DataReductionProxy.Protocol.NotAcceptingTransform", 1 /* NOT_ACCEPTING_TRANSFORM_BLACKLISTED */, 1);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc index cdaa80c..f03df0d 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
@@ -94,8 +94,7 @@ const std::string& expected_bypass_list) { test_context_->RunUntilIdle(); net::ProxyConfig::ProxyRules rules = - config_ - ->CreateProxyConfig(probe_url_config, *manager_.get(), http_proxies) + config_->CreateProxyConfig(probe_url_config, *manager_, http_proxies) .proxy_rules(); ASSERT_EQ(expected_rules_type, rules.type); if (net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME ==
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc index 826be5e..447b117 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
@@ -83,13 +83,12 @@ std::unique_ptr<net::URLRequest> fake_request(context->CreateRequest( GURL("http://www.google.com"), net::RequestPriority::IDLE, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS)); - DataReductionProxyData* data = - DataReductionProxyData::GetData(*fake_request.get()); + DataReductionProxyData* data = DataReductionProxyData::GetData(*fake_request); EXPECT_FALSE(data); data = DataReductionProxyData::GetDataAndCreateIfNecessary(fake_request.get()); EXPECT_TRUE(data); - data = DataReductionProxyData::GetData(*fake_request.get()); + data = DataReductionProxyData::GetData(*fake_request); EXPECT_TRUE(data); DataReductionProxyData* data2 = DataReductionProxyData::GetDataAndCreateIfNecessary(fake_request.get()); @@ -150,7 +149,7 @@ DataReductionProxyData::GetDataAndCreateIfNecessary(fake_request.get()); EXPECT_TRUE(data); DataReductionProxyData::ClearData(fake_request.get()); - data = DataReductionProxyData::GetData(*fake_request.get()); + data = DataReductionProxyData::GetData(*fake_request); EXPECT_FALSE(data); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc index 206b89a6..21a0b7b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -77,7 +77,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(result); DCHECK(result->is_empty() || result->is_direct() || - !config_->IsDataReductionProxy(result->proxy_server(), nullptr)); + !config_->FindConfiguredDataReductionProxy(result->proxy_server())); if (!params::IsIncludedInQuicFieldTrial()) RecordQuicProxyStatus(QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL); @@ -162,7 +162,7 @@ int net_error) { DCHECK(thread_checker_.CalledOnValidThread()); if (bad_proxy.is_valid() && - config_->IsDataReductionProxy(bad_proxy, nullptr)) { + config_->FindConfiguredDataReductionProxy(bad_proxy)) { event_creator_->AddProxyFallbackEvent(net_log_, bad_proxy.ToURI(), net_error); } @@ -187,7 +187,7 @@ net::ProxyServer resolved_proxy_server = result->proxy_server(); DCHECK(resolved_proxy_server.is_valid()); - DCHECK(config_->IsDataReductionProxy(resolved_proxy_server, nullptr)); + DCHECK(config_->FindConfiguredDataReductionProxy(resolved_proxy_server)); if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS() || url.SchemeIsCryptographic()) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc index 76e8d36b..795fde3 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -707,7 +707,7 @@ std::unique_ptr<net::URLRequest> request = FetchURLRequest(GURL("http://example.com/path/"), nullptr, - test.DrpResponseHeaders.c_str(), 1000); + test.DrpResponseHeaders, 1000); EXPECT_EQ(request->GetTotalReceivedBytes(), total_received_bytes() - baseline_received_bytes); @@ -777,9 +777,8 @@ int64_t baseline_received_bytes = total_received_bytes(); int64_t baseline_original_received_bytes = total_original_received_bytes(); - std::unique_ptr<net::URLRequest> request = - FetchURLRequest(GURL("http://example.com/path/"), nullptr, - test.DrpResponseHeaders.c_str(), 0); + std::unique_ptr<net::URLRequest> request = FetchURLRequest( + GURL("http://example.com/path/"), nullptr, test.DrpResponseHeaders, 0); EXPECT_EQ(request->GetTotalReceivedBytes(), total_received_bytes() - baseline_received_bytes);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc index 050f4c8..ac85b385 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -216,7 +216,7 @@ network_properties_manager_.get()); bypass_stats_->InitializeOnIOThread(); proxy_delegate_->InitializeOnIOThread(this); - if (config_client_.get()) + if (config_client_) config_client_->InitializeOnIOThread(url_request_context_getter_); if (ui_task_runner_->BelongsToCurrentThread()) { service_->SetIOData(weak_factory_.GetWeakPtr());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc index 7342956..a897573 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -114,7 +114,7 @@ // Check that the SimpleURLRequestContextGetter uses vanilla HTTP. net::URLRequestContext* request_context = - io_data->basic_url_request_context_getter_.get()->GetURLRequestContext(); + io_data->basic_url_request_context_getter_->GetURLRequestContext(); const net::HttpNetworkSession::Params* http_params = request_context->GetNetworkSessionParams(); EXPECT_FALSE(http_params->enable_http2);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc index edf466af..ee1d2e9d 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc
@@ -20,8 +20,8 @@ DataReductionProxyRequestType GetDataReductionProxyRequestType( const net::URLRequest& request, - const net::ProxyConfig& data_reduction_proxy_config, - const DataReductionProxyConfig& config) { + const net::ProxyConfig& proxy_config, + const DataReductionProxyConfig& data_reduction_proxy_config) { if (request.url().SchemeIs(url::kHttpsScheme)) return HTTPS; if (!request.url().SchemeIs(url::kHttpScheme)) { @@ -41,9 +41,10 @@ if ((request.load_flags() & net::LOAD_BYPASS_PROXY) || (request.proxy_server().is_valid() && !request.proxy_server().is_direct() && - !config.IsDataReductionProxy(request.proxy_server(), nullptr)) || - config.IsBypassedByDataReductionProxyLocalRules( - request, data_reduction_proxy_config)) { + !data_reduction_proxy_config.FindConfiguredDataReductionProxy( + request.proxy_server())) || + data_reduction_proxy_config.IsBypassedByDataReductionProxyLocalRules( + request, proxy_config)) { return SHORT_BYPASS; } @@ -53,8 +54,8 @@ } base::TimeDelta bypass_delay; - if (config.AreDataReductionProxiesBypassed( - request, data_reduction_proxy_config, &bypass_delay)) { + if (data_reduction_proxy_config.AreDataReductionProxiesBypassed( + request, proxy_config, &bypass_delay)) { if (bypass_delay > base::TimeDelta::FromSeconds(kLongBypassDelayInSeconds)) return LONG_BYPASS; return SHORT_BYPASS; @@ -68,7 +69,8 @@ // if they came through the Data Reduction Proxy. if (request.response_headers() && request.response_headers()->response_code() == net::HTTP_NOT_MODIFIED && - config.WasDataReductionProxyUsed(&request, nullptr)) { + data_reduction_proxy_config.FindConfiguredDataReductionProxy( + request.proxy_server())) { return VIA_DATA_REDUCTION_PROXY; }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h index 9c52af5..d06dd62 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h
@@ -47,8 +47,8 @@ // Returns DataReductionProxyRequestType for |request|. DataReductionProxyRequestType GetDataReductionProxyRequestType( const net::URLRequest& request, - const net::ProxyConfig& data_reduction_proxy_config, - const DataReductionProxyConfig& config); + const net::ProxyConfig& proxy_config, + const DataReductionProxyConfig& data_reduction_proxy_config); } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc index ddd898a4..092520bc 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc
@@ -4,8 +4,11 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h" +#include <algorithm> + #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" +#include "net/base/proxy_server.h" namespace data_reduction_proxy { @@ -34,15 +37,58 @@ return proxies_for_http_; } -void DataReductionProxyMutableConfigValues::UpdateValues( - const std::vector<DataReductionProxyServer>& proxies_for_http) { +base::Optional<DataReductionProxyTypeInfo> +DataReductionProxyMutableConfigValues::FindConfiguredDataReductionProxy( + const net::ProxyServer& proxy_server) const { DCHECK(thread_checker_.CalledOnValidThread()); - proxies_for_http_ = proxies_for_http; + + base::Optional<DataReductionProxyTypeInfo> info = + DataReductionProxyParams::FindConfiguredProxyInVector(proxies_for_http(), + proxy_server); + if (info) + return info; + + for (const auto& recent_proxies : recently_configured_proxy_lists_) { + base::Optional<DataReductionProxyTypeInfo> recent_info = + DataReductionProxyParams::FindConfiguredProxyInVector(recent_proxies, + proxy_server); + if (recent_info) + return recent_info; + } + return base::nullopt; +} + +void DataReductionProxyMutableConfigValues::UpdateValues( + const std::vector<DataReductionProxyServer>& new_proxies_for_http) { + DCHECK(thread_checker_.CalledOnValidThread()); + + std::vector<DataReductionProxyServer> previous_proxies = proxies_for_http(); + + proxies_for_http_.clear(); + std::remove_copy_if(new_proxies_for_http.begin(), new_proxies_for_http.end(), + std::back_inserter(proxies_for_http_), + [](const DataReductionProxyServer& proxy) { + return !proxy.proxy_server().is_valid() || + proxy.proxy_server().is_direct(); + }); + + if (previous_proxies.empty() || proxies_for_http() == previous_proxies) { + // There's no point in keeping track of an empty recent list of proxies or a + // list of proxies that's identical to the currently configured list. + return; + } + + // Push |previous_proxies| onto the front of the + // |recently_configured_proxy_lists_|. + std::move_backward(std::begin(recently_configured_proxy_lists_), + std::end(recently_configured_proxy_lists_) - 1, + std::end(recently_configured_proxy_lists_)); + recently_configured_proxy_lists_[0] = std::move(previous_proxies); } void DataReductionProxyMutableConfigValues::Invalidate() { DCHECK(thread_checker_.CalledOnValidThread()); - proxies_for_http_.clear(); + UpdateValues(std::vector<DataReductionProxyServer>()); } } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h index 145db2b..ec52878f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
@@ -8,10 +8,14 @@ #include <vector> #include "base/macros.h" +#include "base/optional.h" #include "base/threading/thread_checker.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h" -#include "net/base/proxy_server.h" -#include "url/gurl.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" + +namespace net { +class ProxyServer; +} namespace data_reduction_proxy { @@ -26,16 +30,17 @@ ~DataReductionProxyMutableConfigValues() override; // Updates |proxies_for_http_| with the provided values. - // Virtual for testing. - virtual void UpdateValues( - const std::vector<DataReductionProxyServer>& proxies_for_http); + void UpdateValues( + const std::vector<DataReductionProxyServer>& new_proxies_for_http); // Invalidates |this| by clearing the stored Data Reduction Proxy servers. void Invalidate(); - // Overrides of |DataReductionProxyConfigValues| + // Overrides of |DataReductionProxyConfigValues|. const std::vector<DataReductionProxyServer>& proxies_for_http() const override; + base::Optional<DataReductionProxyTypeInfo> FindConfiguredDataReductionProxy( + const net::ProxyServer& proxy_server) const override; private: std::vector<DataReductionProxyServer> proxies_for_http_; @@ -45,6 +50,16 @@ // ones specified from the Data Saver API. const bool use_override_proxies_for_http_; + // Keep track of some of the most recently configured proxy lists. This means + // that any requests that were in-progress to a Data Reduction Proxy when the + // list of proxies to use is changed can still be recognized as using a Data + // Reduction Proxy for the purposes of applying bypass logic and recording + // metrics. The number 2 is used because that way the proxy server used by an + // in-progress request can still be recognized if both the list of proxy + // servers to use changes and the proxy config gets invalidated before that + // request's response is processed. + std::vector<DataReductionProxyServer> recently_configured_proxy_lists_[2]; + // Enforce usage on the IO thread. base::ThreadChecker thread_checker_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc index bfea492..61b6ef8 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc
@@ -8,9 +8,11 @@ #include <vector> #include "base/command_line.h" +#include "base/optional.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "net/base/proxy_server.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,6 +21,15 @@ namespace { +void ExpectTypeInfo( + base::Optional<DataReductionProxyTypeInfo> type_info, + const std::vector<DataReductionProxyServer>& expected_proxy_servers, + size_t expected_proxy_index) { + ASSERT_TRUE(type_info); + EXPECT_EQ(expected_proxy_servers, type_info->proxy_servers); + EXPECT_EQ(expected_proxy_index, type_info->proxy_index); +} + class DataReductionProxyMutableConfigValuesTest : public testing::Test { public: DataReductionProxyMutableConfigValuesTest() {} @@ -54,12 +65,34 @@ proxies_for_http.push_back(DataReductionProxyServer( second_proxy_server, ProxyServer::UNSPECIFIED_TYPE)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + first_proxy_server)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + second_proxy_server)); + mutable_config_values()->UpdateValues(proxies_for_http); EXPECT_EQ(proxies_for_http, mutable_config_values()->proxies_for_http()); + // The configured proxies should be recognized as Data Reduction Proxies. + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + first_proxy_server), + proxies_for_http, 0U); + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + second_proxy_server), + proxies_for_http, 1U); + // Invalidation must clear out the list of proxies and their properties. mutable_config_values()->Invalidate(); EXPECT_TRUE(mutable_config_values()->proxies_for_http().empty()); + + // The previously configured proxies should still be recognized as Data + // Reduction Proxies, even though the config was invalidated. + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + first_proxy_server), + proxies_for_http, 0U); + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + second_proxy_server), + proxies_for_http, 1U); } // Tests if HTTP proxies are overridden when |kDataReductionProxyHttpProxies| @@ -70,18 +103,32 @@ "http://override-first.net;http://override-second.net"); Init(); - EXPECT_EQ(std::vector<DataReductionProxyServer>(), - mutable_config_values()->proxies_for_http()); - - std::vector<DataReductionProxyServer> proxies_for_http; + net::ProxyServer first_override_proxy_server = net::ProxyServer::FromURI( + "http://override-first.net", net::ProxyServer::SCHEME_HTTP); + net::ProxyServer second_override_proxy_server = net::ProxyServer::FromURI( + "http://override-second.net", net::ProxyServer::SCHEME_HTTP); net::ProxyServer first_proxy_server(net::ProxyServer::FromURI( "http://first.net", net::ProxyServer::SCHEME_HTTP)); - proxies_for_http.push_back( - DataReductionProxyServer(first_proxy_server, ProxyServer::CORE)); - net::ProxyServer second_proxy_server = net::ProxyServer::FromURI( "http://second.net", net::ProxyServer::SCHEME_HTTP); + + EXPECT_EQ(std::vector<DataReductionProxyServer>(), + mutable_config_values()->proxies_for_http()); + + // No proxy servers should be recognized as Data Reduction Proxies. + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + first_override_proxy_server)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + second_override_proxy_server)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + first_proxy_server)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + second_proxy_server)); + + std::vector<DataReductionProxyServer> proxies_for_http; + proxies_for_http.push_back( + DataReductionProxyServer(first_proxy_server, ProxyServer::CORE)); proxies_for_http.push_back(DataReductionProxyServer( second_proxy_server, ProxyServer::UNSPECIFIED_TYPE)); @@ -89,20 +136,48 @@ std::vector<DataReductionProxyServer> expected_override_proxies_for_http; expected_override_proxies_for_http.push_back(DataReductionProxyServer( - net::ProxyServer::FromURI("http://override-first.net", - net::ProxyServer::SCHEME_HTTP), - ProxyServer::UNSPECIFIED_TYPE)); + first_override_proxy_server, ProxyServer::UNSPECIFIED_TYPE)); expected_override_proxies_for_http.push_back(DataReductionProxyServer( - net::ProxyServer::FromURI("http://override-second.net", - net::ProxyServer::SCHEME_HTTP), - ProxyServer::UNSPECIFIED_TYPE)); + second_override_proxy_server, ProxyServer::UNSPECIFIED_TYPE)); EXPECT_EQ(expected_override_proxies_for_http, mutable_config_values()->proxies_for_http()); + // The overriding proxy servers should be recognized as Data Reduction + // Proxies. + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + first_override_proxy_server), + expected_override_proxies_for_http, 0U); + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + second_override_proxy_server), + expected_override_proxies_for_http, 1U); + + // The proxy servers that were overriden should not be recognized as Data + // Reduction Proxies. + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + first_proxy_server)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + second_proxy_server)); + // Invalidation must clear out the list of proxies and their properties. mutable_config_values()->Invalidate(); EXPECT_TRUE(mutable_config_values()->proxies_for_http().empty()); + + // The overriding proxy servers should be recognized as Data Reduction + // Proxies. + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + first_override_proxy_server), + expected_override_proxies_for_http, 0U); + ExpectTypeInfo(mutable_config_values()->FindConfiguredDataReductionProxy( + second_override_proxy_server), + expected_override_proxies_for_http, 1U); + + // The proxy servers that were overriden should not be recognized as Data + // Reduction Proxies. + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + first_proxy_server)); + EXPECT_FALSE(mutable_config_values()->FindConfiguredDataReductionProxy( + second_proxy_server)); } // Tests if HTTP proxies are overridden when |kDataReductionProxy| or
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc index 2aca3f16..da6a0a7eb 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -359,8 +359,8 @@ using_data_reduction_proxy = false; } else if (proxy_info.proxy_server().host_port_pair().IsEmpty()) { using_data_reduction_proxy = false; - } else if (!data_reduction_proxy_config_->IsDataReductionProxy( - proxy_info.proxy_server(), nullptr)) { + } else if (!data_reduction_proxy_config_->FindConfiguredDataReductionProxy( + proxy_info.proxy_server())) { using_data_reduction_proxy = false; } @@ -636,8 +636,8 @@ const net::ProxyRetryInfoMap& proxy_retry_info) const { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(proxy_info.is_empty() || proxy_info.is_direct() || - !data_reduction_proxy_config_->IsDataReductionProxy( - proxy_info.proxy_server(), nullptr)); + !data_reduction_proxy_config_->FindConfiguredDataReductionProxy( + proxy_info.proxy_server())); if (!util::EligibleForDataReductionProxy(proxy_info, request.url(), request.method())) { return false; @@ -658,8 +658,8 @@ // This method should be called only when the resolved proxy was a data // saver proxy. - DCHECK(data_reduction_proxy_config_->IsDataReductionProxy( - proxy_info.proxy_server(), nullptr)); + DCHECK(data_reduction_proxy_config_->FindConfiguredDataReductionProxy( + proxy_info.proxy_server())); DCHECK(request.url().is_valid()); DCHECK(!request.url().SchemeIsCryptographic()); DCHECK(request.url().SchemeIsHTTPOrHTTPS());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index 6f0ceea..1c30339 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -907,15 +907,15 @@ GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); fake_request->SetLoadFlags(net::LOAD_MAIN_FRAME_DEPRECATED); lofi_decider()->SetIsUsingLoFi(config()->ShouldAcceptServerPreview( - *fake_request.get(), test_previews_decider)); + *fake_request, test_previews_decider)); NotifyNetworkDelegate(fake_request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); VerifyHeaders(is_data_reduction_proxy_enabled[i], true, headers); - VerifyDataReductionProxyData( - *fake_request, is_data_reduction_proxy_enabled[i], - config()->ShouldAcceptServerPreview(*fake_request.get(), - test_previews_decider)); + VerifyDataReductionProxyData(*fake_request, + is_data_reduction_proxy_enabled[i], + config()->ShouldAcceptServerPreview( + *fake_request, test_previews_decider)); } { @@ -990,13 +990,13 @@ GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); fake_request->SetLoadFlags(net::LOAD_MAIN_FRAME_DEPRECATED); lofi_decider()->SetIsUsingLoFi(config()->ShouldAcceptServerPreview( - *fake_request.get(), test_previews_decider)); + *fake_request, test_previews_decider)); NotifyNetworkDelegate(fake_request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - VerifyDataReductionProxyData( - *fake_request, is_data_reduction_proxy_enabled[i], - config()->ShouldAcceptServerPreview(*fake_request.get(), - test_previews_decider)); + VerifyDataReductionProxyData(*fake_request, + is_data_reduction_proxy_enabled[i], + config()->ShouldAcceptServerPreview( + *fake_request, test_previews_decider)); } } } @@ -1060,8 +1060,7 @@ &headers); network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - DataReductionProxyData* data = - DataReductionProxyData::GetData(*request.get()); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); if (!test.used_data_reduction_proxy) { EXPECT_FALSE(data); } else { @@ -1120,8 +1119,7 @@ net::ProxyRetryInfoMap proxy_retry_info; network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - DataReductionProxyData* data = - DataReductionProxyData::GetData(*request.get()); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); if (!test.data_reduction_proxy_enabled || !test.used_direct) { EXPECT_FALSE(data); } else { @@ -1166,8 +1164,7 @@ network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers_original); - DataReductionProxyData* data = - DataReductionProxyData::GetData(*request.get()); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); EXPECT_TRUE(data); EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE, @@ -1182,7 +1179,7 @@ // Simulate a redirect even though the same URL is used. Should clear // DataReductionProxyData. network_delegate()->NotifyBeforeRedirect(request.get(), GURL(kTestURL)); - data = DataReductionProxyData::GetData(*request.get()); + data = DataReductionProxyData::GetData(*request); EXPECT_FALSE(data && data->used_data_reduction_proxy()); // Call NotifyBeforeSendHeaders again with different proxy info to check that @@ -1199,7 +1196,7 @@ network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers_redirect); - data = DataReductionProxyData::GetData(*request.get()); + data = DataReductionProxyData::GetData(*request); EXPECT_FALSE(data); } @@ -1443,8 +1440,8 @@ ssl_socket_data_provider()); } - std::string via_header = ""; - std::string ocl_header = ""; + std::string via_header; + std::string ocl_header; if (test.proxy_config == USE_INSECURE_PROXY) { via_header = "Via: 1.1 Chrome-Compression-Proxy\r\n"; @@ -1811,8 +1808,7 @@ &headers); network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - DataReductionProxyData* data = - DataReductionProxyData::GetData(*request.get()); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); EXPECT_TRUE(data_reduction_proxy_info.is_http()); EXPECT_EQ(++page_id, data->page_id().value()); @@ -1828,14 +1824,14 @@ &headers); network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - data = DataReductionProxyData::GetData(*request.get()); + data = DataReductionProxyData::GetData(*request); EXPECT_EQ(++page_id, data->page_id().value()); // Verify that redirects are the same page ID. network_delegate()->NotifyBeforeRedirect(request.get(), GURL(kTestURL)); network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - data = DataReductionProxyData::GetData(*request.get()); + data = DataReductionProxyData::GetData(*request); EXPECT_EQ(page_id, data->page_id().value()); network_delegate()->NotifyBeforeRedirect(request.get(), GURL(kTestURL)); @@ -1844,7 +1840,7 @@ page_id = io_data()->request_options()->GeneratePageId(); network_delegate()->NotifyBeforeSendHeaders( request.get(), data_reduction_proxy_info, proxy_retry_info, &headers); - data = DataReductionProxyData::GetData(*request.get()); + data = DataReductionProxyData::GetData(*request); EXPECT_EQ(++page_id, data->page_id().value()); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc index 1b9ea074..96f4e58 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -51,7 +51,7 @@ DataReductionProxySettings::DataReductionProxySettings() : unreachable_(false), deferred_initialization_(false), - data_reduction_proxy_enabled_pref_name_(), + prefs_(nullptr), config_(nullptr), clock_(base::DefaultClock::GetInstance()) {} @@ -78,7 +78,7 @@ DCHECK(prefs); DCHECK(io_data); DCHECK(io_data->config()); - DCHECK(data_reduction_proxy_service.get()); + DCHECK(data_reduction_proxy_service); data_reduction_proxy_enabled_pref_name_ = data_reduction_proxy_enabled_pref_name; prefs_ = prefs;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc index aced436..0945cd2 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc
@@ -32,9 +32,7 @@ namespace data_reduction_proxy { -DataReductionProxySettingsTestBase::DataReductionProxySettingsTestBase() - : testing::Test() { -} +DataReductionProxySettingsTestBase::DataReductionProxySettingsTestBase() {} DataReductionProxySettingsTestBase::~DataReductionProxySettingsTestBase() {}
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc index 32df0a9..4da41fd 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -611,7 +611,7 @@ void DataReductionProxyTestContext::DestroySettings() { // Force destruction of |DBDataOwner|, which lives on DB task runner and is // indirectly owned by |settings_|. - if (settings_.get()) { + if (settings_) { settings_.reset(); storage_delegate_->SetStorageDelegate(nullptr); RunUntilIdle();
diff --git a/components/data_reduction_proxy/core/browser/db_data_owner.cc b/components/data_reduction_proxy/core/browser/db_data_owner.cc index 1273720..dbe78df0 100644 --- a/components/data_reduction_proxy/core/browser/db_data_owner.cc +++ b/components/data_reduction_proxy/core/browser/db_data_owner.cc
@@ -47,7 +47,7 @@ std::unique_ptr<DataUsageBucket> current) { DCHECK(sequence_checker_.CalledOnValidSequence()); - data_usage_->StoreCurrentDataUsageBucket(*current.get()); + data_usage_->StoreCurrentDataUsageBucket(*current); } void DBDataOwner::DeleteHistoricalDataUsage() {
diff --git a/components/data_reduction_proxy/core/common/BUILD.gn b/components/data_reduction_proxy/core/common/BUILD.gn index d793083..97bc64a9cb 100644 --- a/components/data_reduction_proxy/core/common/BUILD.gn +++ b/components/data_reduction_proxy/core/common/BUILD.gn
@@ -31,6 +31,7 @@ "data_reduction_proxy_server.h", "data_reduction_proxy_switches.cc", "data_reduction_proxy_switches.h", + "data_reduction_proxy_type_info.h", "lofi_decider.h", "lofi_ui_service.h", "resource_type_provider.h",
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h index 320b6fe..023d8c8 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h
@@ -7,6 +7,13 @@ #include <vector> +#include "base/optional.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" + +namespace net { +class ProxyServer; +} + namespace data_reduction_proxy { class DataReductionProxyServer; @@ -20,6 +27,20 @@ // included. virtual const std::vector<DataReductionProxyServer>& proxies_for_http() const = 0; + + // Determines if the given |proxy_server| matches a currently or recent + // previously configured Data Reduction Proxy server, returning information + // about where that proxy is in the ordered list of proxies to use. It's up to + // the implementation to determine what counts as a recent previously + // configured Data Reduction Proxy server, but the idea is to be able to + // recognize proxies from requests that use the currently configured + // |proxies_for_http()| as well as recognize proxies from requests that are + // in-progress when the list of proxy servers to use changes. If + // |proxy_server| matches multiple proxies, then the most recent and highest + // precedence result is returned. + virtual base::Optional<DataReductionProxyTypeInfo> + FindConfiguredDataReductionProxy( + const net::ProxyServer& proxy_server) const = 0; }; } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc index e257a700..00ec92cd 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
@@ -269,7 +269,7 @@ } std::string json; - base::JSONWriter::Write(*last_bypass.get(), &json); + base::JSONWriter::Write(*last_bypass, &json); return json; }
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc index aede1168..8f822f3 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc
@@ -284,7 +284,7 @@ bypass_event->Set("params", std::move(bypass_params)); std::string sanitized_output; - base::JSONWriter::Write(*sanitized_event.get(), &sanitized_output); + base::JSONWriter::Write(*sanitized_event, &sanitized_output); event_store()->AddAndSetLastBypassEvent(std::move(bypass_event), 0); EXPECT_EQ(sanitized_output, event_store()->SanitizedLastBypassEvent()); } @@ -323,7 +323,7 @@ bypass_event->Set("params", std::move(bypass_params)); std::string sanitized_output; - base::JSONWriter::Write(*sanitized_event.get(), &sanitized_output); + base::JSONWriter::Write(*sanitized_event, &sanitized_output); event_store()->AddAndSetLastBypassEvent(std::move(bypass_event), 0); EXPECT_EQ(sanitized_output, event_store()->SanitizedLastBypassEvent()); }
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc index 1e3fd9a..97afc0a4 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -4,6 +4,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include <algorithm> #include <map> #include <string> #include <vector> @@ -18,6 +19,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/variations/variations_associated_data.h" +#include "net/base/host_port_pair.h" #include "net/base/proxy_server.h" #include "net/http/http_status_code.h" #include "url/url_constants.h" @@ -329,14 +331,18 @@ std::string proxy_overrides = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kDataReductionProxyHttpProxies); - std::vector<std::string> proxy_override_values = base::SplitString( - proxy_overrides, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - for (const std::string& proxy_override : proxy_override_values) { + + for (const auto& proxy_override : + base::SplitStringPiece(proxy_overrides, ";", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + net::ProxyServer proxy_server = net::ProxyServer::FromURI( + proxy_override, net::ProxyServer::SCHEME_HTTP); + DCHECK(proxy_server.is_valid()); + DCHECK(!proxy_server.is_direct()); + // Overriding proxies have type UNSPECIFIED_TYPE. override_proxies_for_http->push_back(DataReductionProxyServer( - net::ProxyServer::FromURI(proxy_override, - net::ProxyServer::SCHEME_HTTP), - ProxyServer::UNSPECIFIED_TYPE)); + std::move(proxy_server), ProxyServer::UNSPECIFIED_TYPE)); } return true; @@ -345,6 +351,7 @@ std::string origin = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kDataReductionProxy); + std::string fallback_origin = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kDataReductionProxyFallback); @@ -353,17 +360,23 @@ return false; override_proxies_for_http->clear(); + // Overriding proxies have type UNSPECIFIED_TYPE. if (!origin.empty()) { + net::ProxyServer primary_proxy = + net::ProxyServer::FromURI(origin, net::ProxyServer::SCHEME_HTTP); + DCHECK(primary_proxy.is_valid()); + DCHECK(!primary_proxy.is_direct()); override_proxies_for_http->push_back(DataReductionProxyServer( - net::ProxyServer::FromURI(origin, net::ProxyServer::SCHEME_HTTP), - ProxyServer::UNSPECIFIED_TYPE)); + std::move(primary_proxy), ProxyServer::UNSPECIFIED_TYPE)); } if (!fallback_origin.empty()) { + net::ProxyServer fallback_proxy = net::ProxyServer::FromURI( + fallback_origin, net::ProxyServer::SCHEME_HTTP); + DCHECK(fallback_proxy.is_valid()); + DCHECK(!fallback_proxy.is_direct()); override_proxies_for_http->push_back(DataReductionProxyServer( - net::ProxyServer::FromURI(fallback_origin, - net::ProxyServer::SCHEME_HTTP), - ProxyServer::UNSPECIFIED_TYPE)); + std::move(fallback_proxy), ProxyServer::UNSPECIFIED_TYPE)); } return true; @@ -385,13 +398,6 @@ } // namespace params -DataReductionProxyTypeInfo::DataReductionProxyTypeInfo() : proxy_index(0) {} - -DataReductionProxyTypeInfo::DataReductionProxyTypeInfo( - const DataReductionProxyTypeInfo& other) = default; - -DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo() {} - DataReductionProxyParams::DataReductionProxyParams() { bool use_override_proxies_for_http = params::GetOverrideProxiesForHttpFromCommandLine(&proxies_for_http_); @@ -407,12 +413,24 @@ net::ProxyServer::SCHEME_HTTP), ProxyServer::CORE)); } + + DCHECK(std::all_of(proxies_for_http_.begin(), proxies_for_http_.end(), + [](const DataReductionProxyServer& proxy) { + return proxy.proxy_server().is_valid() && + !proxy.proxy_server().is_direct(); + })); } DataReductionProxyParams::~DataReductionProxyParams() {} void DataReductionProxyParams::SetProxiesForHttpForTesting( const std::vector<DataReductionProxyServer>& proxies_for_http) { + DCHECK(std::all_of(proxies_for_http.begin(), proxies_for_http.end(), + [](const DataReductionProxyServer& proxy) { + return proxy.proxy_server().is_valid() && + !proxy.proxy_server().is_direct(); + })); + proxies_for_http_ = proxies_for_http; } @@ -421,4 +439,38 @@ return proxies_for_http_; } +base::Optional<DataReductionProxyTypeInfo> +DataReductionProxyParams::FindConfiguredDataReductionProxy( + const net::ProxyServer& proxy_server) const { + return FindConfiguredProxyInVector(proxies_for_http(), proxy_server); +} + +// static +base::Optional<DataReductionProxyTypeInfo> +DataReductionProxyParams::FindConfiguredProxyInVector( + const std::vector<DataReductionProxyServer>& proxies, + const net::ProxyServer& proxy_server) { + if (!proxy_server.is_valid() || proxy_server.is_direct()) + return base::nullopt; + + // Only compare the host port pair of the |proxy_server| since the proxy + // scheme of the stored data reduction proxy may be different than the proxy + // scheme of |proxy_server|. This may happen even when the |proxy_server| is a + // valid data reduction proxy. As an example, the stored data reduction proxy + // may have a proxy scheme of HTTPS while |proxy_server| may have QUIC as the + // proxy scheme. + const net::HostPortPair& host_port_pair = proxy_server.host_port_pair(); + auto it = std::find_if( + proxies.begin(), proxies.end(), + [&host_port_pair](const DataReductionProxyServer& proxy) { + return proxy.proxy_server().host_port_pair().Equals(host_port_pair); + }); + + if (it == proxies.end()) + return base::nullopt; + + return DataReductionProxyTypeInfo(proxies, + static_cast<size_t>(it - proxies.begin())); +} + } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h index 8053a881..eb43fec 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -10,8 +10,10 @@ #include <vector> #include "base/macros.h" +#include "base/optional.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "url/gurl.h" namespace net { @@ -147,17 +149,6 @@ } // namespace params -// Contains information about a given proxy server. |proxies_for_http| contains -// the configured data reduction proxy servers. |proxy_index| notes the index -// of the data reduction proxy used in the list of all data reduction proxies. -struct DataReductionProxyTypeInfo { - DataReductionProxyTypeInfo(); - DataReductionProxyTypeInfo(const DataReductionProxyTypeInfo& other); - ~DataReductionProxyTypeInfo(); - std::vector<net::ProxyServer> proxy_servers; - size_t proxy_index; -}; - // Provides initialization parameters. Proxy origins, and the secure proxy // check url are are taken from flags if available and from preprocessor // constants otherwise. The DataReductionProxySettings class and others use this @@ -178,6 +169,17 @@ const std::vector<DataReductionProxyServer>& proxies_for_http() const override; + // Finds the first proxy in |proxies_for_http()| that matches |proxy_server| + // if any exist. + base::Optional<DataReductionProxyTypeInfo> FindConfiguredDataReductionProxy( + const net::ProxyServer& proxy_server) const override; + + // Helper function to locate |proxy_server| in |proxies| if it exists. This + // function is exposed publicly so that DataReductionProxyParams can use it. + static base::Optional<DataReductionProxyTypeInfo> FindConfiguredProxyInVector( + const std::vector<DataReductionProxyServer>& proxies, + const net::ProxyServer& proxy_server); + private: std::vector<DataReductionProxyServer> proxies_for_http_;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc index e79393a..b99579f4 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc
@@ -9,7 +9,7 @@ namespace data_reduction_proxy { TestDataReductionProxyParams::TestDataReductionProxyParams() - : DataReductionProxyParams(), override_non_secure_proxies_(false) { + : override_non_secure_proxies_(false) { proxies_for_http_.push_back(DataReductionProxyServer( net::ProxyServer::FromURI("origin.net:80", net::ProxyServer::SCHEME_HTTP), ProxyServer::CORE));
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc index a6e181b..e49239c8 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
@@ -13,11 +13,13 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/metrics/field_trial.h" +#include "base/optional.h" #include "base/test/scoped_feature_list.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "components/variations/variations_associated_data.h" #include "net/base/proxy_server.h" @@ -30,27 +32,8 @@ #endif namespace data_reduction_proxy { -class DataReductionProxyParamsTest : public testing::Test { - public: - void CheckValues(const TestDataReductionProxyParams& params, - const std::string& expected_origin, - const std::string& expected_fallback_origin) { - std::vector<net::ProxyServer> expected_proxies; - if (!expected_origin.empty()) { - expected_proxies.push_back(net::ProxyServer::FromURI( - expected_origin, net::ProxyServer::SCHEME_HTTP)); - } - if (!expected_fallback_origin.empty()) { - expected_proxies.push_back(net::ProxyServer::FromURI( - expected_fallback_origin, net::ProxyServer::SCHEME_HTTP)); - } - - EXPECT_EQ(expected_proxies, - DataReductionProxyServer::ConvertToNetProxyServers( - params.proxies_for_http())); - } -}; +class DataReductionProxyParamsTest : public testing::Test {}; TEST_F(DataReductionProxyParamsTest, EverythingDefined) { TestDataReductionProxyParams params; @@ -67,6 +50,24 @@ ProxyServer::CORE)); EXPECT_EQ(expected_proxies, params.proxies_for_http()); + + EXPECT_FALSE( + params.FindConfiguredDataReductionProxy(net::ProxyServer::FromURI( + "unrelated.proxy.net:80", net::ProxyServer::SCHEME_HTTP))); + + base::Optional<DataReductionProxyTypeInfo> first_info = + params.FindConfiguredDataReductionProxy( + expected_proxies[0].proxy_server()); + ASSERT_TRUE(first_info); + EXPECT_EQ(expected_proxies, first_info->proxy_servers); + EXPECT_EQ(0U, first_info->proxy_index); + + base::Optional<DataReductionProxyTypeInfo> second_info = + params.FindConfiguredDataReductionProxy( + expected_proxies[1].proxy_server()); + ASSERT_TRUE(second_info); + EXPECT_EQ(expected_proxies, second_info->proxy_servers); + EXPECT_EQ(1U, second_info->proxy_index); } TEST_F(DataReductionProxyParamsTest, Flags) { @@ -75,7 +76,40 @@ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kDataReductionProxyFallback, "http://ovveride-2.com/"); TestDataReductionProxyParams params; - CheckValues(params, "http://ovveride-1.com/", "http://ovveride-2.com/"); + + std::vector<DataReductionProxyServer> expected_proxies; + expected_proxies.push_back(DataReductionProxyServer( + net::ProxyServer::FromURI("http://ovveride-1.com/", + net::ProxyServer::SCHEME_HTTP), + ProxyServer::UNSPECIFIED_TYPE)); + expected_proxies.push_back(DataReductionProxyServer( + net::ProxyServer::FromURI("http://ovveride-2.com/", + net::ProxyServer::SCHEME_HTTP), + ProxyServer::UNSPECIFIED_TYPE)); + + EXPECT_EQ(expected_proxies, params.proxies_for_http()); + + // The default proxies shouldn't be recognized as Data Reduction Proxies. + EXPECT_FALSE( + params.FindConfiguredDataReductionProxy(net::ProxyServer::FromURI( + "https://proxy.googlezip.net:443", net::ProxyServer::SCHEME_HTTP))); + EXPECT_FALSE( + params.FindConfiguredDataReductionProxy(net::ProxyServer::FromURI( + "compress.googlezip.net:80", net::ProxyServer::SCHEME_HTTP))); + + base::Optional<DataReductionProxyTypeInfo> first_info = + params.FindConfiguredDataReductionProxy( + expected_proxies[0].proxy_server()); + ASSERT_TRUE(first_info); + EXPECT_EQ(expected_proxies, first_info->proxy_servers); + EXPECT_EQ(0U, first_info->proxy_index); + + base::Optional<DataReductionProxyTypeInfo> second_info = + params.FindConfiguredDataReductionProxy( + expected_proxies[1].proxy_server()); + ASSERT_TRUE(second_info); + EXPECT_EQ(expected_proxies, second_info->proxy_servers); + EXPECT_EQ(1U, second_info->proxy_index); } TEST_F(DataReductionProxyParamsTest, IsClientConfigEnabled) {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h new file mode 100644 index 0000000..1137ee0 --- /dev/null +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h
@@ -0,0 +1,36 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_TYPE_INFO_H_ +#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_TYPE_INFO_H_ + +#include <stddef.h> + +#include <vector> + +namespace data_reduction_proxy { + +class DataReductionProxyServer; + +// Contains information about a given proxy server. +struct DataReductionProxyTypeInfo { + DataReductionProxyTypeInfo( + const std::vector<DataReductionProxyServer>& proxy_servers, + size_t proxy_index) + : proxy_servers(proxy_servers), proxy_index(proxy_index) {} + + // The full configured list of proxy servers that includes the target proxy + // server. Since this is held onto as a const reference, the caller needs to + // ensure that it doesn't try to access |proxy_servers| if the list of + // configured proxies has changed since this DataReductionProxyTypeInfo was + // created. + const std::vector<DataReductionProxyServer>& proxy_servers; + + // The index of this proxy in |proxy_servers|. + size_t proxy_index; +}; + +} // namespace data_reduction_proxy + +#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_TYPE_INFO_H_
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc index c4e98cee..2cd5e0e5 100644 --- a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc +++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
@@ -167,7 +167,7 @@ // Search free lists for suitable span. std::unique_ptr<DiscardableSharedMemoryHeap::Span> free_span = heap_->SearchFreeLists(pages, slack); - if (!free_span.get()) + if (!free_span) break; // Attempt to lock |free_span|. Delete span and search free lists again
diff --git a/components/dom_distiller/content/browser/dom_distiller_viewer_source_unittest.cc b/components/dom_distiller/content/browser/dom_distiller_viewer_source_unittest.cc index df1fa73..5238069e 100644 --- a/components/dom_distiller/content/browser/dom_distiller_viewer_source_unittest.cc +++ b/components/dom_distiller/content/browser/dom_distiller_viewer_source_unittest.cc
@@ -22,9 +22,8 @@ }; TEST_F(DomDistillerViewerSourceTest, TestMimeType) { - EXPECT_EQ("text/css", source_.get()->GetMimeType(kViewerCssPath)); - EXPECT_EQ("text/html", source_.get()->GetMimeType("anythingelse")); - + EXPECT_EQ("text/css", source_->GetMimeType(kViewerCssPath)); + EXPECT_EQ("text/html", source_->GetMimeType("anythingelse")); } } // namespace dom_distiller
diff --git a/components/dom_distiller/core/distiller.cc b/components/dom_distiller/core/distiller.cc index f3ebbd8f6..e741731 100644 --- a/components/dom_distiller/core/distiller.cc +++ b/components/dom_distiller/core/distiller.cc
@@ -159,7 +159,7 @@ } } - DCHECK(distiller_result.get()); + DCHECK(distiller_result); DistilledPageData* page_data = GetPageAtIndex(started_pages_index_[page_num]); page_data->distilled_page_proto = @@ -311,7 +311,7 @@ const std::string& response) { DCHECK(started_pages_index_.find(page_num) != started_pages_index_.end()); DistilledPageData* page_data = GetPageAtIndex(started_pages_index_[page_num]); - DCHECK(page_data->distilled_page_proto.get()); + DCHECK(page_data->distilled_page_proto); DCHECK(url_fetcher); auto fetcher_it = std::find_if( page_data->image_fetchers_.begin(), page_data->image_fetchers_.end(),
diff --git a/components/dom_distiller/core/dom_distiller_request_view_base_unittest.cc b/components/dom_distiller/core/dom_distiller_request_view_base_unittest.cc index 102c2d5..f7d8dd9a1 100644 --- a/components/dom_distiller/core/dom_distiller_request_view_base_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_request_view_base_unittest.cc
@@ -194,7 +194,7 @@ std::unique_ptr<ArticleDistillationUpdate> article_update( new ArticleDistillationUpdate(pages, false, false)); - handle.OnArticleUpdated(*article_update.get()); + handle.OnArticleUpdated(*article_update); EXPECT_THAT(handle.GetJavaScriptBuffer(), HasSubstr(no_content)); EXPECT_THAT(handle.GetJavaScriptBuffer(), Not(HasSubstr(valid_content))); @@ -220,7 +220,7 @@ std::unique_ptr<ArticleDistillationUpdate> article_update( new ArticleDistillationUpdate(pages, true, false)); - handle.OnArticleUpdated(*article_update.get()); + handle.OnArticleUpdated(*article_update); EXPECT_THAT(handle.GetJavaScriptBuffer(), HasSubstr(show_loader)); }
diff --git a/components/dom_distiller/core/viewer_unittest.cc b/components/dom_distiller/core/viewer_unittest.cc index d064704d..e7bfd5a 100644 --- a/components/dom_distiller/core/viewer_unittest.cc +++ b/components/dom_distiller/core/viewer_unittest.cc
@@ -92,9 +92,9 @@ std::unique_ptr<FakeViewRequestDelegate> view_request_delegate( new FakeViewRequestDelegate()); ViewerHandle* viewer_handle(new ViewerHandle(ViewerHandle::CancelCallback())); - EXPECT_CALL(*service_.get(), ViewUrlImpl()) + EXPECT_CALL(*service_, ViewUrlImpl()) .WillOnce(testing::Return(viewer_handle)); - EXPECT_CALL(*service_.get(), ViewEntryImpl()).Times(0); + EXPECT_CALL(*service_, ViewEntryImpl()).Times(0); CreateViewRequest( std::string("?") + kUrlKey + "=http%3A%2F%2Fwww.example.com%2F", view_request_delegate.get()); @@ -104,9 +104,9 @@ std::unique_ptr<FakeViewRequestDelegate> view_request_delegate( new FakeViewRequestDelegate()); ViewerHandle* viewer_handle(new ViewerHandle(ViewerHandle::CancelCallback())); - EXPECT_CALL(*service_.get(), ViewEntryImpl()) + EXPECT_CALL(*service_, ViewEntryImpl()) .WillOnce(testing::Return(viewer_handle)); - EXPECT_CALL(*service_.get(), ViewUrlImpl()).Times(0); + EXPECT_CALL(*service_, ViewUrlImpl()).Times(0); CreateViewRequest(std::string("?") + kEntryIdKey + "=abc-def", view_request_delegate.get()); } @@ -114,8 +114,8 @@ TEST_F(DomDistillerViewerTest, TestCreatingInvalidViewRequest) { std::unique_ptr<FakeViewRequestDelegate> view_request_delegate( new FakeViewRequestDelegate()); - EXPECT_CALL(*service_.get(), ViewEntryImpl()).Times(0); - EXPECT_CALL(*service_.get(), ViewUrlImpl()).Times(0); + EXPECT_CALL(*service_, ViewEntryImpl()).Times(0); + EXPECT_CALL(*service_, ViewUrlImpl()).Times(0); // Specify none of the required query parameters. CreateViewRequest("?foo=bar", view_request_delegate.get()); // Specify both of the required query parameters.
diff --git a/components/dom_distiller_strings_grdp/OWNERS b/components/dom_distiller_strings_grdp/OWNERS new file mode 100644 index 0000000..9db3893 --- /dev/null +++ b/components/dom_distiller_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/dom_distiller/OWNERS
diff --git a/components/dom_distiller_strings_grdp/README.md b/components/dom_distiller_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/dom_distiller_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/domain_reliability/header.cc b/components/domain_reliability/header.cc index 0d2136d..cefcd60 100644 --- a/components/domain_reliability/header.cc +++ b/components/domain_reliability/header.cc
@@ -278,7 +278,7 @@ } std::string DomainReliabilityHeader::ToString() const { - std::string string = ""; + std::string string; int64_t max_age_s = max_age_.InSeconds(); if (config_->collectors.empty()) { @@ -314,7 +314,7 @@ base::TimeDelta max_age) : status_(status), config_(std::move(config)), max_age_(max_age) { DCHECK_EQ(PARSE_SET_CONFIG, status_); - DCHECK(config_.get()); + DCHECK(config_); DCHECK_NE(0, max_age_.InMicroseconds()); }
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc index a5cf89e8..64cf9b1 100644 --- a/components/domain_reliability/monitor.cc +++ b/components/domain_reliability/monitor.cc
@@ -336,7 +336,7 @@ return; int response_code; - if (request.response_info.headers.get()) + if (request.response_info.headers) response_code = request.response_info.headers->response_code(); else response_code = -1; @@ -394,7 +394,7 @@ void DomainReliabilityMonitor::MaybeHandleHeader( const RequestInfo& request) { - if (!request.response_info.headers.get()) + if (!request.response_info.headers) return; size_t iter = 0;
diff --git a/components/domain_reliability/service.cc b/components/domain_reliability/service.cc index ed369b8..3efe542e 100644 --- a/components/domain_reliability/service.cc +++ b/components/domain_reliability/service.cc
@@ -65,7 +65,7 @@ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> network_task_runner) override { - DCHECK(!network_task_runner_.get()); + DCHECK(!network_task_runner_); std::unique_ptr<DomainReliabilityMonitor> monitor( new DomainReliabilityMonitor( @@ -86,7 +86,7 @@ DomainReliabilityClearMode clear_mode, const base::Callback<bool(const GURL&)>& origin_filter, const base::Closure& callback) override { - DCHECK(network_task_runner_.get()); + DCHECK(network_task_runner_); network_task_runner_->PostTaskAndReply( FROM_HERE, base::Bind(&DomainReliabilityMonitor::ClearBrowsingData, @@ -96,7 +96,7 @@ void GetWebUIData(const base::Callback<void(std::unique_ptr<base::Value>)>& callback) const override { - DCHECK(network_task_runner_.get()); + DCHECK(network_task_runner_); PostTaskAndReplyWithResult( network_task_runner_.get(), @@ -106,7 +106,7 @@ } void SetDiscardUploadsForTesting(bool discard_uploads) override { - DCHECK(network_task_runner_.get()); + DCHECK(network_task_runner_); network_task_runner_->PostTask( FROM_HERE, @@ -117,7 +117,7 @@ void AddContextForTesting( std::unique_ptr<const DomainReliabilityConfig> config) override { - DCHECK(network_task_runner_.get()); + DCHECK(network_task_runner_); network_task_runner_->PostTask( FROM_HERE, base::BindOnce(&AddContextForTestingOnNetworkTaskRunner, @@ -125,7 +125,7 @@ } void ForceUploadsForTesting() override { - DCHECK(network_task_runner_.get()); + DCHECK(network_task_runner_); network_task_runner_->PostTask( FROM_HERE,
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc index 6b2f626..f0d9a07 100644 --- a/components/download/content/internal/download_driver_impl.cc +++ b/components/download/content/internal/download_driver_impl.cc
@@ -84,7 +84,7 @@ : item->GetFullPath(); entry.completion_time = item->GetEndTime(); entry.response_headers = item->GetResponseHeaders(); - if (entry.response_headers.get()) { + if (entry.response_headers) { entry.can_resume = entry.response_headers->HasHeaderValue("Accept-Ranges", "bytes") || (entry.response_headers->HasHeader("Content-Range") &&
diff --git a/components/download/content/public/all_download_item_notifier_unittest.cc b/components/download/content/public/all_download_item_notifier_unittest.cc index 5fc8e582..b893c8a 100644 --- a/components/download/content/public/all_download_item_notifier_unittest.cc +++ b/components/download/content/public/all_download_item_notifier_unittest.cc
@@ -42,7 +42,7 @@ ~AllDownloadItemNotifierTest() override {} - content::MockDownloadManager& manager() { return *download_manager_.get(); } + content::MockDownloadManager& manager() { return *download_manager_; } download::MockDownloadItem& item() { return item_; } @@ -57,7 +57,7 @@ MockNotifierObserver& observer() { return observer_; } void SetNotifier() { - EXPECT_CALL(*download_manager_.get(), AddObserver(_)); + EXPECT_CALL(*download_manager_, AddObserver(_)); notifier_.reset( new AllDownloadItemNotifier(download_manager_.get(), &observer_)); }
diff --git a/components/download/internal/background_service/blob_task_proxy.cc b/components/download/internal/background_service/blob_task_proxy.cc index ab52593..4c08139 100644 --- a/components/download/internal/background_service/blob_task_proxy.cc +++ b/components/download/internal/background_service/blob_task_proxy.cc
@@ -61,7 +61,7 @@ // Build blob data. This has to do a copy into blob's internal storage. std::string blob_uuid = base::GenerateGUID(); auto builder = std::make_unique<storage::BlobDataBuilder>(blob_uuid); - builder->AppendData(*data.get()); + builder->AppendData(*data); blob_data_handle_ = blob_storage_context_->AddFinishedBlob(std::move(builder));
diff --git a/components/download/internal/background_service/in_memory_download_driver.cc b/components/download/internal/background_service/in_memory_download_driver.cc index 99ba097..50eeda04 100644 --- a/components/download/internal/background_service/in_memory_download_driver.cc +++ b/components/download/internal/background_service/in_memory_download_driver.cc
@@ -131,7 +131,7 @@ base::Optional<DriverEntry> entry; auto it = downloads_.find(guid); if (it != downloads_.end()) - entry = CreateDriverEntry(*it->second.get()); + entry = CreateDriverEntry(*it->second); return entry; }
diff --git a/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc b/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc index 18ab129..74ceabe5 100644 --- a/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc +++ b/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
@@ -34,8 +34,7 @@ class TestNetworkChangeNotifier : public net::NetworkChangeNotifier { public: TestNetworkChangeNotifier() - : net::NetworkChangeNotifier(), - conn_type_(ConnectionType::CONNECTION_UNKNOWN) {} + : conn_type_(ConnectionType::CONNECTION_UNKNOWN) {} // net::NetworkChangeNotifier implementation. ConnectionType GetCurrentConnectionType() const override { @@ -129,7 +128,7 @@ // Simulates a network change call, the event will be sent to client // immediately. void ChangeNetworkTypeImmediately(ConnectionType type) { - DCHECK(listener_.get()); + DCHECK(listener_); static_cast<NetworkStatusListener::Observer*>(listener_.get()) ->OnNetworkChanged(type); }
diff --git a/components/download/internal/common/base_file_win.cc b/components/download/internal/common/base_file_win.cc index df78b695..f7facc3 100644 --- a/components/download/internal/common/base_file_win.cc +++ b/components/download/internal/common/base_file_win.cc
@@ -302,7 +302,7 @@ source.append(1, L'\0'); target.append(1, L'\0'); - SHFILEOPSTRUCT move_info = {0}; + SHFILEOPSTRUCT move_info = {nullptr}; move_info.wFunc = FO_MOVE; move_info.pFrom = source.c_str(); move_info.pTo = target.c_str();
diff --git a/components/download/internal/common/download_file_impl.cc b/components/download/internal/common/download_file_impl.cc index a1b4b684..eefdd2ce 100644 --- a/components/download/internal/common/download_file_impl.cc +++ b/components/download/internal/common/download_file_impl.cc
@@ -504,7 +504,7 @@ DCHECK_GE(incoming_data_size, bytes_to_write); reason = WriteDataToFile( source_stream->offset() + source_stream->bytes_written(), - incoming_data.get()->data(), bytes_to_write); + incoming_data->data(), bytes_to_write); disk_writes_time_ += (base::TimeTicks::Now() - write_start); bytes_seen_ += bytes_to_write; total_incoming_data_size += bytes_to_write;
diff --git a/components/download/internal/common/download_file_unittest.cc b/components/download/internal/common/download_file_unittest.cc index c0bfc9fb..3fb6077 100644 --- a/components/download/internal/common/download_file_unittest.cc +++ b/components/download/internal/common/download_file_unittest.cc
@@ -201,7 +201,7 @@ bool calculate_hash, const DownloadItem::ReceivedSlices& received_slices) { // There can be only one. - DCHECK(!download_file_.get()); + DCHECK(!download_file_); input_stream_ = new StrictMock<MockInputStream>();
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc index 638e372..1574628 100644 --- a/components/download/internal/common/download_item_impl.cc +++ b/components/download/internal/common/download_item_impl.cc
@@ -418,7 +418,7 @@ // Should always have been nuked before now, at worst in // DownloadManager shutdown. - DCHECK(!download_file_.get()); + DCHECK(!download_file_); CHECK(!is_updating_observers_); for (auto& observer : observers_) @@ -1045,7 +1045,7 @@ IsPaused() ? 'T' : 'F', DebugResumeModeString(GetResumeMode()), auto_resume_count_, GetDangerType(), AllDataSaved() ? 'T' : 'F', GetLastModifiedTime().c_str(), GetETag().c_str(), - download_file_.get() ? "true" : "false", url_list.c_str(), + download_file_ ? "true" : "false", url_list.c_str(), GetFullPath().value().c_str(), GetTargetFilePath().value().c_str(), GetReferrerUrl().spec().c_str(), GetSiteUrl().spec().c_str()); } else { @@ -1392,7 +1392,7 @@ url_loader_factory_getter, net::URLRequestContextGetter* url_request_context_getter) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(!download_file_.get()); + DCHECK(!download_file_); DVLOG(20) << __func__ << "() this=" << DebugString(true); RecordDownloadCountWithSource(START_COUNT, download_source_); @@ -1428,7 +1428,7 @@ // If a resumption attempted failed, or if the download was DOA, then the // download should go back to being interrupted. if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) { - DCHECK(!download_file_.get()); + DCHECK(!download_file_); // Download requests that are interrupted by Start() should result in a // DownloadCreateInfo with an intact DownloadSaveInfo. @@ -1721,7 +1721,7 @@ DCHECK(!GetTargetFilePath().empty()); DCHECK(!IsDangerous()); - DCHECK(download_file_.get()); + DCHECK(download_file_); // Unilaterally rename; even if it already has the right name, // we need theannotation. DownloadFile::RenameCompletionCallback callback =
diff --git a/components/download/internal/common/download_item_impl_unittest.cc b/components/download/internal/common/download_item_impl_unittest.cc index 73de27f..1503ec3 100644 --- a/components/download/internal/common/download_item_impl_unittest.cc +++ b/components/download/internal/common/download_item_impl_unittest.cc
@@ -66,7 +66,7 @@ class MockDelegate : public DownloadItemImplDelegate { public: - MockDelegate() : DownloadItemImplDelegate() { SetDefaultExpectations(); } + MockDelegate() { SetDefaultExpectations(); } MOCK_METHOD2(DetermineDownloadTarget, void(DownloadItemImpl*, @@ -2235,8 +2235,7 @@ public ::testing::WithParamInterface<EventList> { public: DownloadItemDestinationUpdateRaceTest() - : DownloadItemTest(), - item_(CreateDownloadItem()), + : item_(CreateDownloadItem()), file_(new ::testing::StrictMock<MockDownloadFile>()), request_handle_(new ::testing::StrictMock<MockRequestHandle>()) { DCHECK_EQ(GetParam().size(), static_cast<unsigned>(kEventCount));
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc index 7ad88f9..9ed647a 100644 --- a/components/download/internal/common/in_progress_download_manager.cc +++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -373,7 +373,7 @@ std::unique_ptr<DownloadFile> download_file; if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE) { - DCHECK(stream.get()); + DCHECK(stream); download_file.reset(file_factory_->CreateFile( std::move(info->save_info), default_download_directory, std::move(stream), id, download->DestinationObserverAsWeakPtr()));
diff --git a/components/download/internal/common/parallel_download_job_unittest.cc b/components/download/internal/common/parallel_download_job_unittest.cc index eb09f931..ff5e9bc 100644 --- a/components/download/internal/common/parallel_download_job_unittest.cc +++ b/components/download/internal/common/parallel_download_job_unittest.cc
@@ -429,7 +429,7 @@ for (auto& worker : job_->workers()) { std::unique_ptr<MockDownloadRequestHandle> mock_handle = std::make_unique<MockDownloadRequestHandle>(); - EXPECT_CALL(*mock_handle.get(), CancelRequest(_)); + EXPECT_CALL(*mock_handle, CancelRequest(_)); MakeWorkerReady(worker.second.get(), std::move(mock_handle)); } @@ -451,10 +451,10 @@ EXPECT_TRUE(job_->is_paused()); for (auto& worker : job_->workers()) { - EXPECT_CALL(*job_.get(), CountOnInputStreamReady()); + EXPECT_CALL(*job_, CountOnInputStreamReady()); std::unique_ptr<MockDownloadRequestHandle> mock_handle = std::make_unique<MockDownloadRequestHandle>(); - EXPECT_CALL(*mock_handle.get(), PauseRequest()); + EXPECT_CALL(*mock_handle, PauseRequest()); MakeWorkerReady(worker.second.get(), std::move(mock_handle)); } @@ -517,7 +517,7 @@ job_->MakeFileInitialized(callback.Get(), DOWNLOAD_INTERRUPT_REASON_NONE); // Simulate and inject an error from IO thread after file initialized. - EXPECT_CALL(*download_item_.get(), GetState()) + EXPECT_CALL(*download_item_, GetState()) .WillRepeatedly(Return(DownloadItem::DownloadState::INTERRUPTED)); // Because of the error, no parallel requests are built.
diff --git a/components/download/quarantine/quarantine_win.cc b/components/download/quarantine/quarantine_win.cc index 165d5e8..f240414 100644 --- a/components/download/quarantine/quarantine_win.cc +++ b/components/download/quarantine/quarantine_win.cc
@@ -74,7 +74,8 @@ std::vector<char> zone_identifier_contents_buffer(32); DWORD actual_length = 0; if (!ReadFile(file.Get(), &zone_identifier_contents_buffer.front(), - zone_identifier_contents_buffer.size(), &actual_length, NULL)) + zone_identifier_contents_buffer.size(), &actual_length, + nullptr)) return false; zone_identifier_contents_buffer.resize(actual_length);
diff --git a/components/drive/BUILD.gn b/components/drive/BUILD.gn index 067d5ba..29b6e0c 100644 --- a/components/drive/BUILD.gn +++ b/components/drive/BUILD.gn
@@ -140,6 +140,8 @@ "chromeos/file_system_interface.cc", "chromeos/file_system_interface.h", "chromeos/file_system_observer.h", + "chromeos/loader_controller.cc", + "chromeos/loader_controller.h", "chromeos/remove_stale_cache_files.cc", "chromeos/remove_stale_cache_files.h", "chromeos/resource_metadata.cc",
diff --git a/components/drive/change_list_loader_unittest.cc b/components/drive/change_list_loader_unittest.cc index d508c48..4dbbb0c 100644 --- a/components/drive/change_list_loader_unittest.cc +++ b/components/drive/change_list_loader_unittest.cc
@@ -19,6 +19,7 @@ #include "components/drive/chromeos/change_list_loader_observer.h" #include "components/drive/chromeos/drive_test_util.h" #include "components/drive/chromeos/file_cache.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/event_logger.h" #include "components/drive/file_change.h"
diff --git a/components/drive/chromeos/change_list_loader.cc b/components/drive/chromeos/change_list_loader.cc index 1c0f787..f75fb08 100644 --- a/components/drive/chromeos/change_list_loader.cc +++ b/components/drive/chromeos/change_list_loader.cc
@@ -20,6 +20,7 @@ #include "components/drive/chromeos/about_resource_loader.h" #include "components/drive/chromeos/change_list_loader_observer.h" #include "components/drive/chromeos/change_list_processor.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/drive_api_util.h" #include "components/drive/event_logger.h" @@ -225,47 +226,6 @@ } // namespace -LoaderController::LoaderController() - : lock_count_(0), - weak_ptr_factory_(this) { -} - -LoaderController::~LoaderController() { - DCHECK(thread_checker_.CalledOnValidThread()); -} - -std::unique_ptr<base::ScopedClosureRunner> LoaderController::GetLock() { - DCHECK(thread_checker_.CalledOnValidThread()); - - ++lock_count_; - return std::make_unique<base::ScopedClosureRunner>( - base::Bind(&LoaderController::Unlock, weak_ptr_factory_.GetWeakPtr())); -} - -void LoaderController::ScheduleRun(const base::Closure& task) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!task.is_null()); - - if (lock_count_ > 0) { - pending_tasks_.push_back(task); - } else { - task.Run(); - } -} - -void LoaderController::Unlock() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_LT(0, lock_count_); - - if (--lock_count_ > 0) - return; - - std::vector<base::Closure> tasks; - tasks.swap(pending_tasks_); - for (size_t i = 0; i < tasks.size(); ++i) - tasks[i].Run(); -} - ChangeListLoader::ChangeListLoader( EventLogger* logger,
diff --git a/components/drive/chromeos/change_list_loader.h b/components/drive/chromeos/change_list_loader.h index 7bb89eb..511ef59 100644 --- a/components/drive/chromeos/change_list_loader.h +++ b/components/drive/chromeos/change_list_loader.h
@@ -22,7 +22,6 @@ namespace base { class CancellationFlag; -class ScopedClosureRunner; class SequencedTaskRunner; class Time; } // namespace base @@ -42,39 +41,9 @@ class ChangeList; class ChangeListLoaderObserver; class ChangeListProcessor; +class LoaderController; class ResourceMetadata; -// Delays execution of tasks as long as more than one lock is alive. -// Used to ensure that ChangeListLoader does not cause race condition by adding -// new entries created by sync tasks before they do. -// All code which may add entries found on the server to the local metadata -// should use this class. -class LoaderController { - public: - LoaderController(); - ~LoaderController(); - - // Increments the lock count and returns an object which decrements the count - // on its destruction. - // While the lock count is positive, tasks will be pending. - std::unique_ptr<base::ScopedClosureRunner> GetLock(); - - // Runs the task if the lock count is 0, otherwise it will be pending. - void ScheduleRun(const base::Closure& task); - - private: - // Decrements the lock count. - void Unlock(); - - int lock_count_; - std::vector<base::Closure> pending_tasks_; - - base::ThreadChecker thread_checker_; - - base::WeakPtrFactory<LoaderController> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(LoaderController); -}; - // ChangeListLoader is used to load the change list, the full resource list, // and directory contents, from Google Drive API. The class also updates the // resource metadata with the change list loaded from the server.
diff --git a/components/drive/chromeos/directory_loader.cc b/components/drive/chromeos/directory_loader.cc index 995caf0..fa1e1937 100644 --- a/components/drive/chromeos/directory_loader.cc +++ b/components/drive/chromeos/directory_loader.cc
@@ -17,9 +17,9 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "components/drive/chromeos/about_resource_loader.h" -#include "components/drive/chromeos/change_list_loader.h" #include "components/drive/chromeos/change_list_loader_observer.h" #include "components/drive/chromeos/change_list_processor.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/drive_api_util.h" #include "components/drive/event_logger.h" @@ -108,8 +108,7 @@ weak_ptr_factory_(this) { } - ~FeedFetcher() { - } + ~FeedFetcher() = default; void Run(const FileOperationCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -212,8 +211,7 @@ weak_ptr_factory_(this) { } -DirectoryLoader::~DirectoryLoader() { -} +DirectoryLoader::~DirectoryLoader() = default; void DirectoryLoader::AddObserver(ChangeListLoaderObserver* observer) { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/components/drive/chromeos/file_system.cc b/components/drive/chromeos/file_system.cc index 48cafdfe..1555ac5b 100644 --- a/components/drive/chromeos/file_system.cc +++ b/components/drive/chromeos/file_system.cc
@@ -28,6 +28,7 @@ #include "components/drive/chromeos/file_system/touch_operation.h" #include "components/drive/chromeos/file_system/truncate_operation.h" #include "components/drive/chromeos/file_system_observer.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/remove_stale_cache_files.h" #include "components/drive/chromeos/search_metadata.h" #include "components/drive/chromeos/sync_client.h"
diff --git a/components/drive/chromeos/file_system/search_operation.cc b/components/drive/chromeos/file_system/search_operation.cc index 649578e..e527e07 100644 --- a/components/drive/chromeos/file_system/search_operation.cc +++ b/components/drive/chromeos/file_system/search_operation.cc
@@ -14,7 +14,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" -#include "components/drive/chromeos/change_list_loader.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/drive_api_util.h" #include "components/drive/file_system_core_util.h"
diff --git a/components/drive/chromeos/loader_controller.cc b/components/drive/chromeos/loader_controller.cc new file mode 100644 index 0000000..cfd7dd416 --- /dev/null +++ b/components/drive/chromeos/loader_controller.cc
@@ -0,0 +1,52 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/drive/chromeos/loader_controller.h" + +#include "base/callback_helpers.h" + +namespace drive { +namespace internal { + +LoaderController::LoaderController() + : lock_count_(0), weak_ptr_factory_(this) {} + +LoaderController::~LoaderController() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +std::unique_ptr<base::ScopedClosureRunner> LoaderController::GetLock() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + ++lock_count_; + return std::make_unique<base::ScopedClosureRunner>(base::BindOnce( + &LoaderController::Unlock, weak_ptr_factory_.GetWeakPtr())); +} + +void LoaderController::ScheduleRun(const base::RepeatingClosure& task) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(task); + + if (lock_count_ > 0) { + pending_tasks_.push_back(task); + } else { + task.Run(); + } +} + +void LoaderController::Unlock() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_LT(0, lock_count_); + + if (--lock_count_ > 0) + return; + + std::vector<base::RepeatingClosure> tasks; + tasks.swap(pending_tasks_); + for (auto& task : tasks) + task.Run(); +} + +} // namespace internal +} // namespace drive
diff --git a/components/drive/chromeos/loader_controller.h b/components/drive/chromeos/loader_controller.h new file mode 100644 index 0000000..26ca87b3 --- /dev/null +++ b/components/drive/chromeos/loader_controller.h
@@ -0,0 +1,62 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DRIVE_CHROMEOS_LOADER_CONTROLLER_H_ +#define COMPONENTS_DRIVE_CHROMEOS_LOADER_CONTROLLER_H_ + +#include <memory> +#include <vector> + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" + +namespace base { +class ScopedClosureRunner; +} + +namespace drive { +namespace internal { + +// Delays execution of tasks as long as more than one lock is alive. +// Used to ensure that ChangeListLoader does not cause race condition by adding +// new entries created by sync tasks before they do. +// All code which may add entries found on the server to the local metadata +// should use this class. +// TODO(slangley): Consider specific unit tests for LoaderController. Currently +// it is tested as an artifact of other unit tests. +class LoaderController { + public: + LoaderController(); + ~LoaderController(); + + // Increments the lock count and returns an object which decrements the count + // on its destruction. + // While the lock count is positive, tasks will be pending. + // TODO(slangley): Return ScopedClosureRunner directly, rather than one that + // is wrapped in a unique_ptr. + std::unique_ptr<base::ScopedClosureRunner> GetLock(); + + // Runs the task if the lock count is 0, otherwise it will be pending. + // TODO(slangley): Change to using a OnceClosure. + void ScheduleRun(const base::Closure& task); + + private: + // Decrements the lock count. + void Unlock(); + + int lock_count_; + std::vector<base::RepeatingClosure> pending_tasks_; + + THREAD_CHECKER(thread_checker_); + + base::WeakPtrFactory<LoaderController> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(LoaderController); +}; + +} // namespace internal +} // namespace drive + +#endif // COMPONENTS_DRIVE_CHROMEOS_LOADER_CONTROLLER_H_
diff --git a/components/drive/chromeos/sync/entry_update_performer.cc b/components/drive/chromeos/sync/entry_update_performer.cc index b0855c3..1276e11 100644 --- a/components/drive/chromeos/sync/entry_update_performer.cc +++ b/components/drive/chromeos/sync/entry_update_performer.cc
@@ -10,9 +10,9 @@ #include "base/callback_helpers.h" #include "base/files/file_util.h" -#include "components/drive/chromeos/change_list_loader.h" #include "components/drive/chromeos/file_cache.h" #include "components/drive/chromeos/file_system/operation_delegate.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/chromeos/sync/entry_revert_performer.h" #include "components/drive/chromeos/sync/remove_performer.h"
diff --git a/components/drive/directory_loader_unittest.cc b/components/drive/directory_loader_unittest.cc index 304cfe17..c7d8676a 100644 --- a/components/drive/directory_loader_unittest.cc +++ b/components/drive/directory_loader_unittest.cc
@@ -13,10 +13,10 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/drive/chromeos/about_resource_loader.h" -#include "components/drive/chromeos/change_list_loader.h" #include "components/drive/chromeos/change_list_loader_observer.h" #include "components/drive/chromeos/drive_test_util.h" #include "components/drive/chromeos/file_cache.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/event_logger.h" #include "components/drive/file_system_core_util.h"
diff --git a/components/drive/drive_uploader.cc b/components/drive/drive_uploader.cc index c9bf1721..bc7d5f2 100644 --- a/components/drive/drive_uploader.cc +++ b/components/drive/drive_uploader.cc
@@ -309,7 +309,7 @@ if (info_ptr->content_length <= kMaxMultipartUploadSize) { DriveServiceBatchOperationsInterface* service; // If this is a batched request, calls the API on the request instead. - if (batch_request.get()) { + if (batch_request) { service = batch_request->configurator(); RecordDriveUploadProtocol(UPLOAD_METHOD_BATCH); } else { @@ -344,7 +344,7 @@ if (info_ptr->content_length <= kMaxMultipartUploadSize) { DriveServiceBatchOperationsInterface* service; // If this is a batched request, calls the API on the request instead. - if (batch_request.get()) { + if (batch_request) { service = batch_request->configurator(); RecordDriveUploadProtocol(UPLOAD_METHOD_BATCH); } else {
diff --git a/components/drive/file_system/operation_test_base.cc b/components/drive/file_system/operation_test_base.cc index 393241f..4fe6587 100644 --- a/components/drive/file_system/operation_test_base.cc +++ b/components/drive/file_system/operation_test_base.cc
@@ -10,6 +10,7 @@ #include "components/drive/chromeos/fake_free_disk_space_getter.h" #include "components/drive/chromeos/file_cache.h" #include "components/drive/chromeos/file_system/operation_delegate.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/event_logger.h" #include "components/drive/file_change.h" @@ -23,11 +24,9 @@ namespace drive { namespace file_system { -OperationTestBase::LoggingDelegate::LoggingDelegate() { -} +OperationTestBase::LoggingDelegate::LoggingDelegate() = default; -OperationTestBase::LoggingDelegate::~LoggingDelegate() { -} +OperationTestBase::LoggingDelegate::~LoggingDelegate() = default; void OperationTestBase::LoggingDelegate::OnFileChangedByOperation( const FileChange& changed_files) { @@ -52,15 +51,13 @@ false : wait_for_sync_complete_handler_.Run(local_id, callback); } -OperationTestBase::OperationTestBase() { -} +OperationTestBase::OperationTestBase() = default; OperationTestBase::OperationTestBase(int test_thread_bundle_options) : thread_bundle_(test_thread_bundle_options) { } -OperationTestBase::~OperationTestBase() { -} +OperationTestBase::~OperationTestBase() = default; void OperationTestBase::SetUp() { blocking_task_runner_ =
diff --git a/components/drive/file_system/search_operation_unittest.cc b/components/drive/file_system/search_operation_unittest.cc index c8837191..28c1bb7 100644 --- a/components/drive/file_system/search_operation_unittest.cc +++ b/components/drive/file_system/search_operation_unittest.cc
@@ -7,7 +7,7 @@ #include <stddef.h> #include "base/callback_helpers.h" -#include "components/drive/chromeos/change_list_loader.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/file_system/operation_test_base.h" #include "components/drive/service/fake_drive_service.h" #include "content/public/test/test_utils.h"
diff --git a/components/drive/service/drive_api_service.cc b/components/drive/service/drive_api_service.cc index 31a56ea..5f17ad6 100644 --- a/components/drive/service/drive_api_service.cc +++ b/components/drive/service/drive_api_service.cc
@@ -281,7 +281,7 @@ DriveAPIService::~DriveAPIService() { DCHECK(thread_checker_.CalledOnValidThread()); - if (sender_.get()) + if (sender_) sender_->auth_service()->RemoveObserver(this); }
diff --git a/components/drive/service/fake_drive_service.cc b/components/drive/service/fake_drive_service.cc index e35c04c..7a2bb4c8 100644 --- a/components/drive/service/fake_drive_service.cc +++ b/components/drive/service/fake_drive_service.cc
@@ -1868,8 +1868,7 @@ max_results)); if (start_changestamp > 0) { next_url = net::AppendOrReplaceQueryParameter( - next_url, "changestamp", - base::Int64ToString(start_changestamp).c_str()); + next_url, "changestamp", base::Int64ToString(start_changestamp)); } if (!search_query.empty()) { next_url = net::AppendOrReplaceQueryParameter(
diff --git a/components/drive/service/fake_drive_service_unittest.cc b/components/drive/service/fake_drive_service_unittest.cc index 4f28a3c..9b944ac7 100644 --- a/components/drive/service/fake_drive_service_unittest.cc +++ b/components/drive/service/fake_drive_service_unittest.cc
@@ -1836,7 +1836,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(DRIVE_NO_CONNECTION, response.code); - EXPECT_FALSE(entry.get()); + EXPECT_FALSE(entry); } TEST_F(FakeDriveServiceTest, ResumeUpload_NotFound) { @@ -1863,7 +1863,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(HTTP_NOT_FOUND, response.code); - EXPECT_FALSE(entry.get()); + EXPECT_FALSE(entry); } TEST_F(FakeDriveServiceTest, ResumeUpload_ExistingFile) { @@ -1907,7 +1907,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); - EXPECT_FALSE(entry.get()); + EXPECT_FALSE(entry); ASSERT_TRUE(!upload_progress_values.empty()); EXPECT_TRUE(base::STLIsSorted(upload_progress_values)); EXPECT_LE(0, upload_progress_values.front().first); @@ -1972,7 +1972,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); - EXPECT_FALSE(entry.get()); + EXPECT_FALSE(entry); ASSERT_TRUE(!upload_progress_values.empty()); EXPECT_TRUE(base::STLIsSorted(upload_progress_values)); EXPECT_LE(0, upload_progress_values.front().first);
diff --git a/components/drive/sync_client_unittest.cc b/components/drive/sync_client_unittest.cc index 5e1dcbf..04f61d2 100644 --- a/components/drive/sync_client_unittest.cc +++ b/components/drive/sync_client_unittest.cc
@@ -21,6 +21,7 @@ #include "components/drive/chromeos/file_system/move_operation.h" #include "components/drive/chromeos/file_system/operation_delegate.h" #include "components/drive/chromeos/file_system/remove_operation.h" +#include "components/drive/chromeos/loader_controller.h" #include "components/drive/chromeos/resource_metadata.h" #include "components/drive/drive.pb.h" #include "components/drive/event_logger.h"
diff --git a/components/error_page_strings_grdp/OWNERS b/components/error_page_strings_grdp/OWNERS new file mode 100644 index 0000000..1a8ff93 --- /dev/null +++ b/components/error_page_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/error_page/OWNERS
diff --git a/components/error_page_strings_grdp/README.md b/components/error_page_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/error_page_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/exo/notification_surface.cc b/components/exo/notification_surface.cc index 17ae6b18..6c3209a 100644 --- a/components/exo/notification_surface.cc +++ b/components/exo/notification_surface.cc
@@ -5,6 +5,7 @@ #include "components/exo/notification_surface.h" #include "components/exo/notification_surface_manager.h" +#include "components/exo/shell_surface.h" #include "components/exo/surface.h" #include "ui/aura/window.h" #include "ui/gfx/geometry/rect.h" @@ -33,6 +34,11 @@ return root_surface()->content_size(); } +void NotificationSurface::SetApplicationId(const char* application_id) { + exo::ShellSurface::SetApplicationId(host_window(), + base::make_optional(application_id)); +} + void NotificationSurface::OnSurfaceCommit() { SurfaceTreeHost::OnSurfaceCommit();
diff --git a/components/exo/notification_surface.h b/components/exo/notification_surface.h index a202ba6..2544e40c 100644 --- a/components/exo/notification_surface.h +++ b/components/exo/notification_surface.h
@@ -28,6 +28,8 @@ // Get the content size of the |root_surface()|. const gfx::Size& GetContentSize() const; + void SetApplicationId(const char* application_id); + const std::string& notification_key() const { return notification_key_; } // Overridden from SurfaceDelegate:
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index fd74cd44..267b4540 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -2347,8 +2347,15 @@ wl_resource_destroy(resource); } +void notification_surface_set_app_id(wl_client* client, + wl_resource* resource, + const char* app_id) { + GetUserDataAs<NotificationSurface>(resource)->SetApplicationId(app_id); +} + const struct zcr_notification_surface_v1_interface - notification_surface_implementation = {notification_surface_destroy}; + notification_surface_implementation = {notification_surface_destroy, + notification_surface_set_app_id}; //////////////////////////////////////////////////////////////////////////////// // remote_shell_interface: @@ -3027,7 +3034,7 @@ const struct zaura_shell_interface aura_shell_implementation = { aura_shell_get_aura_surface, aura_shell_get_aura_output}; -const uint32_t aura_shell_version = 5; +const uint32_t aura_shell_version = 6; void bind_aura_shell(wl_client* client, void* data,
diff --git a/components/favicon/core/BUILD.gn b/components/favicon/core/BUILD.gn index 59f1e72..798ad7bc 100644 --- a/components/favicon/core/BUILD.gn +++ b/components/favicon/core/BUILD.gn
@@ -14,6 +14,8 @@ "favicon_driver_observer.h", "favicon_handler.cc", "favicon_handler.h", + "favicon_server_fetcher_params.cc", + "favicon_server_fetcher_params.h", "favicon_service.cc", "favicon_service.h", "favicon_service_impl.cc",
diff --git a/components/favicon/core/favicon_server_fetcher_params.cc b/components/favicon/core/favicon_server_fetcher_params.cc new file mode 100644 index 0000000..dd23dd9 --- /dev/null +++ b/components/favicon/core/favicon_server_fetcher_params.cc
@@ -0,0 +1,57 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/favicon/core/favicon_server_fetcher_params.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "components/favicon_base/favicon_util.h" +#include "ui/gfx/favicon_size.h" + +namespace favicon { +namespace { + +const char kClientParamDesktop[] = "client=chrome_desktop"; +const char kClientParamMobile[] = "client=chrome"; + +float GetMaxDeviceScaleFactor() { + std::vector<float> favicon_scales = favicon_base::GetFaviconScales(); + DCHECK(!favicon_scales.empty()); + return favicon_scales.back(); +} + +} // namespace + +std::unique_ptr<FaviconServerFetcherParams> +FaviconServerFetcherParams::CreateForDesktop(const GURL& page_url) { + return base::WrapUnique(new FaviconServerFetcherParams( + page_url, favicon_base::IconType::kFavicon, + std::ceil(gfx::kFaviconSize * GetMaxDeviceScaleFactor()), 0, + kClientParamDesktop)); +} + +std::unique_ptr<FaviconServerFetcherParams> +FaviconServerFetcherParams::CreateForMobile(const GURL& page_url, + int min_source_size_in_pixel, + int desired_size_in_pixel) { + return base::WrapUnique(new FaviconServerFetcherParams( + page_url, favicon_base::IconType::kTouchIcon, min_source_size_in_pixel, + desired_size_in_pixel, kClientParamMobile)); +} + +FaviconServerFetcherParams::FaviconServerFetcherParams( + const GURL& page_url, + favicon_base::IconType icon_type, + int min_source_size_in_pixel, + int desired_size_in_pixel, + const std::string& google_server_client_param) + : page_url_(page_url), + icon_type_(icon_type), + min_source_size_in_pixel_(min_source_size_in_pixel), + desired_size_in_pixel_(desired_size_in_pixel), + google_server_client_param_(google_server_client_param) {} + +FaviconServerFetcherParams::~FaviconServerFetcherParams() = default; + +} // namespace favicon
diff --git a/components/favicon/core/favicon_server_fetcher_params.h b/components/favicon/core/favicon_server_fetcher_params.h new file mode 100644 index 0000000..8484239 --- /dev/null +++ b/components/favicon/core/favicon_server_fetcher_params.h
@@ -0,0 +1,53 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_FAVICON_CORE_FAVICON_SERVER_FETCHER_PARAMS_H_ +#define COMPONENTS_FAVICON_CORE_FAVICON_SERVER_FETCHER_PARAMS_H_ + +#include "components/favicon_base/favicon_util.h" + +class GURL; + +namespace favicon { + +class FaviconServerFetcherParams { + public: + // Platform specific constructors that set default fetch parameters. Any + // platform not Android nor iOS is considered desktop. + static std::unique_ptr<FaviconServerFetcherParams> CreateForDesktop( + const GURL& page_url); + static std::unique_ptr<FaviconServerFetcherParams> CreateForMobile( + const GURL& page_url, + int min_source_size_in_pixel, + int desired_size_in_pixel); + + ~FaviconServerFetcherParams(); + + const GURL& page_url() const { return page_url_; }; + favicon_base::IconType icon_type() const { return icon_type_; }; + int min_source_size_in_pixel() const { return min_source_size_in_pixel_; }; + int desired_size_in_pixel() const { return desired_size_in_pixel_; }; + const std::string& google_server_client_param() const { + return google_server_client_param_; + }; + + private: + FaviconServerFetcherParams(const GURL& page_url, + favicon_base::IconType icon_type, + int min_source_size_in_pixel, + int desired_size_in_pixel, + const std::string& google_server_client_param); + + const GURL& page_url_; + favicon_base::IconType icon_type_; + int min_source_size_in_pixel_; + int desired_size_in_pixel_; + std::string google_server_client_param_; + + DISALLOW_COPY_AND_ASSIGN(FaviconServerFetcherParams); +}; + +} // namespace favicon + +#endif // COMPONENTS_FAVICON_CORE_FAVICON_SERVER_FETCHER_PARAMS_H_
diff --git a/components/favicon/core/large_icon_service.cc b/components/favicon/core/large_icon_service.cc index eac4973..4edb822b 100644 --- a/components/favicon/core/large_icon_service.cc +++ b/components/favicon/core/large_icon_service.cc
@@ -24,6 +24,7 @@ #include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "components/data_use_measurement/core/data_use_user_data.h" +#include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" @@ -52,6 +53,8 @@ "size=%d&min_size=%d&max_size=%d&fallback_opts=TYPE,SIZE,URL&url=%s"; const char kGoogleServerV2RequestFormatParam[] = "request_format"; +const char kClientParam[] = "client=chrome"; + const char kCheckSeenParam[] = "check_seen=true&"; const int kGoogleServerV2EnforcedMinSizeInPixel = 16; @@ -79,10 +82,12 @@ return page_url.ReplaceComponents(replacements); } -GURL GetRequestUrlForGoogleServerV2(const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, - bool may_page_url_be_private) { +GURL GetRequestUrlForGoogleServerV2( + const GURL& page_url, + const std::string& google_server_client_param, + int min_source_size_in_pixel, + int desired_size_in_pixel, + bool may_page_url_be_private) { std::string url_format = base::GetFieldTrialParamValueByFeature( kLargeIconServiceFetchingFeature, kGoogleServerV2RequestFormatParam); double desired_to_max_size_factor = base::GetFieldTrialParamByFeatureAsDouble( @@ -105,10 +110,13 @@ static_cast<int>(desired_size_in_pixel * desired_to_max_size_factor); max_size_in_pixel = std::max(max_size_in_pixel, minimum_max_size_in_pixel); - return GURL(base::StringPrintf( + std::string request_url = base::StringPrintf( url_format.empty() ? kGoogleServerV2RequestFormat : url_format.c_str(), may_page_url_be_private ? kCheckSeenParam : "", desired_size_in_pixel, - min_source_size_in_pixel, max_size_in_pixel, page_url.spec().c_str())); + min_source_size_in_pixel, max_size_in_pixel, page_url.spec().c_str()); + base::ReplaceFirstSubstringAfterOffset( + &request_url, 0, std::string(kClientParam), google_server_client_param); + return GURL(request_url); } bool IsDbResultAdequate(const favicon_base::FaviconRawBitmapResult& db_result, @@ -193,8 +201,8 @@ void FinishServerRequestAsynchronously( const favicon_base::GoogleFaviconServerCallback& callback, favicon_base::GoogleFaviconServerRequestStatus status) { - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - base::Bind(callback, status)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, status)); } // Singleton map keyed by organization-identifying domain (excludes registrar @@ -407,6 +415,7 @@ void OnFetchIconFromGoogleServerComplete( FaviconService* favicon_service, const GURL& page_url, + favicon_base::IconType icon_type, const favicon_base::GoogleFaviconServerCallback& callback, const std::string& server_request_url, const gfx::Image& image, @@ -437,8 +446,8 @@ // expired (out-of-date), they will be refetched when we visit the original // page any time in the future. favicon_service->SetOnDemandFavicons( - page_url, GURL(original_icon_url), favicon_base::IconType::kTouchIcon, - image, base::Bind(&OnSetOnDemandFaviconComplete, callback)); + page_url, GURL(original_icon_url), icon_type, image, + base::BindOnce(&OnSetOnDemandFaviconComplete, callback)); } } // namespace @@ -485,13 +494,11 @@ void LargeIconService:: GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, + std::unique_ptr<FaviconServerFetcherParams> params, bool may_page_url_be_private, const net::NetworkTrafficAnnotationTag& traffic_annotation, const favicon_base::GoogleFaviconServerCallback& callback) { - DCHECK_LE(0, min_source_size_in_pixel); + DCHECK_LE(0, params->min_source_size_in_pixel()); if (net::NetworkChangeNotifier::IsOffline()) { // By exiting early when offline, we avoid caching the failure and thus @@ -501,13 +508,13 @@ return; } - if (!page_url.is_valid()) { + if (!params->page_url().is_valid()) { FinishServerRequestAsynchronously( callback, GoogleFaviconServerRequestStatus::FAILURE_TARGET_URL_INVALID); return; } - const GURL trimmed_page_url = TrimPageUrlForGoogleServer(page_url); + const GURL trimmed_page_url = TrimPageUrlForGoogleServer(params->page_url()); if (!trimmed_page_url.is_valid()) { FinishServerRequestAsynchronously( callback, GoogleFaviconServerRequestStatus::FAILURE_TARGET_URL_SKIPPED); @@ -515,7 +522,8 @@ } const GURL server_request_url = GetRequestUrlForGoogleServerV2( - trimmed_page_url, min_source_size_in_pixel, desired_size_in_pixel, + trimmed_page_url, params->google_server_client_param(), + params->min_source_size_in_pixel(), params->desired_size_in_pixel(), may_page_url_be_private); if (!server_request_url.is_valid()) { FinishServerRequestAsynchronously( @@ -532,10 +540,11 @@ } favicon_service_->CanSetOnDemandFavicons( - page_url, favicon_base::IconType::kTouchIcon, + params->page_url(), params->icon_type(), base::BindOnce(&LargeIconService::OnCanSetOnDemandFaviconComplete, weak_ptr_factory_.GetWeakPtr(), server_request_url, - page_url, traffic_annotation, callback)); + params->page_url(), params->icon_type(), + traffic_annotation, callback)); } void LargeIconService::TouchIconFromGoogleServer(const GURL& icon_url) { @@ -591,6 +600,7 @@ void LargeIconService::OnCanSetOnDemandFaviconComplete( const GURL& server_request_url, const GURL& page_url, + favicon_base::IconType icon_type, const net::NetworkTrafficAnnotationTag& traffic_annotation, const favicon_base::GoogleFaviconServerCallback& callback, bool can_set_on_demand_favicon) { @@ -603,8 +613,8 @@ data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE); image_fetcher_->FetchImage( server_request_url.spec(), server_request_url, - base::BindRepeating(&OnFetchIconFromGoogleServerComplete, - favicon_service_, page_url, callback), + base::BindOnce(&OnFetchIconFromGoogleServerComplete, favicon_service_, + page_url, icon_type, callback), traffic_annotation); }
diff --git a/components/favicon/core/large_icon_service.h b/components/favicon/core/large_icon_service.h index 96bd8b1..1d1a32c 100644 --- a/components/favicon/core/large_icon_service.h +++ b/components/favicon/core/large_icon_service.h
@@ -26,6 +26,7 @@ namespace favicon { class FaviconService; +class FaviconServerFetcherParams; // The large icon service provides methods to access large icons. It relies on // the favicon service. @@ -93,9 +94,7 @@ // TODO(jkrcal): It is not clear from the name of this function, that it // actually adds the icon to the local cache. Maybe "StoreLargeIcon..."? void GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, + std::unique_ptr<FaviconServerFetcherParams> params, bool may_page_url_be_private, const net::NetworkTrafficAnnotationTag& traffic_annotation, const favicon_base::GoogleFaviconServerCallback& callback); @@ -125,6 +124,7 @@ void OnCanSetOnDemandFaviconComplete( const GURL& server_request_url, const GURL& page_url, + favicon_base::IconType icon_type, const net::NetworkTrafficAnnotationTag& traffic_annotation, const favicon_base::GoogleFaviconServerCallback& callback, bool can_set_on_demand_favicon);
diff --git a/components/favicon/core/large_icon_service_unittest.cc b/components/favicon/core/large_icon_service_unittest.cc index 7007c78..c563b847 100644 --- a/components/favicon/core/large_icon_service_unittest.cc +++ b/components/favicon/core/large_icon_service_unittest.cc
@@ -17,6 +17,7 @@ #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "components/favicon/core/favicon_client.h" +#include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/test/mock_favicon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" @@ -29,6 +30,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/layout.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image.h" @@ -125,7 +127,10 @@ LargeIconServiceTest() : mock_image_fetcher_(new NiceMock<MockImageFetcher>()), large_icon_service_(&mock_favicon_service_, - base::WrapUnique(mock_image_fetcher_)) {} + base::WrapUnique(mock_image_fetcher_)) { + scoped_set_supported_scale_factors_.reset( + new ui::test::ScopedSetSupportedScaleFactors({ui::SCALE_FACTOR_200P})); + } ~LargeIconServiceTest() override {} @@ -135,6 +140,8 @@ testing::NiceMock<MockFaviconService> mock_favicon_service_; LargeIconService large_icon_service_; base::HistogramTester histogram_tester_; + std::unique_ptr<ui::test::ScopedSetSupportedScaleFactors> + scoped_set_supported_scale_factors_; private: DISALLOW_COPY_AND_ASSIGN(LargeIconServiceTest); @@ -164,9 +171,12 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS)); @@ -175,6 +185,42 @@ "Favicons.LargeIconService.DownloadedSize", 64, /*expected_count=*/1); } +TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerForDesktop) { + const GURL kExpectedServerUrl( + "https://t0.gstatic.com/faviconV2?client=chrome_desktop" + "&drop_404_icon=true&check_seen=true&size=32&min_size=32&max_size=256" + "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/"); + + EXPECT_CALL(mock_favicon_service_, UnableToDownloadFavicon(_)).Times(0); + EXPECT_CALL(mock_favicon_service_, + CanSetOnDemandFavicons(GURL(kDummyUrl), + favicon_base::IconType::kFavicon, _)) + .WillOnce(PostBoolReplyToArg2(true)); + + base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback; + EXPECT_CALL(*mock_image_fetcher_, + FetchImageAndData_(_, kExpectedServerUrl, _, _, _)) + .WillOnce(PostFetchReply(gfx::Image::CreateFrom1xBitmap( + CreateTestSkBitmap(32, 32, kTestColor)))); + EXPECT_CALL(mock_favicon_service_, + SetOnDemandFavicons(GURL(kDummyUrl), kExpectedServerUrl, + favicon_base::IconType::kFavicon, _, _)) + .WillOnce(PostBoolReplyToArg4(true)); + + large_icon_service_ + .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( + favicon::FaviconServerFetcherParams::CreateForDesktop( + GURL(kDummyUrl)), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); + + EXPECT_CALL(callback, + Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS)); + scoped_task_environment_.RunUntilIdle(); + histogram_tester_.ExpectUniqueSample( + "Favicons.LargeIconService.DownloadedSize", 32, /*expected_count=*/1); +} + TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerWithCustomUrl) { variations::testing::VariationParamsManager variation_params( "LargeIconServiceFetching", @@ -206,9 +252,12 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS)); @@ -243,9 +292,12 @@ base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback; large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS)); @@ -274,9 +326,11 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrlWithQuery), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrlWithQuery), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, favicon_base::GoogleFaviconServerCallback()); scoped_task_environment_.RunUntilIdle(); @@ -298,9 +352,12 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/false, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/false, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus:: FAILURE_CONNECTION_ERROR)); @@ -316,9 +373,12 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyFtpUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyFtpUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus:: FAILURE_TARGET_URL_SKIPPED)); @@ -337,9 +397,12 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyInvalidUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyInvalidUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus:: FAILURE_TARGET_URL_INVALID)); @@ -371,9 +434,12 @@ large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus:: FAILURE_CONNECTION_ERROR)); @@ -400,9 +466,12 @@ base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback; large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus:: FAILURE_HTTP_ERROR_CACHED)); @@ -426,9 +495,12 @@ base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback; large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - GURL(kDummyUrl), /*min_source_size_in_pixel=*/42, - /*desired_size_in_pixel=*/61, /*may_page_url_be_private=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get()); + favicon::FaviconServerFetcherParams::CreateForMobile( + GURL(kDummyUrl), + /*min_source_size_in_pixel=*/42, + /*desired_size_in_pixel=*/61), + /*may_page_url_be_private=*/true, TRAFFIC_ANNOTATION_FOR_TESTS, + callback.Get()); EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus:: FAILURE_ICON_EXISTS_IN_DB));
diff --git a/components/mirroring/service/BUILD.gn b/components/mirroring/service/BUILD.gn index 6aea231d..2a91cfff 100644 --- a/components/mirroring/service/BUILD.gn +++ b/components/mirroring/service/BUILD.gn
@@ -41,6 +41,8 @@ "value_util.h", "video_capture_client.cc", "video_capture_client.h", + "wifi_status_monitor.cc", + "wifi_status_monitor.h", ] public_deps = [ @@ -77,6 +79,7 @@ "session_unittest.cc", "udp_socket_client_unittest.cc", "video_capture_client_unittest.cc", + "wifi_status_monitor_unittest.cc", ] deps = [
diff --git a/components/mirroring/service/wifi_status_monitor.cc b/components/mirroring/service/wifi_status_monitor.cc new file mode 100644 index 0000000..f7a57a48 --- /dev/null +++ b/components/mirroring/service/wifi_status_monitor.cc
@@ -0,0 +1,77 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/mirroring/service/wifi_status_monitor.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "components/mirroring/service/message_dispatcher.h" + +namespace mirroring { + +namespace { + +// The interval to query the status. +constexpr base::TimeDelta kQueryInterval = base::TimeDelta::FromMinutes(2); + +// The maximum number of recent status to be kept. +constexpr int kMaxRecords = 30; + +} // namespace + +WifiStatusMonitor::WifiStatusMonitor(int32_t session_id, + MessageDispatcher* message_dispatcher) + : session_id_(session_id), message_dispatcher_(message_dispatcher) { + DCHECK(message_dispatcher_); + message_dispatcher_->Subscribe( + ResponseType::STATUS_RESPONSE, + base::BindRepeating(&WifiStatusMonitor::RecordStatus, + base::Unretained(this))); + query_timer_.Start(FROM_HERE, kQueryInterval, + base::BindRepeating(&WifiStatusMonitor::QueryStatus, + base::Unretained(this))); + QueryStatus(); +} + +WifiStatusMonitor::~WifiStatusMonitor() { + message_dispatcher_->Unsubscribe(ResponseType::STATUS_RESPONSE); +} + +std::vector<WifiStatus> WifiStatusMonitor::GetRecentValues() { + std::vector<WifiStatus> recent_status(recent_status_.begin(), + recent_status_.end()); + recent_status_.clear(); + return recent_status; +} + +void WifiStatusMonitor::QueryStatus() { + base::Value query(base::Value::Type::DICTIONARY); + query.SetKey("type", base::Value("GET_STATUS")); + query.SetKey("sessionId", base::Value(session_id_)); + query.SetKey("seqNum", base::Value(message_dispatcher_->GetNextSeqNumber())); + base::Value::ListStorage status; + status.emplace_back(base::Value("wifiSnr")); + status.emplace_back(base::Value("wifiSpeed")); + query.SetKey("get_status", base::Value(status)); + CastMessage get_status_message; + get_status_message.message_namespace = kWebRtcNamespace; + get_status_message.data = std::move(query); + message_dispatcher_->SendOutboundMessage(get_status_message); +} + +void WifiStatusMonitor::RecordStatus(const ReceiverResponse& response) { + if (!response.status || response.status->wifi_speed.size() != 4) + return; + if (recent_status_.size() == kMaxRecords) + recent_status_.pop_front(); + WifiStatus received_status; + received_status.snr = response.status->wifi_snr; + // Only records the current speed. + received_status.speed = response.status->wifi_speed[3]; + received_status.timestamp = base::Time::Now(); + recent_status_.emplace_back(received_status); +} + +} // namespace mirroring
diff --git a/components/mirroring/service/wifi_status_monitor.h b/components/mirroring/service/wifi_status_monitor.h new file mode 100644 index 0000000..ac348ce --- /dev/null +++ b/components/mirroring/service/wifi_status_monitor.h
@@ -0,0 +1,61 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_ +#define COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_ + +#include <vector> + +#include "base/containers/circular_deque.h" +#include "base/macros.h" +#include "base/time/time.h" +#include "base/timer/timer.h" + +namespace mirroring { + +class MessageDispatcher; +struct ReceiverResponse; + +struct WifiStatus { + double snr; + int32_t speed; // The current WiFi speed. + base::Time timestamp; // Recording time of this status. +}; + +// Periodically sends requests to the Cast device for WiFi network status +// updates, processes responses, and maintains a recent history of data points. +// This data can be included in feedback logs to help identify and diagnose +// issues related to lousy network performance. +class WifiStatusMonitor { + public: + // |message_dispatcher| must keep alive during the lifetime of this class. + WifiStatusMonitor(int32_t session_id, MessageDispatcher* message_dispatcher); + ~WifiStatusMonitor(); + + // Gets the recorded status and clear |recent_status_|. + std::vector<WifiStatus> GetRecentValues(); + + // Sends GET_STATUS message to receiver. + void QueryStatus(); + + // Callback for the STATUS_RESPONSE message. Records the WiFi status reported + // by receiver. + void RecordStatus(const ReceiverResponse& response); + + private: + const int32_t session_id_; + + MessageDispatcher* const message_dispatcher_; // Outlives this class. + + base::RepeatingTimer query_timer_; + + // Stores the recent status. Will be reset when GetRecentValues() is called. + base::circular_deque<WifiStatus> recent_status_; + + DISALLOW_COPY_AND_ASSIGN(WifiStatusMonitor); +}; + +} // namespace mirroring + +#endif // COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
diff --git a/components/mirroring/service/wifi_status_monitor_unittest.cc b/components/mirroring/service/wifi_status_monitor_unittest.cc new file mode 100644 index 0000000..26e53f0 --- /dev/null +++ b/components/mirroring/service/wifi_status_monitor_unittest.cc
@@ -0,0 +1,173 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/mirroring/service/wifi_status_monitor.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/json/json_reader.h" +#include "base/macros.h" +#include "base/test/mock_callback.h" +#include "base/test/scoped_task_environment.h" +#include "components/mirroring/service/message_dispatcher.h" +#include "components/mirroring/service/value_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; + +namespace mirroring { + +namespace { + +bool IsNullMessage(const CastMessage& message) { + return message.message_namespace.empty() && message.data.is_none(); +} + +std::string GetMessageType(const CastMessage& message) { + std::string type; + if (message.data.is_none()) + return type; + EXPECT_TRUE(GetString(message.data, "type", &type)); + return type; +} + +void VerifyRecordedStatus(const std::vector<WifiStatus> recorded_status, + double starting_snr, + int starting_speed, + int num_of_responses) { + EXPECT_EQ(num_of_responses, static_cast<int>(recorded_status.size())); + for (int i = 0; i < num_of_responses; ++i) { + EXPECT_EQ(starting_snr + i, recorded_status[i].snr); + EXPECT_EQ(starting_speed + i, recorded_status[i].speed); + } +} + +} // namespace + +class WifiStatusMonitorTest : public CastMessageChannel, + public ::testing::Test { + public: + WifiStatusMonitorTest() : message_dispatcher_(this, error_callback_.Get()) {} + + ~WifiStatusMonitorTest() override {} + + // CastMessageChannel implementation. For outbound messages. + void Send(const CastMessage& message) override { + last_outbound_message_.message_namespace = message.message_namespace; + last_outbound_message_.data = message.data.Clone(); + } + + protected: + // Generates and sends |num_of_responses| responses. + void SendStatusResponses(double starting_snr, + int starting_speed, + int num_of_responses) { + for (int i = 0; i < num_of_responses; ++i) { + const std::string response = + "{\"seqNum\":" + + std::to_string(message_dispatcher_.GetNextSeqNumber()) + + "," + "\"type\": \"STATUS_RESPONSE\"," + "\"result\": \"ok\"," + "\"status\": {" + "\"wifiSnr\":" + + std::to_string(starting_snr + i) + + "," + "\"wifiSpeed\": [1234, 5678, 3000, " + + std::to_string(starting_speed + i) + + "]," + "\"wifiFcsError\": [12, 13, 12, 12]}" // This will be ignored. + "}"; + SendInboundMessage(response); + } + } + + // Sends an inbound message to |message_dispatcher|. + void SendInboundMessage(const std::string& response) { + std::unique_ptr<base::Value> value = base::JSONReader::Read(response); + ASSERT_TRUE(value); + CastMessage message; + message.message_namespace = kWebRtcNamespace; + message.data = base::Value::FromUniquePtrValue(std::move(value)); + static_cast<CastMessageChannel*>(&message_dispatcher_)->Send(message); + scoped_task_environment_.RunUntilIdle(); + } + + // Creates a WifiStatusMonitor and start monitoring the status. + std::unique_ptr<WifiStatusMonitor> StartMonitoring() { + EXPECT_TRUE(IsNullMessage(last_outbound_message_)); + EXPECT_CALL(error_callback_, Run(_)).Times(0); + auto status_monitor = + std::make_unique<WifiStatusMonitor>(123, &message_dispatcher_); + scoped_task_environment_.RunUntilIdle(); + // Expect to receive request to send GET_STATUS message when create a + // WifiStatusMonitor. + EXPECT_EQ(kWebRtcNamespace, last_outbound_message_.message_namespace); + EXPECT_EQ("GET_STATUS", GetMessageType(last_outbound_message_)); + // Clear the old outbound message. + last_outbound_message_.message_namespace.clear(); + last_outbound_message_.data = base::Value(); + EXPECT_TRUE(IsNullMessage(last_outbound_message_)); + return status_monitor; + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + base::MockCallback<MessageDispatcher::ErrorCallback> error_callback_; + MessageDispatcher message_dispatcher_; + CastMessage last_outbound_message_; + + private: + DISALLOW_COPY_AND_ASSIGN(WifiStatusMonitorTest); +}; + +TEST_F(WifiStatusMonitorTest, QueryStatusAndRecordResponse) { + std::unique_ptr<WifiStatusMonitor> status_monitor = StartMonitoring(); + + // Send two responses and verify the data are stored. + SendStatusResponses(36.7, 3001, 2); + std::vector<WifiStatus> recent_status = status_monitor->GetRecentValues(); + VerifyRecordedStatus(recent_status, 36.7, 3001, 2); + + // There should be no further status stored. + recent_status = status_monitor->GetRecentValues(); + EXPECT_TRUE(recent_status.empty()); + + // Sends more than the maximum number (30) of records that can be stored. + SendStatusResponses(36.7, 3001, 40); + // Expect that only the recent 30 records were stored. + recent_status = status_monitor->GetRecentValues(); + VerifyRecordedStatus(recent_status, 46.7, 3011, 30); +} + +TEST_F(WifiStatusMonitorTest, IgnoreMalformedStatusMessage) { + std::unique_ptr<WifiStatusMonitor> status_monitor = StartMonitoring(); + + // Sends a response with incomplete wifiSpeed data and expects it is ignored. + const std::string response1 = + "{\"seqNum\": 123," + "\"type\": \"STATUS_RESPONSE\"," + "\"result\": \"ok\"," + "\"status\": {" + "\"wifiSnr\": 32," + "\"wifiSpeed\": [1234, 5678, 3000]," + "\"wifiFcsError\": [12, 13, 12, 12]}" + "}"; + SendInboundMessage(response1); + std::vector<WifiStatus> recent_status = status_monitor->GetRecentValues(); + scoped_task_environment_.RunUntilIdle(); + EXPECT_TRUE(recent_status.empty()); + + // Sends a response with null status field and expects it is ignored. + const std::string response2 = + "{\"seqNum\": 123," + "\"type\": \"STATUS_RESPONSE\"," + "\"status\": null}"; + SendInboundMessage(response2); + recent_status = status_monitor->GetRecentValues(); + scoped_task_environment_.RunUntilIdle(); + EXPECT_TRUE(recent_status.empty()); +} + +} // namespace mirroring
diff --git a/components/net_log/BUILD.gn b/components/net_log/BUILD.gn index 133894e..dc1750e 100644 --- a/components/net_log/BUILD.gn +++ b/components/net_log/BUILD.gn
@@ -17,6 +17,7 @@ "//components/data_reduction_proxy/core/common", "//components/version_info", "//net", + "//services/network/public/mojom", ] } @@ -31,6 +32,9 @@ "//base/test:test_support", "//net", "//net:test_support", + "//services/network:network_service", + "//services/network/public/cpp", + "//services/network/public/cpp:cpp_base", "//testing/gtest", ] }
diff --git a/components/net_log/DEPS b/components/net_log/DEPS index efca3dd..4d7f1c7 100644 --- a/components/net_log/DEPS +++ b/components/net_log/DEPS
@@ -2,4 +2,5 @@ "+components/data_reduction_proxy/core/common", "+components/version_info", "+net", + "+services/network", ]
diff --git a/components/net_log/chrome_net_log.cc b/components/net_log/chrome_net_log.cc index a799eee..878b964 100644 --- a/components/net_log/chrome_net_log.cc +++ b/components/net_log/chrome_net_log.cc
@@ -49,7 +49,7 @@ NetExportFileWriter* ChromeNetLog::net_export_file_writer() { if (!net_export_file_writer_) - net_export_file_writer_ = base::WrapUnique(new NetExportFileWriter(this)); + net_export_file_writer_ = base::WrapUnique(new NetExportFileWriter()); return net_export_file_writer_.get(); } @@ -61,6 +61,18 @@ net::GetNetConstants(); DCHECK(constants_dict); + auto platform_dict = + GetPlatformConstants(command_line_string, channel_string); + if (platform_dict) + constants_dict->MergeDictionary(platform_dict.get()); + return constants_dict; +} + +std::unique_ptr<base::DictionaryValue> ChromeNetLog::GetPlatformConstants( + const base::CommandLine::StringType& command_line_string, + const std::string& channel_string) { + auto constants_dict = std::make_unique<base::DictionaryValue>(); + // Add a dictionary with the version of the client and its command line // arguments. auto dict = std::make_unique<base::DictionaryValue>(); @@ -84,7 +96,7 @@ data_reduction_proxy::DataReductionProxyEventStore::AddConstants( constants_dict.get()); - return std::move(constants_dict); + return constants_dict; } void ChromeNetLog::ShutDownBeforeTaskScheduler() {
diff --git a/components/net_log/chrome_net_log.h b/components/net_log/chrome_net_log.h index cfa0298..ead1479 100644 --- a/components/net_log/chrome_net_log.h +++ b/components/net_log/chrome_net_log.h
@@ -56,6 +56,12 @@ const base::CommandLine::StringType& command_line_string, const std::string& channel_string); + // Returns only platform-specific constants. This doesn't include the net/ + // baseline, only Chrome-specific platform information. + static std::unique_ptr<base::DictionaryValue> GetPlatformConstants( + const base::CommandLine::StringType& command_line_string, + const std::string& channel_string); + // Notify the ChromeNetLog that things are shutting-down. // // If ChromeNetLog does not outlive the TaskScheduler, there is no need to
diff --git a/components/net_log/net_export_file_writer.cc b/components/net_log/net_export_file_writer.cc index 87252ef9..6f3597f 100644 --- a/components/net_log/net_export_file_writer.cc +++ b/components/net_log/net_export_file_writer.cc
@@ -14,20 +14,12 @@ #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" #include "base/task_runner_util.h" #include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" #include "components/net_log/chrome_net_log.h" -#include "net/log/file_net_log_observer.h" -#include "net/log/net_log_util.h" -#include "net/url_request/url_request_context_getter.h" - -namespace net { -class URLRequestContext; -} namespace net_log { @@ -61,31 +53,6 @@ return results; } -// Generates net log entries for ongoing events from |context_getters| and -// adds them to |observer|. -void CreateNetLogEntriesForActiveObjects( - const NetExportFileWriter::URLRequestContextGetterList& context_getters, - net::NetLog::ThreadSafeObserver* observer) { - std::set<net::URLRequestContext*> contexts; - for (const auto& getter : context_getters) { - DCHECK(getter->GetNetworkTaskRunner()->BelongsToCurrentThread()); - contexts.insert(getter->GetURLRequestContext()); - } - net::CreateNetLogEntriesForActiveObjects(contexts, observer); -} - -// Adds net info from net::GetNetInfo() to |polled_data|. -std::unique_ptr<base::DictionaryValue> AddNetInfo( - scoped_refptr<net::URLRequestContextGetter> context_getter, - std::unique_ptr<base::DictionaryValue> polled_data) { - DCHECK(context_getter); - std::unique_ptr<base::DictionaryValue> net_info = net::GetNetInfo( - context_getter->GetURLRequestContext(), net::NET_INFO_ALL_SOURCES); - if (polled_data) - net_info->MergeDictionary(polled_data.get()); - return net_info; -} - // If running on a POSIX OS, this will attempt to set all the permission flags // of the file at |path| to 1. Will return |path| on success and the empty path // on failure. @@ -114,18 +81,19 @@ } // namespace -NetExportFileWriter::NetExportFileWriter(ChromeNetLog* chrome_net_log) +NetExportFileWriter::NetExportFileWriter() : state_(STATE_UNINITIALIZED), log_exists_(false), log_capture_mode_known_(false), log_capture_mode_(net::NetLogCaptureMode::Default()), - chrome_net_log_(chrome_net_log), default_log_base_dir_getter_(base::Bind(&base::GetTempDir)), weak_ptr_factory_(this) {} NetExportFileWriter::~NetExportFileWriter() { - if (file_net_log_observer_) - file_net_log_observer_->StopObserving(nullptr, base::Closure()); + if (net_log_exporter_) { + net_log_exporter_->Stop(base::Value(base::Value::Type::DICTIONARY), + base::DoNothing()); + } } void NetExportFileWriter::AddObserver(StateObserver* observer) { @@ -138,15 +106,10 @@ state_observer_list_.RemoveObserver(observer); } -void NetExportFileWriter::Initialize( - scoped_refptr<base::TaskRunner> net_task_runner) { +void NetExportFileWriter::Initialize() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(net_task_runner); file_task_runner_ = CreateFileTaskRunner(); - if (net_task_runner_) - DCHECK_EQ(net_task_runner_, net_task_runner); - net_task_runner_ = net_task_runner; if (state_ != STATE_UNINITIALIZED) return; @@ -168,7 +131,7 @@ uint64_t max_file_size, const base::CommandLine::StringType& command_line_string, const std::string& channel_string, - const URLRequestContextGetterList& context_getters) { + network::mojom::NetworkContext* network_context) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(file_task_runner_); @@ -184,41 +147,70 @@ NotifyStateObserversAsync(); - std::unique_ptr<base::Value> constants( - ChromeNetLog::GetConstants(command_line_string, channel_string)); + network_context->CreateNetLogExporter(mojo::MakeRequest(&net_log_exporter_)); + base::Value custom_constants = base::Value::FromUniquePtrValue( + ChromeNetLog::GetPlatformConstants(command_line_string, channel_string)); - file_net_log_observer_ = net::FileNetLogObserver::CreateBounded( - log_path_, max_file_size, std::move(constants)); - - net_task_runner_->PostTaskAndReply( - FROM_HERE, - base::Bind(&CreateNetLogEntriesForActiveObjects, context_getters, - base::Unretained(file_net_log_observer_.get())), - base::Bind( - &NetExportFileWriter::StartNetLogAfterCreateEntriesForActiveObjects, - weak_ptr_factory_.GetWeakPtr(), capture_mode)); + base::PostTaskAndReplyWithResult( + file_task_runner_.get(), FROM_HERE, + base::BindOnce(&NetExportFileWriter::CreateOutputFile, log_path_), + base::BindOnce(&NetExportFileWriter::StartNetLogAfterCreateFile, + weak_ptr_factory_.GetWeakPtr(), capture_mode, + max_file_size, std::move(custom_constants))); } -void NetExportFileWriter::StartNetLogAfterCreateEntriesForActiveObjects( - net::NetLogCaptureMode capture_mode) { +void NetExportFileWriter::StartNetLogAfterCreateFile( + net::NetLogCaptureMode capture_mode, + uint64_t max_file_size, + base::Value custom_constants, + base::File output_file) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(STATE_STARTING_LOG, state_); - state_ = STATE_LOGGING; - log_exists_ = true; - log_capture_mode_known_ = true; - log_capture_mode_ = capture_mode; + // TODO(morlovich): Communicate file open trouble better + // (https://crbug.com/838977) + if (!output_file.IsValid()) { + ResetExporterThenSetStateNotLogging(); + return; + } - NotifyStateObservers(); + network::mojom::NetLogExporter_CaptureMode rpc_capture_mode = + network::mojom::NetLogExporter::CaptureMode::DEFAULT; + if (capture_mode.include_socket_bytes()) { + rpc_capture_mode = + network::mojom::NetLogExporter::CaptureMode::INCLUDE_SOCKET_BYTES; + } else if (capture_mode.include_cookies_and_credentials()) { + rpc_capture_mode = network::mojom::NetLogExporter::CaptureMode:: + INCLUDE_COOKIES_AND_CREDENTIALS; + } - file_net_log_observer_->StartObserving(chrome_net_log_, capture_mode); + // base::Unretained(this) is safe here since |net_log_exporter_| is owned by + // |this| and is a mojo InterfacePtr, which guarantees callback cancellation + // upon its destruction. + net_log_exporter_->Start( + std::move(output_file), std::move(custom_constants), rpc_capture_mode, + max_file_size, + base::BindOnce(&NetExportFileWriter::OnStartResult, + base::Unretained(this), capture_mode)); +} + +void NetExportFileWriter::OnStartResult(net::NetLogCaptureMode capture_mode, + int result) { + if (result == net::OK) { + state_ = STATE_LOGGING; + log_exists_ = true; + log_capture_mode_known_ = true; + log_capture_mode_ = capture_mode; + + NotifyStateObservers(); + } else { + ResetExporterThenSetStateNotLogging(); + } } void NetExportFileWriter::StopNetLog( - std::unique_ptr<base::DictionaryValue> polled_data, - scoped_refptr<net::URLRequestContextGetter> context_getter) { + std::unique_ptr<base::DictionaryValue> polled_data) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(net_task_runner_); if (state_ != STATE_LOGGING) return; @@ -227,15 +219,19 @@ NotifyStateObserversAsync(); - if (context_getter) { - base::PostTaskAndReplyWithResult( - net_task_runner_.get(), FROM_HERE, - base::BindOnce(&AddNetInfo, context_getter, std::move(polled_data)), - base::BindOnce(&NetExportFileWriter::StopNetLogAfterAddNetInfo, - weak_ptr_factory_.GetWeakPtr())); - } else { - StopNetLogAfterAddNetInfo(std::move(polled_data)); - } + base::Value polled_data_value(base::Value::Type::DICTIONARY); + if (polled_data) + polled_data_value = base::Value::FromUniquePtrValue(std::move(polled_data)); + // base::Unretained(this) is safe here since |net_log_exporter_| is owned by + // |this| and is a mojo InterfacePtr, which guarantees callback cancellation + // upon its destruction. + net_log_exporter_->Stop(std::move(polled_data_value), + base::BindOnce(&NetExportFileWriter::OnStopResult, + base::Unretained(this))); +} + +void NetExportFileWriter::OnStopResult(int result) { + ResetExporterThenSetStateNotLogging(); } std::unique_ptr<base::DictionaryValue> NetExportFileWriter::GetState() const { @@ -352,23 +348,17 @@ NotifyStateObservers(); } -void NetExportFileWriter::StopNetLogAfterAddNetInfo( - std::unique_ptr<base::DictionaryValue> polled_data) { +void NetExportFileWriter::ResetExporterThenSetStateNotLogging() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_EQ(STATE_STOPPING_LOG, state_); - - file_net_log_observer_->StopObserving( - std::move(polled_data), - base::Bind(&NetExportFileWriter::ResetObserverThenSetStateNotLogging, - weak_ptr_factory_.GetWeakPtr())); -} - -void NetExportFileWriter::ResetObserverThenSetStateNotLogging() { - DCHECK(thread_checker_.CalledOnValidThread()); - file_net_log_observer_.reset(); + net_log_exporter_.reset(); state_ = STATE_NOT_LOGGING; NotifyStateObservers(); } +base::File NetExportFileWriter::CreateOutputFile(base::FilePath path) { + return base::File(path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); +} + } // namespace net_log
diff --git a/components/net_log/net_export_file_writer.h b/components/net_log/net_export_file_writer.h index f0453320..b734e5d 100644 --- a/components/net_log/net_export_file_writer.h +++ b/components/net_log/net_export_file_writer.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/command_line.h" +#include "base/files/file.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/macros.h" @@ -17,17 +18,19 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/threading/thread_checker.h" -#include "net/log/file_net_log_observer.h" +#include "base/values.h" #include "net/log/net_log_capture_mode.h" +#include "services/network/public/mojom/network_service.mojom.h" namespace base { -class DictionaryValue; class TaskRunner; } // namespace base -namespace net { -class URLRequestContextGetter; -} // namespace net +namespace network { +namespace mojom { +class NetworkContext; +} +} // namespace network namespace net_log { @@ -37,10 +40,10 @@ // It's a singleton that acts as the interface to all NetExportMessageHandlers // which can tell it to start or stop logging in response to user actions from // net-export UIs. Because it's a singleton, the logging state can be shared -// between multiple instances of the net-export UI. Internally, it manages an -// instance of net::FileNetLogObserver and handles the attaching/detaching of it -// to the ChromeNetLog. This class is used by the iOS and non-iOS -// implementations of net-export. +// between multiple instances of the net-export UI. Internally, it manages a +// pipe to an instance of network::NetLogExporter and handles the +// attaching/detaching of it to the NetLog. This class is used by the iOS and +// non-iOS implementations of net-export. // // NetExportFileWriter maintains the current logging state using the members // |state_|, |log_exists_|, |log_capture_mode_known_|, |log_capture_mode_|. @@ -52,11 +55,12 @@ // // This class is created and destroyed on the UI thread, and all public entry // points are to be called on the UI thread. Internally, the class may run some -// code on the |file_task_runner_| and |net_task_runner_|. +// code on the |file_task_runner_|. class NetExportFileWriter { public: // Special value meaning "can use an unlimited number of bytes". - static constexpr uint64_t kNoLimit = net::FileNetLogObserver::kNoLimit; + static constexpr uint64_t kNoLimit = + network::mojom::NetLogExporter::kUnlimitedFileSize; // The observer interface to be implemented by code that wishes to be notified // of NetExportFileWriter's state changes. @@ -75,8 +79,6 @@ using FilePathCallback = base::Callback<void(const base::FilePath&)>; using DirectoryGetter = base::Callback<bool(base::FilePath*)>; - using URLRequestContextGetterList = - std::vector<scoped_refptr<net::URLRequestContextGetter>>; ~NetExportFileWriter(); @@ -90,11 +92,9 @@ // Detaches a StateObserver. void RemoveObserver(StateObserver* observer); - // Initializes NetExportFileWriter if not initialized and sets the network - // task runner (used by NetExportFileWriter when querying network state). - // This task runner must not be changed once set. Calling this function again - // with the same parameter is OK. - void Initialize(scoped_refptr<base::TaskRunner> net_task_runner); + // Initializes NetExportFileWriter if not initialized. Calling this function + // again is OK. + void Initialize(); // Starts collecting NetLog data into the file at |log_path|. If |log_path| is // empty, the default log path is used. If NetExportFileWriter is already @@ -103,30 +103,21 @@ // |max_file_size| places a bound on how large the log file can grow. To make // it grow unboundedly pass kNoLimit. // - // |context_getters| is an optional list of URLRequestContextGetters used only - // to add log entries for ongoing events when logging starts. They are not - // used for retrieving polled data. All the contexts must be bound to the same - // thread. + // |network_context| will be used to append net info (from net::GetInfo()) + // at end of logging once StopNetLog is called. void StartNetLog(const base::FilePath& log_path, net::NetLogCaptureMode capture_mode, uint64_t max_file_size, const base::CommandLine::StringType& command_line_string, const std::string& channel_string, - const URLRequestContextGetterList& context_getters); + network::mojom::NetworkContext* network_context); // Stops collecting NetLog data into the file. It is a no-op if // NetExportFileWriter is currently not logging. // // |polled_data| is a JSON dictionary that will be appended to the end of the // log; it's for adding additional info to the log that aren't events. - // If |context_getter| is not null, then StopNetLog() will automatically - // append net info (from net::GetNetInfo() retrieved using |context_getter|) - // to |polled_data|. - // Note that StopNetLog() accepts (optionally) only one context getter for - // retrieving net polled data as opposed to StartNetLog() which accepts zero - // or more context getters for retrieving ongoing net events. - void StopNetLog(std::unique_ptr<base::DictionaryValue> polled_data, - scoped_refptr<net::URLRequestContextGetter> context_getter); + void StopNetLog(std::unique_ptr<base::DictionaryValue> polled_data); // Creates a DictionaryValue summary of the state of the NetExportFileWriter std::unique_ptr<base::DictionaryValue> GetState() const; @@ -156,7 +147,7 @@ protected: // Constructs a NetExportFileWriter. Only one instance is created in browser // process. - explicit NetExportFileWriter(ChromeNetLog* chrome_net_log); + NetExportFileWriter(); private: friend class ChromeNetLog; @@ -189,30 +180,30 @@ const DefaultLogPathResults& set_up_default_log_path_results); // Called internally by StartNetLog(). Contains tasks to be done to start - // logging after net log entries for ongoing events are added to the log from - // the |net_task_runner_|. - void StartNetLogAfterCreateEntriesForActiveObjects( - net::NetLogCaptureMode capture_mode); + // logging after the output file has been created. + void StartNetLogAfterCreateFile(net::NetLogCaptureMode capture_mode, + uint64_t max_file_size, + base::Value custom_constants, + base::File log_file); - // Called internally by StopNetLog(). Contains tasks to be done to stop - // logging after net-thread polled data is retrieved on the - // |net_task_runner_|. - void StopNetLogAfterAddNetInfo( - std::unique_ptr<base::DictionaryValue> polled_data); + void OnStartResult(net::NetLogCaptureMode capture_mode, int result); + void OnStopResult(int result); - // Contains tasks to be done after |file_net_log_observer_| has completely + // Contains tasks to be done after |net_log_exporter_| has completely // stopped writing. - void ResetObserverThenSetStateNotLogging(); + void ResetExporterThenSetStateNotLogging(); + + // Creates a new file for writing at |path|, trying to overwrite any existing + // file. Called on |file_task_runner_|. + static base::File CreateOutputFile(base::FilePath path); // All members are accessed solely from the main thread (the thread that // |thread_checker_| is bound to). - base::ThreadChecker thread_checker_; // Task runners for file-specific and net-specific tasks that must run on a // file or net task runner. scoped_refptr<base::TaskRunner> file_task_runner_; - scoped_refptr<base::TaskRunner> net_task_runner_; State state_; // Current logging state of NetExportFileWriter. @@ -222,13 +213,8 @@ base::FilePath log_path_; // base::FilePath to the NetLog file. - // |file_net_log_observer_| watches the NetLog event stream, and - // sends all entries to the file created in StartNetLog(). - std::unique_ptr<net::FileNetLogObserver> file_net_log_observer_; - - // The |chrome_net_log_| is owned by the browser process, cached here to avoid - // using global (g_browser_process). - ChromeNetLog* chrome_net_log_; + // Used to ask the network service to do the actual exporting. + network::mojom::NetLogExporterPtr net_log_exporter_; // List of StateObservers to notify on state changes. base::ObserverList<StateObserver, true> state_observer_list_;
diff --git a/components/net_log/net_export_file_writer_unittest.cc b/components/net_log/net_export_file_writer_unittest.cc index ebc5cf5..2dfcae0 100644 --- a/components/net_log/net_export_file_writer_unittest.cc +++ b/components/net_log/net_export_file_writer_unittest.cc
@@ -16,19 +16,22 @@ #include "base/files/scoped_temp_dir.h" #include "base/json/json_reader.h" #include "base/json/json_string_value_serializer.h" +#include "base/synchronization/waitable_event.h" #include "base/test/scoped_task_environment.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/build_config.h" -#include "components/net_log/chrome_net_log.h" #include "net/base/test_completion_callback.h" -#include "net/http/http_network_session.h" #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_event_type.h" +#include "net/test/embedded_test_server/default_handlers.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" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "net/url_request/url_request_context_getter.h" -#include "net/url_request/url_request_test_util.h" +#include "services/network/network_context.h" +#include "services/network/network_service.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/simple_url_loader.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -162,44 +165,6 @@ return ::testing::AssertionSuccess(); } -void SetUpTestContextGetterWithQuicTimeoutInfo( - net::NetLog* net_log, - int quic_idle_connection_timeout_seconds, - scoped_refptr<net::TestURLRequestContextGetter>* context_getter) { - std::unique_ptr<net::TestURLRequestContext> context = - std::make_unique<net::TestURLRequestContext>(true); - context->set_net_log(net_log); - - std::unique_ptr<net::HttpNetworkSession::Params> params( - new net::HttpNetworkSession::Params); - params->quic_idle_connection_timeout_seconds = - quic_idle_connection_timeout_seconds; - - context->set_http_network_session_params(std::move(params)); - context->Init(); - - *context_getter = new net::TestURLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get(), std::move(context)); -} - -void SetUpTestContextGetterWithRequest( - net::NetLog* net_log, - const GURL& url, - net::URLRequest::Delegate* delegate, - scoped_refptr<net::TestURLRequestContextGetter>* context_getter, - std::unique_ptr<net::URLRequest>* request) { - auto context = std::make_unique<net::TestURLRequestContext>(true); - context->set_net_log(net_log); - context->Init(); - - *request = context->CreateRequest(url, net::IDLE, delegate, - TRAFFIC_ANNOTATION_FOR_TESTS); - (*request)->Start(); - - *context_getter = new net::TestURLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get(), std::move(context)); -} - // An implementation of NetExportFileWriter::StateObserver that allows waiting // until it's notified of a new state. class TestStateObserver : public NetExportFileWriter::StateObserver { @@ -251,15 +216,23 @@ class NetExportFileWriterTest : public ::testing::Test { public: - using URLRequestContextGetterList = - std::vector<scoped_refptr<net::URLRequestContextGetter>>; - NetExportFileWriterTest() - : file_writer_(&net_log_), net_thread_("NetLogFileWriter net thread") {} + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO), + network_service_(network::NetworkService::CreateForTesting()) {} // ::testing::Test implementation void SetUp() override { ASSERT_TRUE(log_temp_dir_.CreateUniqueTempDir()); + network::mojom::NetworkContextParamsPtr params = + network::mojom::NetworkContextParams::New(); + // Use a fixed proxy config, to avoid dependencies on local network + // configuration. + params->initial_proxy_config = + net::ProxyConfigWithAnnotation::CreateDirect(); + network_context_ = std::make_unique<network::NetworkContext>( + network_service_.get(), mojo::MakeRequest(&network_context_ptr_), + std::move(params)); // Override |file_writer_|'s default-log-base-directory-getter to // a getter that returns the temp dir created for the test. @@ -268,8 +241,6 @@ default_log_path_ = log_temp_dir_.GetPath().Append(kLogRelativePath); - ASSERT_TRUE(net_thread_.Start()); - file_writer_.AddObserver(&test_state_observer_); ASSERT_TRUE(VerifyState(file_writer_.GetState(), kStateUninitializedString, @@ -291,7 +262,7 @@ WARN_UNUSED_RESULT ::testing::AssertionResult InitializeThenVerifyNewState( bool expected_initialize_success, bool expected_log_exists) { - file_writer_.Initialize(net_thread_.task_runner()); + file_writer_.Initialize(); std::unique_ptr<base::DictionaryValue> state = test_state_observer_.WaitForNewState(); ::testing::AssertionResult result = @@ -325,10 +296,10 @@ const base::FilePath& custom_log_path, net::NetLogCaptureMode capture_mode, const std::string& expected_capture_mode_string, - const URLRequestContextGetterList& context_getters) { + network::mojom::NetworkContext* network_context) { file_writer_.StartNetLog(custom_log_path, capture_mode, kMaxLogSizeBytes, base::CommandLine::StringType(), kChannelString, - context_getters); + network_context); std::unique_ptr<base::DictionaryValue> state = test_state_observer_.WaitForNewState(); ::testing::AssertionResult result = @@ -366,9 +337,8 @@ WARN_UNUSED_RESULT ::testing::AssertionResult StopThenVerifyNewStateAndFile( const base::FilePath& custom_log_path, std::unique_ptr<base::DictionaryValue> polled_data, - scoped_refptr<net::URLRequestContextGetter> context_getter, const std::string& expected_capture_mode_string) { - file_writer_.StopNetLog(std::move(polled_data), context_getter); + file_writer_.StopNetLog(std::move(polled_data)); std::unique_ptr<base::DictionaryValue> state = test_state_observer_.WaitForNewState(); ::testing::AssertionResult result = @@ -415,7 +385,7 @@ return ::testing::AssertionSuccess(); } - ChromeNetLog* net_log() { return &net_log_; } + net::NetLog* net_log() { return network_service_->net_log(); } NetExportFileWriter* file_writer() { return &file_writer_; } @@ -425,17 +395,22 @@ const base::FilePath& default_log_path() const { return default_log_path_; } - base::Thread* net_thread() { return &net_thread_; } - TestStateObserver* test_state_observer() { return &test_state_observer_; } + network::mojom::NetworkContext* network_context() { + return network_context_ptr_.get(); + } + private: base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<network::NetworkService> network_service_; - ChromeNetLog net_log_; + network::mojom::NetworkContextPtr network_context_ptr_; + std::unique_ptr<network::NetworkContext> network_context_; - // |file_writer_| is initialized after |net_log_| so that it can stop - // obvserving on destruction. + // |file_writer_| is initialized after |network_context_ptr_| since + // |file_writer_| destructor can talk to mojo objects owned by + // |network_context_|. NetExportFileWriter file_writer_; base::ScopedTempDir log_temp_dir_; @@ -443,8 +418,6 @@ // The default log path that |file_writer_| will use is cached here. base::FilePath default_log_path_; - base::Thread net_thread_; - TestStateObserver test_state_observer_; }; @@ -501,41 +474,38 @@ // StartNetLog(), should result in state change. ASSERT_TRUE(StartThenVerifyNewState(base::FilePath(), capture_modes[i], capture_mode_strings[i], - URLRequestContextGetterList())); + network_context())); // Calling StartNetLog() again should be a no-op. Try doing StartNetLog() // with various capture modes; they should all be ignored and result in no // state change. - file_writer()->StartNetLog(base::FilePath(), capture_modes[i], - kMaxLogSizeBytes, - base::CommandLine::StringType(), kChannelString, - URLRequestContextGetterList()); - file_writer()->StartNetLog(base::FilePath(), capture_modes[(i + 1) % 3], - kMaxLogSizeBytes, - base::CommandLine::StringType(), kChannelString, - URLRequestContextGetterList()); - file_writer()->StartNetLog(base::FilePath(), capture_modes[(i + 2) % 3], - kMaxLogSizeBytes, - base::CommandLine::StringType(), kChannelString, - URLRequestContextGetterList()); + file_writer()->StartNetLog( + base::FilePath(), capture_modes[i], kMaxLogSizeBytes, + base::CommandLine::StringType(), kChannelString, network_context()); + file_writer()->StartNetLog( + base::FilePath(), capture_modes[(i + 1) % 3], kMaxLogSizeBytes, + base::CommandLine::StringType(), kChannelString, network_context()); + file_writer()->StartNetLog( + base::FilePath(), capture_modes[(i + 2) % 3], kMaxLogSizeBytes, + base::CommandLine::StringType(), kChannelString, network_context()); // StopNetLog(), should result in state change. The capture mode should // match that of the first StartNetLog() call (called by // StartThenVerifyNewState()). - ASSERT_TRUE(StopThenVerifyNewStateAndFile( - base::FilePath(), nullptr, nullptr, capture_mode_strings[i])); + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, + capture_mode_strings[i])); // Stopping a second time should be a no-op. - file_writer()->StopNetLog(nullptr, nullptr); + file_writer()->StopNetLog(nullptr); } // Start and stop one more time just to make sure the last StopNetLog() call // was properly ignored and left |file_writer_| in a valid state. ASSERT_TRUE(StartThenVerifyNewState(base::FilePath(), capture_modes[0], capture_mode_strings[0], - URLRequestContextGetterList())); + network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, capture_mode_strings[0])); } @@ -546,9 +516,9 @@ ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, kCaptureModeDefaultString)); int64_t stop_file_size; @@ -567,9 +537,9 @@ // before adding the junk data. ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, kCaptureModeDefaultString)); int64_t new_stop_file_size; @@ -585,9 +555,9 @@ ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, kCaptureModeDefaultString)); // Get file size without the event. @@ -596,11 +566,11 @@ ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); net_log()->AddGlobalEntry(net::NetLogEventType::CANCELLED); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, kCaptureModeDefaultString)); // Get file size after adding the event and make sure it's larger than before. @@ -623,9 +593,9 @@ ASSERT_TRUE(StartThenVerifyNewState( custom_log_path, net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(custom_log_path, nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(custom_log_path, nullptr, kCaptureModeDefaultString)); // Get file size without the event. @@ -634,11 +604,11 @@ ASSERT_TRUE(StartThenVerifyNewState( custom_log_path, net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); net_log()->AddGlobalEntry(net::NetLogEventType::CANCELLED); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(custom_log_path, nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(custom_log_path, nullptr, kCaptureModeDefaultString)); // Get file size after adding the event and make sure it's larger than before. @@ -647,7 +617,7 @@ EXPECT_GE(new_stop_file_size, stop_file_size); } -TEST_F(NetExportFileWriterTest, StopWithPolledDataAndContextGetter) { +TEST_F(NetExportFileWriterTest, StopWithPolledData) { ASSERT_TRUE(InitializeThenVerifyNewState(true, false)); // Create dummy polled data @@ -657,24 +627,13 @@ std::make_unique<base::DictionaryValue>(); dummy_polled_data->SetString(kDummyPolledDataPath, kDummyPolledDataString); - // Create test context getter on |net_thread_| and wait for it to finish. - scoped_refptr<net::TestURLRequestContextGetter> context_getter; - const int kDummyQuicParam = 75; - net::TestClosure init_done; - net_thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&SetUpTestContextGetterWithQuicTimeoutInfo, net_log(), - kDummyQuicParam, &context_getter), - init_done.closure()); - init_done.WaitForResult(); - ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, URLRequestContextGetterList())); + kCaptureModeDefaultString, network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile( - base::FilePath(), std::move(dummy_polled_data), context_getter, - kCaptureModeDefaultString)); + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), + std::move(dummy_polled_data), + kCaptureModeDefaultString)); // Read polledData from log file. std::unique_ptr<base::DictionaryValue> root; @@ -687,44 +646,74 @@ ASSERT_TRUE(polled_data->GetString(kDummyPolledDataPath, &dummy_string)); EXPECT_EQ(kDummyPolledDataString, dummy_string); - // Check that it also contains the field from the URLRequestContext that was - // passed in. - base::DictionaryValue* quic_info; - ASSERT_TRUE(polled_data->GetDictionary("quicInfo", &quic_info)); - base::Value* timeout_value = nullptr; - int timeout; - ASSERT_TRUE( - quic_info->Get("idle_connection_timeout_seconds", &timeout_value)); - ASSERT_TRUE(timeout_value->GetAsInteger(&timeout)); - EXPECT_EQ(kDummyQuicParam, timeout); + // Check that it also contains something from net::GetNetInfo. + base::DictionaryValue* http_cache_info; + ASSERT_TRUE(polled_data->GetDictionary("httpCacheInfo", &http_cache_info)); } -TEST_F(NetExportFileWriterTest, StartWithContextGetters) { +// Test with requests in flight. This is done by going through a sequence of a +// redirect --- at which point the log is started --- and then a fetch of +// destination that's blocked on an event in EmbeddedTestServer. +TEST_F(NetExportFileWriterTest, StartWithNetworkContextActive) { + net::EmbeddedTestServer test_server; + net::test_server::RegisterDefaultHandlers(&test_server); + + base::WaitableEvent block_fetch( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + + test_server.RegisterRequestHandler(base::BindRepeating( + [](base::WaitableEvent* block_fetch, + const net::test_server::HttpRequest& request) + -> std::unique_ptr<net::test_server::HttpResponse> { + if (request.relative_url == "/block") + block_fetch->Wait(); + return nullptr; + }, + &block_fetch)); + + ASSERT_TRUE(test_server.Start()); + ASSERT_TRUE(InitializeThenVerifyNewState(true, false)); - // Create test context getter and request on |net_thread_| and wait for it to - // finish. - const std::string kDummyUrl = "blah:blah"; - scoped_refptr<net::TestURLRequestContextGetter> context_getter; - std::unique_ptr<net::URLRequest> request; - net::TestDelegate delegate; - delegate.set_quit_on_complete(false); + network::mojom::URLLoaderFactoryPtr url_loader_factory; + network_context()->CreateURLLoaderFactory( + mojo::MakeRequest(&url_loader_factory), 0); - net::TestClosure init_done; - net_thread()->task_runner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&SetUpTestContextGetterWithRequest, net_log(), GURL(kDummyUrl), - &delegate, &context_getter, &request), - init_done.closure()); - init_done.WaitForResult(); + const char kRedirectURL[] = "/server-redirect?/block"; + std::unique_ptr<network::ResourceRequest> request = + std::make_unique<network::ResourceRequest>(); + request->url = test_server.GetURL(kRedirectURL); + std::unique_ptr<network::SimpleURLLoader> simple_loader = + network::SimpleURLLoader::Create(std::move(request), + TRAFFIC_ANNOTATION_FOR_TESTS); + base::RunLoop run_loop, run_loop2; + simple_loader->SetOnRedirectCallback(base::BindRepeating( + [](base::RepeatingClosure notify_log, + const net::RedirectInfo& redirect_info, + const network::ResourceResponseHead& response_head) { + notify_log.Run(); + }, + run_loop.QuitClosure())); + simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory.get(), + base::BindOnce( + [](base::OnceClosure quit_closure, + std::unique_ptr<std::string> response_body) { + std::move(quit_closure).Run(); + }, + run_loop2.QuitClosure())); + + // Wait for fetch to get some bytes accross. It will not be the entire + // thing since the post-redirect URL will get blocked by the custom handler. + run_loop.Run(); ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::Default(), - kCaptureModeDefaultString, {context_getter})); + kCaptureModeDefaultString, network_context())); - ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, nullptr, + ASSERT_TRUE(StopThenVerifyNewStateAndFile(base::FilePath(), nullptr, kCaptureModeDefaultString)); - // Read events from log file. std::unique_ptr<base::DictionaryValue> root; ASSERT_TRUE(ReadCompleteLogFile(default_log_path(), &root)); @@ -732,7 +721,7 @@ ASSERT_TRUE(root->GetList("events", &events)); // Check there is at least one event as a result of the ongoing request. - EXPECT_GE(events->GetSize(), 1u); + ASSERT_GE(events->GetSize(), 1u); // Check the URL in the params of the first event. base::DictionaryValue* event; @@ -741,24 +730,24 @@ EXPECT_TRUE(event->GetDictionary("params", &event_params)); std::string event_url; EXPECT_TRUE(event_params->GetString("url", &event_url)); - EXPECT_EQ(kDummyUrl, event_url); + EXPECT_EQ(test_server.GetURL(kRedirectURL), event_url); - net_thread()->task_runner()->DeleteSoon(FROM_HERE, request.release()); + block_fetch.Signal(); + run_loop2.Run(); } TEST_F(NetExportFileWriterTest, ReceiveStartWhileInitializing) { // Trigger initialization of |file_writer_|. - file_writer()->Initialize(net_thread()->task_runner()); + file_writer()->Initialize(); // Before running the main message loop, tell |file_writer_| to start // logging. Not running the main message loop prevents the initialization // process from completing, so this ensures that StartNetLog() is received // before |file_writer_| finishes initialization, which means this // should be a no-op. - file_writer()->StartNetLog(base::FilePath(), - net::NetLogCaptureMode::Default(), - kMaxLogSizeBytes, base::CommandLine::StringType(), - kChannelString, URLRequestContextGetterList()); + file_writer()->StartNetLog( + base::FilePath(), net::NetLogCaptureMode::Default(), kMaxLogSizeBytes, + base::CommandLine::StringType(), kChannelString, network_context()); // Now run the main message loop. Make sure StartNetLog() was ignored by // checking that the next two states are "initializing" followed by @@ -777,20 +766,19 @@ // Call StartNetLog() on |file_writer_| and wait for the state change. ASSERT_TRUE(StartThenVerifyNewState( base::FilePath(), net::NetLogCaptureMode::IncludeSocketBytes(), - kCaptureModeIncludeSocketBytesString, URLRequestContextGetterList())); + kCaptureModeIncludeSocketBytesString, network_context())); // Tell |file_writer_| to stop logging. - file_writer()->StopNetLog(nullptr, nullptr); + file_writer()->StopNetLog(nullptr); // Before running the main message loop, tell |file_writer_| to start // logging. Not running the main message loop prevents the stopping process // from completing, so this ensures StartNetLog() is received before // |file_writer_| finishes stopping, which means this should be a // no-op. - file_writer()->StartNetLog(base::FilePath(), - net::NetLogCaptureMode::Default(), - kMaxLogSizeBytes, base::CommandLine::StringType(), - kChannelString, URLRequestContextGetterList()); + file_writer()->StartNetLog( + base::FilePath(), net::NetLogCaptureMode::Default(), kMaxLogSizeBytes, + base::CommandLine::StringType(), kChannelString, network_context()); // Now run the main message loop. Make sure the last StartNetLog() was // ignored by checking that the next two states are "stopping-log" followed by
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc index 0fc12b6b..ce663a2 100644 --- a/components/ntp_snippets/content_suggestions_service.cc +++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -18,6 +18,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_clock.h" #include "base/values.h" +#include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" @@ -295,7 +296,8 @@ })"); large_icon_service_ ->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - publisher_url, minimum_size_in_pixel, desired_size_in_pixel, + favicon::FaviconServerFetcherParams::CreateForMobile( + publisher_url, minimum_size_in_pixel, desired_size_in_pixel), /*may_page_url_be_private=*/false, traffic_annotation, base::Bind( &ContentSuggestionsService::OnGetFaviconFromGoogleServerFinished,
diff --git a/components/ntp_snippets_strings_grdp/OWNERS b/components/ntp_snippets_strings_grdp/OWNERS new file mode 100644 index 0000000..c7f9cc3f --- /dev/null +++ b/components/ntp_snippets_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/ntp_snippets/OWNERS
diff --git a/components/ntp_snippets_strings_grdp/README.md b/components/ntp_snippets_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/ntp_snippets_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/ntp_tiles/icon_cacher_impl.cc b/components/ntp_tiles/icon_cacher_impl.cc index ad8cfdd..2b5853e 100644 --- a/components/ntp_tiles/icon_cacher_impl.cc +++ b/components/ntp_tiles/icon_cacher_impl.cc
@@ -8,6 +8,7 @@ #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" +#include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon/core/favicon_util.h" #include "components/favicon/core/large_icon_service.h" @@ -264,9 +265,10 @@ })"); large_icon_service_ ->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - page_url, - GetMinimumFetchingSizeForChromeSuggestionsFaviconsFromServer(), - GetDesiredFetchingSizeForChromeSuggestionsFaviconsFromServer(), + favicon::FaviconServerFetcherParams::CreateForMobile( + page_url, + GetMinimumFetchingSizeForChromeSuggestionsFaviconsFromServer(), + GetDesiredFetchingSizeForChromeSuggestionsFaviconsFromServer()), /*may_page_url_be_private=*/true, traffic_annotation, base::Bind(&IconCacherImpl::OnMostLikelyFaviconDownloaded, weak_ptr_factory_.GetWeakPtr(), page_url));
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn index b2f88908..e4d2bf8a 100644 --- a/components/offline_pages/core/BUILD.gn +++ b/components/offline_pages/core/BUILD.gn
@@ -36,6 +36,8 @@ "model/get_pages_task.h", "model/get_thumbnail_task.cc", "model/get_thumbnail_task.h", + "model/has_thumbnail_task.cc", + "model/has_thumbnail_task.h", "model/mark_page_accessed_task.cc", "model/mark_page_accessed_task.h", "model/offline_page_model_taskified.cc", @@ -166,6 +168,7 @@ "model/delete_page_task_unittest.cc", "model/get_pages_task_unittest.cc", "model/get_thumbnail_task_unittest.cc", + "model/has_thumbnail_task_unittest.cc", "model/mark_page_accessed_task_unittest.cc", "model/offline_page_model_taskified_unittest.cc", "model/offline_page_model_utils_unittest.cc",
diff --git a/components/offline_pages/core/model/has_thumbnail_task.cc b/components/offline_pages/core/model/has_thumbnail_task.cc new file mode 100644 index 0000000..695f81e --- /dev/null +++ b/components/offline_pages/core/model/has_thumbnail_task.cc
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/offline_pages/core/model/has_thumbnail_task.h" + +#include "components/offline_pages/core/offline_page_metadata_store_sql.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "sql/transaction.h" + +namespace offline_pages { + +namespace { + +bool ThumbnailExistsSync(int64_t offline_id, sql::Connection* db) { + static const char kSql[] = + "SELECT 1 FROM page_thumbnails WHERE offline_id = ?"; + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt64(0, offline_id); + return statement.Step(); +} + +} // namespace + +HasThumbnailTask::HasThumbnailTask(OfflinePageMetadataStoreSQL* store, + int64_t offline_id, + ThumbnailExistsCallback exists_callback) + : store_(store), + offline_id_(offline_id), + exists_callback_(std::move(exists_callback)), + weak_ptr_factory_(this) {} + +HasThumbnailTask::~HasThumbnailTask() = default; + +void HasThumbnailTask::Run() { + store_->Execute(base::BindOnce(ThumbnailExistsSync, std::move(offline_id_)), + base::BindOnce(&HasThumbnailTask::OnThumbnailExists, + weak_ptr_factory_.GetWeakPtr())); +} + +void HasThumbnailTask::OnThumbnailExists(bool exists) { + TaskComplete(); + std::move(exists_callback_).Run(exists); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/model/has_thumbnail_task.h b/components/offline_pages/core/model/has_thumbnail_task.h new file mode 100644 index 0000000..80b53d8cc --- /dev/null +++ b/components/offline_pages/core/model/has_thumbnail_task.h
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_HAS_THUMBNAIL_TASK_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_HAS_THUMBNAIL_TASK_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/task.h" + +namespace offline_pages { +class OfflinePageMetadataStoreSQL; + +// Checks if a thumbnail exists for the specified offline id. +class HasThumbnailTask : public Task { + public: + using ThumbnailExistsCallback = base::OnceCallback<void(bool)>; + + HasThumbnailTask(OfflinePageMetadataStoreSQL* store, + int64_t offline_id, + ThumbnailExistsCallback exists_callback); + ~HasThumbnailTask() override; + + // Task implementation: + void Run() override; + + private: + void OnThumbnailExists(bool exists); + + OfflinePageMetadataStoreSQL* store_; + int64_t offline_id_; + ThumbnailExistsCallback exists_callback_; + base::WeakPtrFactory<HasThumbnailTask> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(HasThumbnailTask); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_HAS_THUMBNAIL_TASK_H_
diff --git a/components/offline_pages/core/model/has_thumbnail_task_unittest.cc b/components/offline_pages/core/model/has_thumbnail_task_unittest.cc new file mode 100644 index 0000000..147330e --- /dev/null +++ b/components/offline_pages/core/model/has_thumbnail_task_unittest.cc
@@ -0,0 +1,46 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/offline_pages/core/model/has_thumbnail_task.h" + +#include <memory> + +#include "base/bind_helpers.h" +#include "base/test/bind_test_util.h" +#include "base/test/mock_callback.h" +#include "components/offline_pages/core/model/model_task_test_base.h" +#include "components/offline_pages/core/model/store_thumbnail_task.h" +#include "components/offline_pages/core/offline_store_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { +namespace { + +using ThumbnailExistsCallback = HasThumbnailTask::ThumbnailExistsCallback; + +class HasThumbnailTaskTest : public ModelTaskTestBase {}; + +TEST_F(HasThumbnailTaskTest, CorrectlyFindsById) { + const int64_t valid_offline_id = 1; + const int64_t invalid_offline_id = 2; + OfflinePageThumbnail thumb; + thumb.offline_id = valid_offline_id; + thumb.expiration = store_utils::FromDatabaseTime(1234); + thumb.thumbnail = "123abc"; + RunTask( + std::make_unique<StoreThumbnailTask>(store(), thumb, base::DoNothing())); + + base::MockCallback<ThumbnailExistsCallback> exists_callback; + EXPECT_CALL(exists_callback, Run(true)); + RunTask(std::make_unique<HasThumbnailTask>(store(), valid_offline_id, + exists_callback.Get())); + + base::MockCallback<ThumbnailExistsCallback> doesnt_exist_callback; + EXPECT_CALL(doesnt_exist_callback, Run(false)); + RunTask(std::make_unique<HasThumbnailTask>(store(), invalid_offline_id, + doesnt_exist_callback.Get())); +} + +} // namespace +} // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.cc b/components/offline_pages/core/model/offline_page_model_taskified.cc index a9a580f..afc579cc 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -26,6 +26,7 @@ #include "components/offline_pages/core/model/delete_page_task.h" #include "components/offline_pages/core/model/get_pages_task.h" #include "components/offline_pages/core/model/get_thumbnail_task.h" +#include "components/offline_pages/core/model/has_thumbnail_task.h" #include "components/offline_pages/core/model/mark_page_accessed_task.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" #include "components/offline_pages/core/model/persistent_page_consistency_check_task.h" @@ -426,6 +427,13 @@ store_.get(), offline_id, std::move(callback))); } +void OfflinePageModelTaskified::HasThumbnailForOfflineId( + int64_t offline_id, + base::OnceCallback<void(bool)> callback) { + task_queue_.AddTask(std::make_unique<HasThumbnailTask>( + store_.get(), offline_id, std::move(callback))); +} + const base::FilePath& OfflinePageModelTaskified::GetInternalArchiveDirectory( const std::string& name_space) const { if (policy_controller_->IsRemovedOnCacheReset(name_space))
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.h b/components/offline_pages/core/model/offline_page_model_taskified.h index 52215f2a1..adfb81d 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.h +++ b/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -135,6 +135,9 @@ int64_t offline_id, base::OnceCallback<void(std::unique_ptr<OfflinePageThumbnail>)> callback) override; + void HasThumbnailForOfflineId( + int64_t offline_id, + base::OnceCallback<void(bool)> callback) override; const base::FilePath& GetInternalArchiveDirectory( const std::string& name_space) const override;
diff --git a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc index 714f403b..0a7d610 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
@@ -162,20 +162,6 @@ return model_->last_maintenance_tasks_schedule_time_; } - std::unique_ptr<OfflinePageThumbnail> GetThumbnailSync(int64_t offline_id) { - bool called = false; - std::unique_ptr<OfflinePageThumbnail> result; - auto callback = base::BindLambdaForTesting( - [&](std::unique_ptr<OfflinePageThumbnail> thumbnail) { - called = true; - result = std::move(thumbnail); - }); - model_->GetThumbnailByOfflineId(offline_id, callback); - PumpLoop(); - EXPECT_TRUE(called); - return result; - } - private: scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; @@ -1666,7 +1652,8 @@ 0); } -TEST_F(OfflinePageModelTaskifiedTest, StoreAndGetThumbnail) { +TEST_F(OfflinePageModelTaskifiedTest, StoreAndCheckThumbnail) { + // Store a thumbnail. OfflinePageThumbnail thumb; thumb.offline_id = 1; thumb.expiration = base::Time::Now(); @@ -1675,12 +1662,21 @@ EXPECT_CALL(*this, ThumbnailAdded(_, thumb)); PumpLoop(); + // Check it exists + bool thumbnail_exists = false; + auto exists_callback = base::BindLambdaForTesting( + [&](bool exists) { thumbnail_exists = exists; }); + model()->HasThumbnailForOfflineId(thumb.offline_id, exists_callback); + PumpLoop(); + EXPECT_TRUE(thumbnail_exists); + + // Obtain its data. std::unique_ptr<OfflinePageThumbnail> result_thumbnail; - auto callback = base::BindLambdaForTesting( + auto data_callback = base::BindLambdaForTesting( [&](std::unique_ptr<OfflinePageThumbnail> result) { result_thumbnail = std::move(result); }); - model()->GetThumbnailByOfflineId(thumb.offline_id, callback); + model()->GetThumbnailByOfflineId(thumb.offline_id, data_callback); PumpLoop(); EXPECT_EQ(thumb, *result_thumbnail); }
diff --git a/components/offline_pages/core/offline_page_model.h b/components/offline_pages/core/offline_page_model.h index 141e59c..599de5b 100644 --- a/components/offline_pages/core/offline_page_model.h +++ b/components/offline_pages/core/offline_page_model.h
@@ -231,6 +231,12 @@ virtual void GetThumbnailByOfflineId(int64_t offline_id, GetThumbnailCallback callback) = 0; + // Checks if a thumbnail for a specific |offline_id| exists in the + // page_thumbnails table. Calls callback with the bool result. + virtual void HasThumbnailForOfflineId( + int64_t offline_id, + base::OnceCallback<void(bool)> callback) = 0; + // Publishes an offline page from the internal offline page directory. This // includes putting it in a public directory, updating the system download // manager, if any, and updating the offline page model database.
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_task.cc b/components/offline_pages/core/prefetch/generate_page_bundle_task.cc index 345d38bf..adc45fb 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_task.cc +++ b/components/offline_pages/core/prefetch/generate_page_bundle_task.cc
@@ -8,7 +8,9 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/time/default_clock.h" +#include "components/offline_pages/core/client_id.h" #include "components/offline_pages/core/offline_store_utils.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h" #include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h" @@ -18,19 +20,32 @@ #include "sql/transaction.h" namespace offline_pages { + +// A wrapper for two vectors, one with string URLs and one with offline and +// client ids pairs, each holding data for the same set of prefetch items. +struct GeneratePageBundleTask::UrlAndIds { + std::vector<std::string> urls; + PrefetchDispatcher::IdsVector ids; +}; + namespace { +using UrlAndIds = GeneratePageBundleTask::UrlAndIds; + // Temporary storage for Urls metadata fetched from the storage. struct FetchedUrl { FetchedUrl() = default; FetchedUrl(int64_t offline_id, + ClientId client_id, const std::string& requested_url, int generate_bundle_attempts) : offline_id(offline_id), + client_id(client_id), requested_url(requested_url), generate_bundle_attempts(generate_bundle_attempts) {} int64_t offline_id; + ClientId client_id; std::string requested_url; int generate_bundle_attempts; }; @@ -58,7 +73,8 @@ std::unique_ptr<std::vector<FetchedUrl>> FetchUrlsSync(sql::Connection* db) { static const char kSql[] = - "SELECT offline_id, requested_url, generate_bundle_attempts" + "SELECT offline_id, client_namespace, client_id, requested_url," + " generate_bundle_attempts" " FROM prefetch_items" " WHERE state = ?" " ORDER BY creation_time DESC"; @@ -67,10 +83,15 @@ auto urls = std::make_unique<std::vector<FetchedUrl>>(); while (statement.Step()) { - urls->push_back( - FetchedUrl(statement.ColumnInt64(0), // offline_id - statement.ColumnString(1), // requested_url - statement.ColumnInt(2))); // generate_bundle_attempts + urls->push_back(FetchedUrl( + // offline_id + statement.ColumnInt64(0), + // client_id + {statement.ColumnString(1), statement.ColumnString(2)}, + // requested_url + statement.ColumnString(3), + // generate_bundle_attempts + statement.ColumnInt(4))); } return urls; @@ -88,9 +109,8 @@ return statement.Run(); } -std::unique_ptr<std::vector<std::string>> SelectUrlsToPrefetchSync( - base::Clock* clock, - sql::Connection* db) { +std::unique_ptr<UrlAndIds> SelectUrlsToPrefetchSync(base::Clock* clock, + sql::Connection* db) { if (!db) return nullptr; @@ -112,26 +132,29 @@ urls->resize(kMaxUrlsToSend); } - auto url_specs = std::make_unique<std::vector<std::string>>(); + auto url_and_ids = std::make_unique<UrlAndIds>(); for (const auto& url : *urls) { if (!UpdateStateSync(db, url.offline_id, clock)) return nullptr; - url_specs->push_back(std::move(url.requested_url)); + url_and_ids->urls.push_back(std::move(url.requested_url)); + url_and_ids->ids.push_back({url.offline_id, std::move(url.client_id)}); } if (!transaction.Commit()) return nullptr; - return url_specs; + return url_and_ids; } } // namespace GeneratePageBundleTask::GeneratePageBundleTask( + PrefetchDispatcher* prefetch_dispatcher, PrefetchStore* prefetch_store, PrefetchGCMHandler* gcm_handler, PrefetchNetworkRequestFactory* request_factory, const PrefetchRequestFinishedCallback& callback) : clock_(base::DefaultClock::GetInstance()), + prefetch_dispatcher_(prefetch_dispatcher), prefetch_store_(prefetch_store), gcm_handler_(gcm_handler), request_factory_(request_factory), @@ -152,23 +175,30 @@ } void GeneratePageBundleTask::StartGeneratePageBundle( - std::unique_ptr<std::vector<std::string>> urls) { - if (!urls || urls->empty()) { + std::unique_ptr<UrlAndIds> url_and_ids) { + if (!url_and_ids) { TaskComplete(); return; } + DCHECK(!url_and_ids->urls.empty()); + DCHECK_EQ(url_and_ids->urls.size(), url_and_ids->ids.size()); - gcm_handler_->GetGCMToken( - base::Bind(&GeneratePageBundleTask::GotRegistrationId, - weak_factory_.GetWeakPtr(), base::Passed(std::move(urls)))); + gcm_handler_->GetGCMToken(base::AdaptCallbackForRepeating(base::BindOnce( + &GeneratePageBundleTask::GotRegistrationId, weak_factory_.GetWeakPtr(), + base::Passed(std::move(url_and_ids))))); } void GeneratePageBundleTask::GotRegistrationId( - std::unique_ptr<std::vector<std::string>> urls, + std::unique_ptr<UrlAndIds> url_and_ids, const std::string& id, instance_id::InstanceID::Result result) { + DCHECK(url_and_ids); // TODO(dimich): Add UMA reporting on instance_id::InstanceID::Result. - request_factory_->MakeGeneratePageBundleRequest(*urls, id, callback_); + request_factory_->MakeGeneratePageBundleRequest(url_and_ids->urls, id, + callback_); + prefetch_dispatcher_->GeneratePageBundleRequested( + std::make_unique<PrefetchDispatcher::IdsVector>( + std::move(url_and_ids->ids))); TaskComplete(); }
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_task.h b/components/offline_pages/core/prefetch/generate_page_bundle_task.h index 7228eec..0430164 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_task.h +++ b/components/offline_pages/core/prefetch/generate_page_bundle_task.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/clock.h" #include "components/gcm_driver/instance_id/instance_id.h" +#include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" #include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/task.h" @@ -24,7 +25,10 @@ // determined are viable to prefetch. class GeneratePageBundleTask : public Task { public: - GeneratePageBundleTask(PrefetchStore* prefetch_store, + struct UrlAndIds; + + GeneratePageBundleTask(PrefetchDispatcher* prefetch_dispatcher, + PrefetchStore* prefetch_store, PrefetchGCMHandler* gcm_handler, PrefetchNetworkRequestFactory* request_factory, const PrefetchRequestFinishedCallback& callback); @@ -36,13 +40,14 @@ void SetClockForTesting(base::Clock* clock); private: - void StartGeneratePageBundle(std::unique_ptr<std::vector<std::string>> urls); - void GotRegistrationId(std::unique_ptr<std::vector<std::string>> urls, + void StartGeneratePageBundle(std::unique_ptr<UrlAndIds> url_and_ids); + void GotRegistrationId(std::unique_ptr<UrlAndIds> url_and_ids, const std::string& id, instance_id::InstanceID::Result result); base::Clock* clock_; + PrefetchDispatcher* prefetch_dispatcher_; PrefetchStore* prefetch_store_; PrefetchGCMHandler* gcm_handler_; PrefetchNetworkRequestFactory* request_factory_;
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_task_unittest.cc b/components/offline_pages/core/prefetch/generate_page_bundle_task_unittest.cc index e185d99..0394acb 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_task_unittest.cc +++ b/components/offline_pages/core/prefetch/generate_page_bundle_task_unittest.cc
@@ -4,6 +4,8 @@ #include "components/offline_pages/core/prefetch/generate_page_bundle_task.h" +#include <utility> + #include "base/logging.h" #include "base/test/mock_callback.h" #include "base/test/simple_test_clock.h" @@ -14,6 +16,7 @@ #include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" #include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h" +#include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h" #include "components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h" #include "components/offline_pages/core/task.h" #include "testing/gmock/include/gmock/gmock.h" @@ -35,8 +38,11 @@ TestPrefetchGCMHandler* gcm_handler() { return &gcm_handler_; } + TestPrefetchDispatcher* dispatcher() { return &dispatcher_; } + private: TestPrefetchGCMHandler gcm_handler_; + TestPrefetchDispatcher dispatcher_; }; TEST_F(GeneratePageBundleTaskTest, StoreFailure) { @@ -44,17 +50,21 @@ base::MockCallback<PrefetchRequestFinishedCallback> callback; RunTask(std::make_unique<GeneratePageBundleTask>( - store(), gcm_handler(), prefetch_request_factory(), callback.Get())); + dispatcher(), store(), gcm_handler(), prefetch_request_factory(), + callback.Get())); + EXPECT_EQ(0, dispatcher()->generate_page_bundle_requested); } TEST_F(GeneratePageBundleTaskTest, EmptyTask) { base::MockCallback<PrefetchRequestFinishedCallback> callback; RunTask(std::make_unique<GeneratePageBundleTask>( - store(), gcm_handler(), prefetch_request_factory(), callback.Get())); + dispatcher(), store(), gcm_handler(), prefetch_request_factory(), + callback.Get())); EXPECT_FALSE(prefetch_request_factory()->HasOutstandingRequests()); auto requested_urls = prefetch_request_factory()->GetAllUrlsRequested(); EXPECT_TRUE(requested_urls->empty()); + EXPECT_EQ(0, dispatcher()->generate_page_bundle_requested); } TEST_F(GeneratePageBundleTaskTest, TaskMakesNetworkRequest) { @@ -62,6 +72,7 @@ base::SimpleTestClock clock; + // This item will be sent with the bundle request. PrefetchItem item1 = item_generator()->CreateItem(PrefetchItemState::NEW_REQUEST); item1.freshness_time = clock.Now(); @@ -70,6 +81,8 @@ clock.Advance(base::TimeDelta::FromSeconds(1)); + // This item will also be sent with the bundle request but being the freshest + // it will come first in the list. PrefetchItem item2 = item_generator()->CreateItem(PrefetchItemState::NEW_REQUEST); item1.freshness_time = clock.Now(); @@ -82,18 +95,33 @@ PrefetchItem item3 = item_generator()->CreateItem(PrefetchItemState::FINISHED); EXPECT_TRUE(store_util()->InsertPrefetchItem(item3)); + EXPECT_NE(item3.offline_id, item1.offline_id); + EXPECT_NE(item3.offline_id, item2.offline_id); EXPECT_EQ(3, store_util()->CountPrefetchItems()); clock.Advance(base::TimeDelta::FromHours(1)); - GeneratePageBundleTask task(store(), gcm_handler(), + GeneratePageBundleTask task(dispatcher(), store(), gcm_handler(), prefetch_request_factory(), request_callback.Get()); task.SetClockForTesting(&clock); RunTask(&task); - auto requested_urls = prefetch_request_factory()->GetAllUrlsRequested(); + // Note: even though the requested URLs checked further below are in undefined + // order (due to use of std::set) their order of requesting is known: latest + // creation dates should come first. But as these ids are stored in a + // std::vector we can rely on the order being correct. + EXPECT_EQ(1, dispatcher()->generate_page_bundle_requested); + EXPECT_EQ(2u, dispatcher()->ids_from_generate_page_bundle_requested->size()); + EXPECT_EQ(std::make_pair(item1.offline_id, item1.client_id), + dispatcher()->ids_from_generate_page_bundle_requested->at(1)); + EXPECT_EQ(std::make_pair(item2.offline_id, item2.client_id), + dispatcher()->ids_from_generate_page_bundle_requested->at(0)); + + std::unique_ptr<std::set<std::string>> requested_urls = + prefetch_request_factory()->GetAllUrlsRequested(); + EXPECT_EQ(2u, requested_urls->size()); EXPECT_THAT(*requested_urls, Contains(item1.url.spec())); EXPECT_THAT(*requested_urls, Contains(item2.url.spec())); EXPECT_THAT(*requested_urls, Not(Contains(item3.url.spec())));
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher.h b/components/offline_pages/core/prefetch/prefetch_dispatcher.h index 0cfc6cf..f1e551d 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher.h
@@ -44,6 +44,9 @@ // Reconcilers during BackgroundTask processing. class PrefetchDispatcher { public: + // Vector of pairs of offline and client IDs. + using IdsVector = std::vector<std::pair<int64_t, ClientId>>; + virtual ~PrefetchDispatcher() = default; // Initializes the dispatcher with its respective service instance. This must @@ -104,6 +107,9 @@ const std::map<std::string, std::pair<base::FilePath, int64_t>>& success_downloads) = 0; + // Called when a GeneratePageBundle request has been sent. + virtual void GeneratePageBundleRequested(std::unique_ptr<IdsVector> ids) = 0; + // Called when a download is completed successfully or fails. virtual void DownloadCompleted( const PrefetchDownloadResult& download_result) = 0;
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc index c1b0441c..69ae1afd 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -4,6 +4,7 @@ #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h" +#include <algorithm> #include <utility> #include "base/bind.h" @@ -49,26 +50,11 @@ namespace offline_pages { namespace { + void DeleteBackgroundTaskHelper(std::unique_ptr<PrefetchBackgroundTask> task) { task.reset(); } -void FetchComplete(OfflinePageModel* offline_model, - int64_t offline_id, - const std::string& image_data) { - if (image_data.empty()) - return; - // Thumbnails are marked to expire after this delta. Expired thumbnails are - // eventually deleted if their offline_id does not correspond to an offline - // item. Two days gives us plenty of time so that the prefetched item can be - // imported into the offline item database. - const base::TimeDelta kThumbnailExpirationDelta = - base::TimeDelta::FromDays(2); - - offline_model->StoreThumbnail(OfflinePageThumbnail( - offline_id, base::Time::Now() + kThumbnailExpirationDelta, image_data)); -} - } // namespace PrefetchDispatcherImpl::PrefetchDispatcherImpl() @@ -230,7 +216,7 @@ std::unique_ptr<Task> generate_page_bundle_task = std::make_unique<GeneratePageBundleTask>( - service_->GetPrefetchStore(), service_->GetPrefetchGCMHandler(), + this, service_->GetPrefetchStore(), service_->GetPrefetchGCMHandler(), service_->GetPrefetchNetworkRequestFactory(), base::Bind( &PrefetchDispatcherImpl::DidGenerateBundleOrGetOperationRequest, @@ -332,6 +318,14 @@ success_downloads)); } +void PrefetchDispatcherImpl::GeneratePageBundleRequested( + std::unique_ptr<PrefetchDispatcher::IdsVector> ids) { + // Reverse the order so that the fresher items are last. This is done because + // the ids are popped from the end of the vector. + std::reverse(ids->begin(), ids->end()); + FetchThumbnails(std::move(ids)); +} + void PrefetchDispatcherImpl::DownloadCompleted( const PrefetchDownloadResult& download_result) { if (!service_->GetPrefetchConfiguration()->IsPrefetchingEnabled()) @@ -353,12 +347,9 @@ void PrefetchDispatcherImpl::ItemDownloaded(int64_t offline_id, const ClientId& client_id) { - DCHECK(client_id.name_space == kSuggestedArticlesNamespace); - auto complete_callback = base::BindOnce( - &FetchComplete, base::Unretained(service_->GetOfflinePageModel()), - offline_id); - service_->GetThumbnailFetcher()->FetchSuggestionImageData( - client_id, std::move(complete_callback)); + auto ids = std::make_unique<IdsVector>(); + ids->emplace_back(offline_id, client_id); + FetchThumbnails(std::move(ids)); } void PrefetchDispatcherImpl::ArchiveImported(int64_t offline_id, bool success) { @@ -396,4 +387,55 @@ } } +void PrefetchDispatcherImpl::FetchThumbnails( + std::unique_ptr<PrefetchDispatcher::IdsVector> remaining_ids) { + if (remaining_ids->empty()) + return; + + int64_t offline_id = remaining_ids->back().first; + ClientId client_id = std::move(remaining_ids->back().second); + DCHECK(client_id.name_space == kSuggestedArticlesNamespace); + remaining_ids->pop_back(); + + service_->GetOfflinePageModel()->HasThumbnailForOfflineId( + offline_id, + base::BindOnce(&PrefetchDispatcherImpl::ThumbnailExistenceChecked, + base::Unretained(this), offline_id, std::move(client_id), + std::move(remaining_ids))); +} + +void PrefetchDispatcherImpl::ThumbnailExistenceChecked( + const int64_t offline_id, + ClientId client_id, + std::unique_ptr<PrefetchDispatcher::IdsVector> remaining_ids, + bool thumbnail_exists) { + if (thumbnail_exists) { + ThumbnailFetchComplete(offline_id, std::move(remaining_ids), std::string()); + } else { + auto complete_callback = base::BindOnce( + &PrefetchDispatcherImpl::ThumbnailFetchComplete, base::Unretained(this), + offline_id, std::move(remaining_ids)); + service_->GetThumbnailFetcher()->FetchSuggestionImageData( + client_id, std::move(complete_callback)); + } +} + +void PrefetchDispatcherImpl::ThumbnailFetchComplete( + const int64_t offline_id, + std::unique_ptr<PrefetchDispatcher::IdsVector> remaining_ids, + const std::string& image_data) { + // Thumbnails are marked to expire after this delta. Expired thumbnails are + // eventually deleted if their offline_id does not correspond to an offline + // item. Two days gives us plenty of time so that the prefetched item can be + // imported into the offline item database. + const base::TimeDelta kThumbnailExpirationDelta = + base::TimeDelta::FromDays(2); + + if (!image_data.empty()) { + service_->GetOfflinePageModel()->StoreThumbnail(OfflinePageThumbnail( + offline_id, base::Time::Now() + kThumbnailExpirationDelta, image_data)); + } + FetchThumbnails(std::move(remaining_ids)); +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h index 52535b168..8f514c94 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h
@@ -45,6 +45,7 @@ const std::set<std::string>& outstanding_download_ids, const std::map<std::string, std::pair<base::FilePath, int64_t>>& success_downloads) override; + void GeneratePageBundleRequested(std::unique_ptr<IdsVector> ids) override; void DownloadCompleted( const PrefetchDownloadResult& download_result) override; void ItemDownloaded(int64_t offline_id, const ClientId& client_id) override; @@ -82,6 +83,23 @@ // becomes idle and any task called SchedulePipelineProcessing() before. void QueueActionTasks(); + // The methods below control the downloading of thumbnails for the provided + // prefetch items IDs. They are called multiple times for the same article, + // when they reach different points in the pipeline to increase the likeliness + // of the thumbnail to be available. The existence of the thumbnail is + // verified to avoid re-downloads. + // Also, even though unlikely, concurrent calls to these methods are + // supported. They will generate simultaneous download attempts but there will + // be no impact in the consistency of stored data. + void FetchThumbnails(std::unique_ptr<IdsVector> remaining_ids); + void ThumbnailExistenceChecked(const int64_t offline_id, + ClientId client_id, + std::unique_ptr<IdsVector> remaining_ids, + bool thumbnail_exists); + void ThumbnailFetchComplete(const int64_t offline_id, + std::unique_ptr<IdsVector> remaining_ids, + const std::string& image_data); + PrefetchService* service_; TaskQueue task_queue_; bool needs_pipeline_processing_ = false;
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc index 772938a..4872567 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -35,22 +35,32 @@ #include "url/gurl.h" using testing::Contains; +using ::testing::InSequence; namespace offline_pages { namespace { using testing::_; -const char kTestNamespace[] = "TestPrefetchClientNamespace"; const char kTestID[] = "id"; const GURL kTestURL("https://www.chromium.org"); const GURL kTestURL2("https://www.chromium.org/2"); const int64_t kTestOfflineID = 1111; -const char kClientID1[] = "client-id-1"; +const char kClientID[] = "client-id-1"; class MockOfflinePageModel : public StubOfflinePageModel { public: + MockOfflinePageModel() = default; + ~MockOfflinePageModel() override = default; MOCK_METHOD1(StoreThumbnail, void(const OfflinePageThumbnail& thumb)); + MOCK_METHOD2(HasThumbnailForOfflineId_, + void(int64_t offline_id, + base::OnceCallback<void(bool)>* callback)); + void HasThumbnailForOfflineId( + int64_t offline_id, + base::OnceCallback<void(bool)> callback) override { + HasThumbnailForOfflineId_(offline_id, &callback); + } }; class TestPrefetchBackgroundTask : public PrefetchBackgroundTask { @@ -125,10 +135,11 @@ return reschedule_type_; } - void ExpectFetchThumbnail(const std::string& thumbnail_data) { + void ExpectFetchThumbnail(const std::string& thumbnail_data, + const char* client_id = kClientID) { EXPECT_CALL(*thumbnail_fetcher_, FetchSuggestionImageData_( - ClientId(kSuggestedArticlesNamespace, kClientID1), _)) + ClientId(kSuggestedArticlesNamespace, client_id), _)) .WillOnce( testing::Invoke(testing::CallbackToFunctor(base::BindRepeating( [](const std::string& thumbnail_data, @@ -142,12 +153,30 @@ thumbnail_data, task_runner())))); } + void ExpectHasThumbnailForOfflineId(int64_t offline_id, bool to_return) { + EXPECT_CALL(*offline_model_, HasThumbnailForOfflineId_(offline_id, _)) + .WillOnce( + testing::Invoke(testing::CallbackToFunctor(base::BindRepeating( + [](bool to_return, + scoped_refptr<base::TestMockTimeTaskRunner> task_runner, + int64_t offline_id_, + base::OnceCallback<void(bool)>* callback) { + task_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(*callback), to_return)); + }, + to_return, task_runner())))); + } + protected: // Owned by |taco_|. MockOfflinePageModel* offline_model_; std::vector<PrefetchURL> test_urls_; + // Owned by |taco_|. + MockThumbnailFetcher* thumbnail_fetcher_; + private: std::unique_ptr<PrefetchServiceTestTaco> taco_; @@ -157,8 +186,6 @@ PrefetchDispatcherImpl* dispatcher_; // Owned by |taco_|. TestPrefetchNetworkRequestFactory* network_request_factory_; - // Owned by |taco_|. - MockThumbnailFetcher* thumbnail_fetcher_; bool reschedule_called_ = false; PrefetchBackgroundTaskRescheduleType reschedule_type_ = @@ -218,7 +245,8 @@ // with the state of adding tasks, and that the end state is we have tests // that verify the proper tasks were added in the proper order at each wakeup // signal of the dispatcher. - prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace, + test_urls_); prefetch_dispatcher()->RemoveAllUnprocessedPrefetchURLs( kSuggestedArticlesNamespace); prefetch_dispatcher()->RemovePrefetchURLsByClientId( @@ -226,7 +254,8 @@ } TEST_F(PrefetchDispatcherTest, AddCandidatePrefetchURLsTask) { - prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace, + test_urls_); EXPECT_TRUE(dispatcher_task_queue()->HasPendingTasks()); RunUntilIdle(); EXPECT_FALSE(dispatcher_task_queue()->HasPendingTasks()); @@ -234,10 +263,11 @@ } TEST_F(PrefetchDispatcherTest, RemovePrefetchURLsByClientId) { - prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace, + test_urls_); RunUntilIdle(); prefetch_dispatcher()->RemovePrefetchURLsByClientId( - ClientId(kTestNamespace, test_urls_.front().id)); + ClientId(kSuggestedArticlesNamespace, test_urls_.front().id)); EXPECT_TRUE(dispatcher_task_queue()->HasPendingTasks()); RunUntilIdle(); EXPECT_FALSE(dispatcher_task_queue()->HasPendingTasks()); @@ -249,7 +279,8 @@ disabled_feature_list.InitAndDisableFeature(kPrefetchingOfflinePagesFeature); // Don't add a task for new prefetch URLs. - prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace, + test_urls_); EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask()); // Do nothing with a new background task. @@ -263,7 +294,8 @@ DisablePrefetchingInSettings(); // Don't add a task for new prefetch URLs. - prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace, + test_urls_); EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask()); // Do nothing with a new background task. @@ -276,7 +308,7 @@ TEST_F(PrefetchDispatcherTest, DispatcherReleasesBackgroundTask) { PrefetchURL prefetch_url(kTestID, kTestURL, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); // We start the background task, causing reconcilers and action tasks to be @@ -307,7 +339,7 @@ TEST_F(PrefetchDispatcherTest, RetryWithBackoffAfterFailedNetworkRequest) { PrefetchURL prefetch_url(kTestID, kTestURL, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); BeginBackgroundTask(); @@ -316,7 +348,7 @@ // Trigger another request to make sure we have more work to do. PrefetchURL prefetch_url2(kTestID, kTestURL2, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); RunUntilIdle(); // This should trigger retry with backoff. @@ -339,7 +371,7 @@ TEST_F(PrefetchDispatcherTest, RetryWithoutBackoffAfterFailedNetworkRequest) { PrefetchURL prefetch_url(kTestID, kTestURL, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); BeginBackgroundTask(); @@ -348,7 +380,7 @@ // Trigger another request to make sure we have more work to do. PrefetchURL prefetch_url2(kTestID, kTestURL2, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); // This should trigger retry without backoff. RespondWithNetError(net::ERR_CONNECTION_CLOSED); @@ -370,7 +402,7 @@ TEST_F(PrefetchDispatcherTest, SuspendAfterFailedNetworkRequest) { PrefetchURL prefetch_url(kTestID, kTestURL, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); BeginBackgroundTask(); @@ -379,7 +411,7 @@ // Trigger another request to make sure we have more work to do. PrefetchURL prefetch_url2(kTestID, kTestURL2, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); EXPECT_FALSE(dispatcher_suspended()); @@ -405,7 +437,7 @@ TEST_F(PrefetchDispatcherTest, SuspendRemovedAfterNewBackgroundTask) { PrefetchURL prefetch_url(kTestID, kTestURL, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); BeginBackgroundTask(); @@ -431,7 +463,7 @@ // Trigger another request to make sure we have more work to do. PrefetchURL prefetch_url2(kTestID, kTestURL2, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); BeginBackgroundTask(); @@ -445,26 +477,70 @@ TEST_F(PrefetchDispatcherTest, NoNetworkRequestsAfterNewURLs) { PrefetchURL prefetch_url(kTestID, kTestURL, base::string16()); prefetch_dispatcher()->AddCandidatePrefetchURLs( - kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); + kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); // We should not have started GPB EXPECT_EQ(nullptr, GetRunningFetcher()); } -TEST_F(PrefetchDispatcherTest, ThumbnailFetchFailure) { +TEST_F(PrefetchDispatcherTest, ThumbnailFetchFailure_ItemDownloaded) { ExpectFetchThumbnail(""); + ExpectHasThumbnailForOfflineId(kTestOfflineID, false); EXPECT_CALL(*offline_model_, StoreThumbnail(_)).Times(0); prefetch_dispatcher()->ItemDownloaded( - kTestOfflineID, ClientId(kSuggestedArticlesNamespace, kClientID1)); + kTestOfflineID, ClientId(kSuggestedArticlesNamespace, kClientID)); } -TEST_F(PrefetchDispatcherTest, ThumbnailFetchSuccess) { +TEST_F(PrefetchDispatcherTest, ThumbnailFetchSuccess_ItemDownloaded) { std::string kThumbnailData = "abc"; + ExpectHasThumbnailForOfflineId(kTestOfflineID, false); EXPECT_CALL(*offline_model_, StoreThumbnail(ValidThumbnail())); ExpectFetchThumbnail(kThumbnailData); prefetch_dispatcher()->ItemDownloaded( - kTestOfflineID, ClientId(kSuggestedArticlesNamespace, kClientID1)); + kTestOfflineID, ClientId(kSuggestedArticlesNamespace, kClientID)); +} + +TEST_F(PrefetchDispatcherTest, ThumbnailAlreadyExists_ItemDownloaded) { + ExpectHasThumbnailForOfflineId(kTestOfflineID, true); + EXPECT_CALL(*thumbnail_fetcher_, FetchSuggestionImageData_(_, _)).Times(0); + EXPECT_CALL(*offline_model_, StoreThumbnail(_)).Times(0); + prefetch_dispatcher()->ItemDownloaded( + kTestOfflineID, ClientId(kSuggestedArticlesNamespace, kClientID)); +} + +TEST_F(PrefetchDispatcherTest, + ThumbnailVariousCases_GeneratePageBundleRequested) { + // Covers all possible thumbnail cases with a single + // GeneratePageBundleRequested call: fetch succeeds (#1), fetch fails (#2), + // item already exists (#3). + const int64_t kTestOfflineID1 = 100; + const int64_t kTestOfflineID2 = 101; + const int64_t kTestOfflineID3 = 102; + const char kClientID1[] = "a"; + const char kClientID2[] = "b"; + const char kClientID3[] = "c"; + + InSequence in_sequence; + // Case #1. + ExpectHasThumbnailForOfflineId(kTestOfflineID1, false); + ExpectFetchThumbnail("abc", kClientID1); + EXPECT_CALL(*offline_model_, StoreThumbnail(_)).Times(1); + // Case #2. + ExpectHasThumbnailForOfflineId(kTestOfflineID2, false); + ExpectFetchThumbnail("", kClientID2); + // Case #3. + ExpectHasThumbnailForOfflineId(kTestOfflineID3, true); + + auto prefetch_item_ids = std::make_unique<PrefetchDispatcher::IdsVector>(); + prefetch_item_ids->emplace_back( + kTestOfflineID1, ClientId(kSuggestedArticlesNamespace, kClientID1)); + prefetch_item_ids->emplace_back( + kTestOfflineID2, ClientId(kSuggestedArticlesNamespace, kClientID2)); + prefetch_item_ids->emplace_back( + kTestOfflineID3, ClientId(kSuggestedArticlesNamespace, kClientID3)); + prefetch_dispatcher()->GeneratePageBundleRequested( + std::move(prefetch_item_ids)); } } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc index a535ae5..f968c35a 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc +++ b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.cc
@@ -59,6 +59,12 @@ cleanup_downloads_count++; } +void TestPrefetchDispatcher::GeneratePageBundleRequested( + std::unique_ptr<IdsVector> ids) { + generate_page_bundle_requested++; + ids_from_generate_page_bundle_requested = std::move(ids); +} + void TestPrefetchDispatcher::DownloadCompleted( const PrefetchDownloadResult& download_result) { download_results.push_back(download_result);
diff --git a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h index 4ca398b..e1aa62e 100644 --- a/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/test_prefetch_dispatcher.h
@@ -39,6 +39,7 @@ const std::set<std::string>& outstanding_download_ids, const std::map<std::string, std::pair<base::FilePath, int64_t>>& success_downloads) override; + void GeneratePageBundleRequested(std::unique_ptr<IdsVector> ids) override; void DownloadCompleted( const PrefetchDownloadResult& download_result) override; void ItemDownloaded(int64_t offline_id, const ClientId& client_id) override; @@ -51,6 +52,7 @@ std::vector<PrefetchDownloadResult> download_results; std::vector<std::pair<int64_t, ClientId>> item_downloaded_results; std::vector<std::pair<int64_t, bool>> import_results; + std::unique_ptr<IdsVector> ids_from_generate_page_bundle_requested; int cleanup_downloads_count = 0; int new_suggestions_count = 0; @@ -58,6 +60,7 @@ int remove_all_suggestions_count = 0; int remove_by_client_id_count = 0; int task_schedule_count = 0; + int generate_page_bundle_requested = 0; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/stub_offline_page_model.cc b/components/offline_pages/core/stub_offline_page_model.cc index 80ad5689..e3f3e2e2 100644 --- a/components/offline_pages/core/stub_offline_page_model.cc +++ b/components/offline_pages/core/stub_offline_page_model.cc
@@ -71,6 +71,9 @@ void StubOfflinePageModel::GetThumbnailByOfflineId( int64_t offline_id, GetThumbnailCallback callback) {} +void StubOfflinePageModel::HasThumbnailForOfflineId( + int64_t offline_id, + base::OnceCallback<void(bool)> callback) {} void StubOfflinePageModel::PublishInternalArchive( const OfflinePageItem& offline_page, std::unique_ptr<OfflinePageArchiver> archiver,
diff --git a/components/offline_pages/core/stub_offline_page_model.h b/components/offline_pages/core/stub_offline_page_model.h index 2a64463a..d923c704 100644 --- a/components/offline_pages/core/stub_offline_page_model.h +++ b/components/offline_pages/core/stub_offline_page_model.h
@@ -74,6 +74,9 @@ void StoreThumbnail(const OfflinePageThumbnail& thumb) override; void GetThumbnailByOfflineId(int64_t offline_id, GetThumbnailCallback callback) override; + void HasThumbnailForOfflineId( + int64_t offline_id, + base::OnceCallback<void(bool)> callback) override; void PublishInternalArchive( const OfflinePageItem& offline_page, std::unique_ptr<OfflinePageArchiver> archiver,
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index a893da9..765dd1b5 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -65,6 +65,8 @@ "clipboard_url_provider.h", "contextual_suggestions_service.cc", "contextual_suggestions_service.h", + "favicon_cache.cc", + "favicon_cache.h", "history_match.cc", "history_match.h", "history_provider.cc", @@ -152,6 +154,8 @@ "//base:i18n", "//components/bookmarks/browser", "//components/data_use_measurement/core", + "//components/favicon/core", + "//components/favicon_base", "//components/keyed_service/core", "//components/metrics", "//components/navigation_metrics", @@ -284,6 +288,7 @@ "bookmark_provider_unittest.cc", "builtin_provider_unittest.cc", "clipboard_url_provider_unittest.cc", + "favicon_cache_unittest.cc", "history_provider_unittest.cc", "history_quick_provider_unittest.cc", "history_url_provider_unittest.cc", @@ -314,6 +319,7 @@ "//base", "//components/bookmarks/browser", "//components/bookmarks/test", + "//components/favicon/core/test:test_support", "//components/history/core/test", "//components/open_from_clipboard:test_support", "//components/prefs:test_support",
diff --git a/components/omnibox/browser/DEPS b/components/omnibox/browser/DEPS index dbc9c08..dbca7cf6 100644 --- a/components/omnibox/browser/DEPS +++ b/components/omnibox/browser/DEPS
@@ -2,6 +2,8 @@ "+components/bookmarks/browser", "+components/bookmarks/test", "+components/data_use_measurement/core", + "+components/favicon_base", + "+components/favicon/core", "+components/history/core/browser", "+components/history/core/test", "+components/keyed_service/core",
diff --git a/chrome/browser/ui/omnibox/favicon_cache.cc b/components/omnibox/browser/favicon_cache.cc similarity index 98% rename from chrome/browser/ui/omnibox/favicon_cache.cc rename to components/omnibox/browser/favicon_cache.cc index 1e605026..937e294 100644 --- a/chrome/browser/ui/omnibox/favicon_cache.cc +++ b/components/omnibox/browser/favicon_cache.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/omnibox/favicon_cache.h" +#include "components/omnibox/browser/favicon_cache.h" #include "base/containers/mru_cache.h" #include "components/favicon/core/favicon_service.h"
diff --git a/chrome/browser/ui/omnibox/favicon_cache.h b/components/omnibox/browser/favicon_cache.h similarity index 87% rename from chrome/browser/ui/omnibox/favicon_cache.h rename to components/omnibox/browser/favicon_cache.h index 9ec0f85..35ede6b7 100644 --- a/chrome/browser/ui/omnibox/favicon_cache.h +++ b/components/omnibox/browser/favicon_cache.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_OMNIBOX_FAVICON_CACHE_H_ -#define CHROME_BROWSER_UI_OMNIBOX_FAVICON_CACHE_H_ +#ifndef COMPONENTS_OMNIBOX_BROWSER_FAVICON_CACHE_H_ +#define COMPONENTS_OMNIBOX_BROWSER_FAVICON_CACHE_H_ #include <list> #include <map> @@ -33,8 +33,10 @@ typedef base::OnceCallback<void(const gfx::Image& favicon)> FaviconFetchedCallback; -// We cache a very small number of favicons so we can synchronously deliver -// them to prevent flicker as the user types. +// This caches favicons for pages. We cache a small number of them so we can +// synchronously deliver them to the UI to prevent flicker as the user types. +// It also stores and times out null results from when we cannot fetch a favicon +// from the history database. class FaviconCache : public history::HistoryServiceObserver { public: FaviconCache(favicon::FaviconService* favicon_service, @@ -92,4 +94,4 @@ DISALLOW_COPY_AND_ASSIGN(FaviconCache); }; -#endif // CHROME_BROWSER_UI_OMNIBOX_FAVICON_CACHE_H_ +#endif // COMPONENTS_OMNIBOX_BROWSER_FAVICON_CACHE_H_
diff --git a/chrome/browser/ui/omnibox/favicon_cache_unittest.cc b/components/omnibox/browser/favicon_cache_unittest.cc similarity index 98% rename from chrome/browser/ui/omnibox/favicon_cache_unittest.cc rename to components/omnibox/browser/favicon_cache_unittest.cc index aa9250e..1a7998fe 100644 --- a/chrome/browser/ui/omnibox/favicon_cache_unittest.cc +++ b/components/omnibox/browser/favicon_cache_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/omnibox/favicon_cache.h" +#include "components/omnibox/browser/favicon_cache.h" #include "components/favicon/core/test/mock_favicon_service.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/components/omnibox/browser/omnibox_view.h b/components/omnibox/browser/omnibox_view.h index a7b6d95..91d803a 100644 --- a/components/omnibox/browser/omnibox_view.h +++ b/components/omnibox/browser/omnibox_view.h
@@ -116,7 +116,7 @@ // preserving and selecting the user's text if they already typed in a query. virtual void EnterKeywordModeForDefaultSearchProvider() = 0; - // Returns true if all text is selected or there is no text at all. + // Returns true if all text is selected. Returns false if there is no text. virtual bool IsSelectAll() const = 0; // Fills |start| and |end| with the indexes of the current selection's bounds.
diff --git a/components/omnibox_strings_grdp/OWNERS b/components/omnibox_strings_grdp/OWNERS new file mode 100644 index 0000000..5535cd2 --- /dev/null +++ b/components/omnibox_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/omnibox/OWNERS
diff --git a/components/omnibox_strings_grdp/README.md b/components/omnibox_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/omnibox_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp index b8e680932..9d8345c0 100644 --- a/components/page_info_strings.grdp +++ b/components/page_info_strings.grdp
@@ -215,6 +215,9 @@ <message name="IDS_PAGE_INFO_TYPE_POPUPS" desc="The label used for popups permission controls in the Page Info popup."> Popups </message> + <message name="IDS_PAGE_INFO_TYPE_POPUPS_REDIRECTS" desc="The label used for the popup/redirect permission controls in the Page Info popup."> + Pop-ups and redirects + </message> <message name="IDS_PAGE_INFO_TYPE_FLASH" desc="The label used for Flash permissions in the Page Info popup."> Flash </message>
diff --git a/components/page_info_strings_grdp/OWNERS b/components/page_info_strings_grdp/OWNERS new file mode 100644 index 0000000..7c601fd --- /dev/null +++ b/components/page_info_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/ui/page_info/OWNERS
diff --git a/components/page_info_strings_grdp/README.md b/components/page_info_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/page_info_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc index a1bc1aca..0b14d3a 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.cc +++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/syslog_logging.h" #include "components/autofill/content/browser/content_autofill_driver.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/password_form.h" @@ -329,6 +330,8 @@ // about:blank frames as well as data URLs. If that's not the case, kill the // renderer, as it might be exploited. if (url.SchemeIs(url::kAboutScheme) || url.SchemeIs(url::kDataScheme)) { + SYSLOG(WARNING) << "Killing renderer: illegal password access from about: " + << " or data: URL. Reason: " << static_cast<int>(reason); bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), reason); return false; } @@ -337,6 +340,8 @@ content::ChildProcessSecurityPolicy::GetInstance(); if (!policy->CanAccessDataForOrigin(render_frame_host_->GetProcess()->GetID(), url)) { + SYSLOG(WARNING) << "Killing renderer: illegal password access. Reason: " + << static_cast<int>(reason); bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), reason); return false; }
diff --git a/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc b/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc index a2b7363..7b77ba19 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc
@@ -185,6 +185,11 @@ AffiliatedMatchHelper::kInitializationDelayOnStartup); } + void ExpectNoDeferredTasks() { + mock_time_task_runner_->RunUntilIdle(); + ASSERT_FALSE(mock_time_task_runner_->HasPendingTask()); + } + void RunUntilIdle() { // TODO(gab): Add support for base::RunLoop().RunUntilIdle() in scope of // ScopedMockTimeMessageLoopTaskRunner and use it instead of this helper @@ -666,7 +671,7 @@ match_helper()->Initialize(); RunUntilIdle(); DestroyMatchHelper(); - ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization()); + ASSERT_NO_FATAL_FAILURE(ExpectNoDeferredTasks()); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc b/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc index 016b378..8c044d6 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
@@ -411,7 +411,8 @@ throttler->SignalNetworkRequestNeeded(); throttler.reset(); - EXPECT_EQ(1u, GetPendingTaskCount()); + // We expect the task to be cancelled. + EXPECT_EQ(0u, GetPendingTaskCount()); AssertNoReleaseUntilNoTasksRemain(); }
diff --git a/components/payments_strings_grdp/OWNERS b/components/payments_strings_grdp/OWNERS new file mode 100644 index 0000000..616d5533 --- /dev/null +++ b/components/payments_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/payments/OWNERS
diff --git a/components/payments_strings_grdp/README.md b/components/payments_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/payments_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/pdf_strings_grdp/OWNERS b/components/pdf_strings_grdp/OWNERS new file mode 100644 index 0000000..db781ac --- /dev/null +++ b/components/pdf_strings_grdp/OWNERS
@@ -0,0 +1 @@ +raymes@chromium.org
diff --git a/components/pdf_strings_grdp/README.md b/components/pdf_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/pdf_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/policy_strings_grdp/README.md b/components/policy_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/policy_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/printing/service/pdf_compositor_service.cc b/components/printing/service/pdf_compositor_service.cc index f0b8c7b0..d3dfcc4fe 100644 --- a/components/printing/service/pdf_compositor_service.cc +++ b/components/printing/service/pdf_compositor_service.cc
@@ -66,7 +66,7 @@ void PdfCompositorService::PrepareToStart() { // Set up discardable memory manager. discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { #if defined(USE_AURA) context()->connector()->BindInterface(ui::mojom::kServiceName, &manager_ptr);
diff --git a/components/printing_strings_grdp/OWNERS b/components/printing_strings_grdp/OWNERS new file mode 100644 index 0000000..21ccd7b --- /dev/null +++ b/components/printing_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/printing/OWNERS
diff --git a/components/printing_strings_grdp/README.md b/components/printing_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/printing_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/reset_password_strings_grdp/OWNERS b/components/reset_password_strings_grdp/OWNERS new file mode 100644 index 0000000..5225674 --- /dev/null +++ b/components/reset_password_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/safe_browsing/OWNERS
diff --git a/components/reset_password_strings_grdp/README.md b/components/reset_password_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/reset_password_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/safe_browsing/browser/safe_browsing_network_context.cc b/components/safe_browsing/browser/safe_browsing_network_context.cc index aaad13c..b331202 100644 --- a/components/safe_browsing/browser/safe_browsing_network_context.cc +++ b/components/safe_browsing/browser/safe_browsing_network_context.cc
@@ -41,6 +41,13 @@ return network_context_.get(); } + void FlushForTesting() { + if (network_context_) + network_context_.FlushForTesting(); + if (url_loader_factory_) + url_loader_factory_.FlushForTesting(); + } + protected: // network::URLLoaderFactory implementation: void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, @@ -150,6 +157,11 @@ return url_loader_factory_->GetNetworkContext(); } +void SafeBrowsingNetworkContext::FlushForTesting() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + url_loader_factory_->FlushForTesting(); +} + void SafeBrowsingNetworkContext::ServiceShuttingDown() { url_loader_factory_->Reset(); }
diff --git a/components/safe_browsing/browser/safe_browsing_network_context.h b/components/safe_browsing/browser/safe_browsing_network_context.h index d558ef1..589c231 100644 --- a/components/safe_browsing/browser/safe_browsing_network_context.h +++ b/components/safe_browsing/browser/safe_browsing_network_context.h
@@ -39,6 +39,9 @@ // Returns a NetworkContext. network::mojom::NetworkContext* GetNetworkContext(); + // Flushes NetworkContext and URLLoaderFactory pipes. + void FlushForTesting(); + // Called at shutdown to ensure that the URLRequestContextGetter reference is // destroyed.. void ServiceShuttingDown();
diff --git a/components/security_state_strings_grdp/OWNERS b/components/security_state_strings_grdp/OWNERS new file mode 100644 index 0000000..9e98e48 --- /dev/null +++ b/components/security_state_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/security_state/OWNERS
diff --git a/components/security_state_strings_grdp/README.md b/components/security_state_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/security_state_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/ssl_errors_strings_grdp/OWNERS b/components/ssl_errors_strings_grdp/OWNERS new file mode 100644 index 0000000..877ebf5a --- /dev/null +++ b/components/ssl_errors_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/ssl_errors/OWNERS
diff --git a/components/ssl_errors_strings_grdp/README.md b/components/ssl_errors_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/ssl_errors_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/supervised_user_error_page_strings_grdp/OWNERS b/components/supervised_user_error_page_strings_grdp/OWNERS new file mode 100644 index 0000000..0ba46ac8 --- /dev/null +++ b/components/supervised_user_error_page_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/supervised_user_error_page/OWNERS
diff --git a/components/supervised_user_error_page_strings_grdp/README.md b/components/supervised_user_error_page_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/supervised_user_error_page_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/sync_ui_strings_grdp/OWNERS b/components/sync_ui_strings_grdp/OWNERS new file mode 100644 index 0000000..261ab18 --- /dev/null +++ b/components/sync_ui_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/sync/OWNERS
diff --git a/components/sync_ui_strings_grdp/README.md b/components/sync_ui_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/sync_ui_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/translate_strings_grdp/OWNERS b/components/translate_strings_grdp/OWNERS new file mode 100644 index 0000000..bb5c3afc --- /dev/null +++ b/components/translate_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/translate/OWNERS
diff --git a/components/translate_strings_grdp/README.md b/components/translate_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/translate_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/ukm/debug/ukm_debug_data_extractor.cc b/components/ukm/debug/ukm_debug_data_extractor.cc index 89071bc..0e471c3 100644 --- a/components/ukm/debug/ukm_debug_data_extractor.cc +++ b/components/ukm/debug/ukm_debug_data_extractor.cc
@@ -90,7 +90,7 @@ for (const auto& metric : entry->metrics) { output.append(base::StringPrintf( "<h5>Metric:%s Value:%" PRId64 "</h5>", - GetName(it->second, metric->metric_hash).c_str(), metric->value)); + GetName(it->second, metric.first).c_str(), metric.second)); } } }
diff --git a/components/ukm/test_ukm_recorder.cc b/components/ukm/test_ukm_recorder.cc index 8bb2a8cc..cdf89c4 100644 --- a/components/ukm/test_ukm_recorder.cc +++ b/components/ukm/test_ukm_recorder.cc
@@ -29,7 +29,7 @@ out->source_id = in->source_id; } for (const auto& metric : in->metrics) { - out->metrics.emplace_back(metric->Clone()); + out->metrics.emplace(metric); } } @@ -113,10 +113,9 @@ const int64_t* TestUkmRecorder::GetEntryMetric(const mojom::UkmEntry* entry, base::StringPiece metric_name) { uint64_t hash = base::HashMetricName(metric_name); - for (const auto& metric : entry->metrics) { - if (metric->metric_hash == hash) - return &metric->value; - } + const auto it = entry->metrics.find(hash); + if (it != entry->metrics.end()) + return &it->second; return nullptr; }
diff --git a/components/ukm/ukm_recorder_impl.cc b/components/ukm/ukm_recorder_impl.cc index 69024974..88a91b8 100644 --- a/components/ukm/ukm_recorder_impl.cc +++ b/components/ukm/ukm_recorder_impl.cc
@@ -120,8 +120,8 @@ out->set_event_hash(in.event_hash); for (const auto& metric : in.metrics) { Entry::Metric* proto_metric = out->add_metrics(); - proto_metric->set_metric_hash(metric->metric_hash); - proto_metric->set_value(metric->value); + proto_metric->set_metric_hash(metric.first); + proto_metric->set_value(metric.second); } } @@ -157,7 +157,7 @@ return true; const auto& metric_map = it->second.metric_map; for (const auto& metric : entry.metrics) { - if (metric_map.count(metric->metric_hash) == 0) + if (metric_map.count(metric.first) == 0) return true; } return false; @@ -404,8 +404,8 @@ EventAggregate& event_aggregate = event_aggregations_[entry->event_hash]; event_aggregate.total_count++; for (const auto& metric : entry->metrics) { - MetricAggregate& aggregate = event_aggregate.metrics[metric->metric_hash]; - double value = metric->value; + MetricAggregate& aggregate = event_aggregate.metrics[metric.first]; + double value = metric.second; aggregate.total_count++; aggregate.value_sum += value; aggregate.value_square_sum += value * value; @@ -420,7 +420,7 @@ RecordDroppedEntry(DroppedDataReason::SAMPLED_OUT); event_aggregate.dropped_due_to_sampling++; for (auto& metric : entry->metrics) - event_aggregate.metrics[metric->metric_hash].dropped_due_to_sampling++; + event_aggregate.metrics[metric.first].dropped_due_to_sampling++; return; } @@ -428,7 +428,7 @@ RecordDroppedEntry(DroppedDataReason::MAX_HIT); event_aggregate.dropped_due_to_limits++; for (auto& metric : entry->metrics) - event_aggregate.metrics[metric->metric_hash].dropped_due_to_limits++; + event_aggregate.metrics[metric.first].dropped_due_to_limits++; return; }
diff --git a/components/undo_strings_grdp/OWNERS b/components/undo_strings_grdp/OWNERS new file mode 100644 index 0000000..3c4cda0 --- /dev/null +++ b/components/undo_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/undo/OWNERS
diff --git a/components/undo_strings_grdp/README.md b/components/undo_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/undo_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/version_ui_strings_grdp/OWNERS b/components/version_ui_strings_grdp/OWNERS new file mode 100644 index 0000000..21929621 --- /dev/null +++ b/components/version_ui_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://components/version_ui/OWNERS
diff --git a/components/version_ui_strings_grdp/README.md b/components/version_ui_strings_grdp/README.md new file mode 100644 index 0000000..119d8b9 --- /dev/null +++ b/components/version_ui_strings_grdp/README.md
@@ -0,0 +1,5 @@ +This directory of image SHA-1 hashes is used to improve translations of UI +strings through context images for translators. + +See also: [Chrome Translation Screenshots - Instructions & FAQ +](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/viz/common/display/renderer_settings.h b/components/viz/common/display/renderer_settings.h index db0b1d7..740cb2a 100644 --- a/components/viz/common/display/renderer_settings.h +++ b/components/viz/common/display/renderer_settings.h
@@ -33,6 +33,7 @@ bool allow_overlays = true; bool dont_round_texture_sizes_for_pixel_tests = false; int highp_threshold_min = 0; + bool auto_resize_output_surface = true; int slow_down_compositing_scale_factor = 1;
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index a0ec8d1..38b20f4 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -105,6 +105,8 @@ "display_embedder/server_shared_bitmap_manager.h", "display_embedder/skia_output_surface_impl.cc", "display_embedder/skia_output_surface_impl.h", + "display_embedder/skia_output_surface_impl_on_gpu.cc", + "display_embedder/skia_output_surface_impl_on_gpu.h", "display_embedder/software_output_surface.cc", "display_embedder/software_output_surface.h", "display_embedder/viz_process_context_provider.cc",
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 4470265..42b6787 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -315,7 +315,8 @@ gfx::Size surface_size; bool have_damage = false; auto& last_render_pass = *frame.render_pass_list.back(); - if (last_render_pass.output_rect.size() != current_surface_size_ && + if (settings_.auto_resize_output_surface && + last_render_pass.output_rect.size() != current_surface_size_ && last_render_pass.damage_rect == last_render_pass.output_rect && !current_surface_size_.IsEmpty()) { // Resize the output rect to the current surface size so that we won't
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 62df999e..c97a62e 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -805,10 +805,9 @@ shader = content->makeShader(&content_mat); if (quad->mask_resource_id()) { - cc::DisplayResourceProvider::ScopedReadLockSkImage mask_lock( - resource_provider_, quad->mask_resource_id()); - const SkImage* image = mask_lock.sk_image(); - if (!mask_lock.valid()) + ScopedSkImageBuilder builder(this, quad->mask_resource_id()); + const SkImage* image = builder.sk_image(); + if (!image) return; // Scale normalized uv rect into absolute texel coordinates.
diff --git a/components/viz/service/display_embedder/output_device_backing_unittest.cc b/components/viz/service/display_embedder/output_device_backing_unittest.cc index 6b24f28..91657333 100644 --- a/components/viz/service/display_embedder/output_device_backing_unittest.cc +++ b/components/viz/service/display_embedder/output_device_backing_unittest.cc
@@ -15,7 +15,7 @@ size_t GetViewportSizeInBytes(const gfx::Size& viewport_size) { size_t bytes = std::numeric_limits<size_t>::max(); - DCHECK(ResourceSizes::MaybeSizeInBytes(viewport_size, RGBA_8888, &bytes)); + CHECK(ResourceSizes::MaybeSizeInBytes(viewport_size, RGBA_8888, &bytes)); return bytes; }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index 8966c6d..08e427f70 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -4,7 +4,6 @@ #include "components/viz/service/display_embedder/skia_output_surface_impl.h" -#include "base/atomic_sequence_num.h" #include "base/callback_helpers.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h" @@ -13,71 +12,45 @@ #include "components/viz/common/resources/resource_metadata.h" #include "components/viz/service/display/output_surface_client.h" #include "components/viz/service/display/output_surface_frame.h" +#include "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h" #include "components/viz/service/display_embedder/viz_process_context_provider.h" #include "components/viz/service/gl/gpu_service_impl.h" #include "gpu/command_buffer/common/swap_buffers_complete_params.h" -#include "gpu/command_buffer/service/gpu_preferences.h" -#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/scheduler.h" -#include "gpu/command_buffer/service/sync_point_manager.h" -#include "gpu/command_buffer/service/texture_base.h" -#include "gpu/command_buffer/service/texture_manager.h" -#include "gpu/ipc/service/image_transport_surface.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_gl_api_implementation.h" -#include "ui/gl/gl_surface.h" -#include "ui/gl/gl_switches_util.h" -#include "ui/gl/gl_version_info.h" namespace viz { + namespace { -base::AtomicSequenceNumber g_next_command_buffer_id; +template <typename... Args> +void PostAsyncTask( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const base::RepeatingCallback<void(Args...)>& callback, + Args... args) { + task_runner->PostTask(FROM_HERE, base::BindOnce(callback, args...)); +} + +template <typename... Args> +base::RepeatingCallback<void(Args...)> CreateSafeCallback( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const base::RepeatingCallback<void(Args...)>& callback) { + return base::BindRepeating(&PostAsyncTask<Args...>, task_runner, callback); +} } // namespace -// Metadata for YUV promise SkImage. -class SkiaOutputSurfaceImpl::YUVResourceMetadata { - public: - YUVResourceMetadata(std::vector<ResourceMetadata> metadatas, - SkYUVColorSpace yuv_color_space) - : metadatas_(std::move(metadatas)), yuv_color_space_(yuv_color_space) { - DCHECK(metadatas_.size() == 2 || metadatas_.size() == 3); - } - YUVResourceMetadata(YUVResourceMetadata&& other) = default; - ~YUVResourceMetadata() = default; - YUVResourceMetadata& operator=(YUVResourceMetadata&& other) = default; - - const std::vector<ResourceMetadata>& metadatas() const { return metadatas_; } - SkYUVColorSpace yuv_color_space() const { return yuv_color_space_; } - const sk_sp<SkImage> image() const { return image_; } - void set_image(sk_sp<SkImage> image) { image_ = image; } - const gfx::Size size() const { return metadatas_[0].size; } - - private: - // Resource metadatas for YUV planes. - std::vector<ResourceMetadata> metadatas_; - - SkYUVColorSpace yuv_color_space_; - - // The image copied from YUV textures, it is for fullfilling the promise - // image. - // TODO(penghuang): Remove it when Skia supports drawing YUV textures - // directly. - sk_sp<SkImage> image_; - - DISALLOW_COPY_AND_ASSIGN(YUVResourceMetadata); -}; - // A helper class for fullfilling promise image on the GPU thread. template <class FullfillContextType> class SkiaOutputSurfaceImpl::PromiseTextureHelper { public: using HelperType = PromiseTextureHelper<FullfillContextType>; - PromiseTextureHelper(SkiaOutputSurfaceImpl* impl, FullfillContextType context) - : impl_(impl), context_(std::move(context)) {} + PromiseTextureHelper(base::WeakPtr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu, + FullfillContextType context) + : impl_on_gpu_(impl_on_gpu), context_(std::move(context)) {} ~PromiseTextureHelper() = default; static sk_sp<SkImage> MakePromiseSkImage( @@ -91,8 +64,9 @@ SkAlphaType alpha_type, sk_sp<SkColorSpace> color_space, FullfillContextType context) { - DCHECK_CALLED_ON_VALID_THREAD(impl->client_thread_checker_); - auto helper = std::make_unique<HelperType>(impl, std::move(context)); + DCHECK_CALLED_ON_VALID_THREAD(impl->thread_checker_); + auto helper = std::make_unique<HelperType>(impl->impl_on_gpu_->weak_ptr(), + std::move(context)); auto image = recorder->makePromiseTexture( backend_format, size.width(), size.height(), mip_mapped, origin, color_type, alpha_type, color_space, HelperType::Fullfill, @@ -111,8 +85,12 @@ GrBackendTexture* backend_texture) { DCHECK(texture_context); auto* helper = static_cast<HelperType*>(texture_context); - DCHECK_CALLED_ON_VALID_THREAD(helper->impl_->gpu_thread_checker_); - helper->impl_->OnPromiseTextureFullfill(helper->context_, backend_texture); + // The fullfill is always called by SkiaOutputSurfaceImplOnGpu::SwapBuffers + // or SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass, so impl_on_gpu_ + // should be always valid. + DCHECK(helper->impl_on_gpu_); + helper->impl_on_gpu_->FullfillPromiseTexture(helper->context_, + backend_texture); } static void Release(void* texture_context) { DCHECK(texture_context); } @@ -123,7 +101,7 @@ static_cast<HelperType*>(texture_context)); } - SkiaOutputSurfaceImpl* const impl_; + base::WeakPtr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_; // The data for calling the fullfill methods in SkiaOutputSurfaceImpl. FullfillContextType context_; @@ -141,9 +119,8 @@ // TODO(penghuang): Remove this hack when Skia supports drawing YUV textures // directly. template <> -void SkiaOutputSurfaceImpl::PromiseTextureHelper< - SkiaOutputSurfaceImpl::YUVResourceMetadata>::Init(SkiaOutputSurfaceImpl* - impl) { +void SkiaOutputSurfaceImpl::PromiseTextureHelper<YUVResourceMetadata>::Init( + SkiaOutputSurfaceImpl* impl) { impl->yuv_resource_metadatas_.push_back(&context_); } @@ -153,41 +130,37 @@ scoped_refptr<VizProcessContextProvider> context_provider, SyntheticBeginFrameSource* synthetic_begin_frame_source) : SkiaOutputSurface(context_provider), - command_buffer_id_(gpu::CommandBufferId::FromUnsafeValue( - g_next_command_buffer_id.GetNext() + 1)), gpu_service_(gpu_service), surface_handle_(surface_handle), synthetic_begin_frame_source_(synthetic_begin_frame_source), - gpu_thread_weak_ptr_factory_(this), - client_thread_weak_ptr_factory_(this) { - DETACH_FROM_THREAD(client_thread_checker_); - DETACH_FROM_THREAD(gpu_thread_checker_); + weak_ptr_factory_(this) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); recorder_ = nullptr; - // TODO(penghuang): avoid blocking compositor thread. - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); + // Use GPU scheduler to release impl_on_gpu_ on the GPU thread, so all + // scheduled tasks for the impl_on_gpu_ will be executed, before releasing + // it. The GPU thread is the main thread of the viz process. It outlives the + // compositor thread. We don't need worry about it for now. auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); - auto callback = base::BindOnce(&SkiaOutputSurfaceImpl::DestroyOnGpuThread, - base::Unretained(this), &event); + auto callback = + base::BindOnce([](std::unique_ptr<SkiaOutputSurfaceImplOnGpu>) {}, + std::move(impl_on_gpu_)); gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( sequence_id, std::move(callback), std::vector<gpu::SyncToken>())); - event.Wait(); } void SkiaOutputSurfaceImpl::BindToClient(OutputSurfaceClient* client) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(client); DCHECK(!client_); client_ = client; - client_thread_weak_ptr_ = client_thread_weak_ptr_factory_.GetWeakPtr(); + weak_ptr_ = weak_ptr_factory_.GetWeakPtr(); client_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - // TODO(penghuang): avoid blocking compositor thread. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); @@ -199,12 +172,12 @@ } void SkiaOutputSurfaceImpl::EnsureBackbuffer() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); NOTIMPLEMENTED(); } void SkiaOutputSurfaceImpl::DiscardBackbuffer() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); NOTIMPLEMENTED(); } @@ -213,7 +186,7 @@ } void SkiaOutputSurfaceImpl::SetDrawRectangle(const gfx::Rect& draw_rectangle) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); NOTIMPLEMENTED(); } @@ -222,7 +195,7 @@ const gfx::ColorSpace& color_space, bool has_alpha, bool use_stencil) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); recorder_ = nullptr; SkSurfaceCharacterization* characterization = nullptr; @@ -241,8 +214,10 @@ } auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); - auto callback = base::BindOnce(&SkiaOutputSurfaceImpl::ReshapeOnGpuThread, - base::Unretained(this), size, + // impl_on_gpu_ is released on the GPU thread by a posted task from + // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained. + auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::Reshape, + base::Unretained(impl_on_gpu_.get()), size, device_scale_factor, color_space, has_alpha, use_stencil, characterization, event.get()); gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( @@ -258,14 +233,14 @@ } uint32_t SkiaOutputSurfaceImpl::GetFramebufferCopyTextureFormat() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return GL_RGB; } OverlayCandidateValidator* SkiaOutputSurfaceImpl::GetOverlayCandidateValidator() const { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return nullptr; } @@ -274,35 +249,35 @@ } unsigned SkiaOutputSurfaceImpl::GetOverlayTextureId() const { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return 0; } gfx::BufferFormat SkiaOutputSurfaceImpl::GetOverlayBufferFormat() const { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return gfx::BufferFormat::RGBX_8888; } bool SkiaOutputSurfaceImpl::HasExternalStencilTest() const { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return false; } void SkiaOutputSurfaceImpl::ApplyExternalStencil() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } #if BUILDFLAG(ENABLE_VULKAN) gpu::VulkanSurface* SkiaOutputSurfaceImpl::GetVulkanSurface() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return nullptr; } #endif SkCanvas* SkiaOutputSurfaceImpl::GetSkCanvasForCurrentFrame() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(recorder_); DCHECK_EQ(current_render_pass_id_, 0u); @@ -311,7 +286,7 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImage( ResourceMetadata metadata) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(recorder_); // Convert internal format from GLES2 to platform GL. @@ -333,7 +308,7 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(recorder_); DCHECK(metadatas.size() == 2 || metadatas.size() == 3); @@ -355,21 +330,24 @@ gpu::SyncToken SkiaOutputSurfaceImpl::SkiaSwapBuffers( OutputSurfaceFrame frame) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(recorder_); gpu::SyncToken sync_token(gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE, - command_buffer_id_, ++sync_fence_release_); + impl_on_gpu_->command_buffer_id(), + ++sync_fence_release_); sync_token.SetVerifyFlush(); auto ddl = recorder_->detach(); DCHECK(ddl); RecreateRecorder(); auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); - auto callback = - base::BindOnce(&SkiaOutputSurfaceImpl::SwapBuffersOnGpuThread, - base::Unretained(this), std::move(frame), std::move(ddl), - std::move(yuv_resource_metadatas_), sync_fence_release_); + // impl_on_gpu_ is released on the GPU thread by a posted task from + // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained. + auto callback = base::BindOnce( + &SkiaOutputSurfaceImplOnGpu::SwapBuffers, + base::Unretained(impl_on_gpu_.get()), std::move(frame), std::move(ddl), + std::move(yuv_resource_metadatas_), sync_fence_release_); gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( sequence_id, std::move(callback), std::move(resource_sync_tokens_))); return sync_token; @@ -380,7 +358,7 @@ const gfx::Size& surface_size, ResourceFormat format, bool mipmap) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(gpu_service_->gr_context()); DCHECK(!current_render_pass_id_); DCHECK(!offscreen_surface_recorder_); @@ -416,27 +394,30 @@ } gpu::SyncToken SkiaOutputSurfaceImpl::FinishPaintRenderPass() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(gpu_service_->gr_context()); DCHECK(current_render_pass_id_); DCHECK(offscreen_surface_recorder_); gpu::SyncToken sync_token(gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE, - command_buffer_id_, ++sync_fence_release_); + impl_on_gpu_->command_buffer_id(), + ++sync_fence_release_); + sync_token.SetVerifyFlush(); auto ddl = offscreen_surface_recorder_->detach(); offscreen_surface_recorder_ = nullptr; DCHECK(ddl); auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); + // impl_on_gpu_ is released on the GPU thread by a posted task from + // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained. auto callback = base::BindOnce( - &SkiaOutputSurfaceImpl::FinishPaintRenderPassOnGpuThread, - base::Unretained(this), current_render_pass_id_, std::move(ddl), - std::move(yuv_resource_metadatas_), sync_fence_release_); + &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass, + base::Unretained(impl_on_gpu_.get()), current_render_pass_id_, + std::move(ddl), std::move(yuv_resource_metadatas_), sync_fence_release_); gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( sequence_id, std::move(callback), std::move(resource_sync_tokens_))); current_render_pass_id_ = 0; - sync_token.SetVerifyFlush(); return sync_token; } @@ -445,7 +426,7 @@ const gfx::Size& size, ResourceFormat format, bool mipmap) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(recorder_); // Convert internal format from GLES2 to platform GL. @@ -466,264 +447,37 @@ std::vector<RenderPassId> ids) { DCHECK(!ids.empty()); auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); - auto callback = base::BindOnce( - &SkiaOutputSurfaceImpl::RemoveRenderPassResourceOnGpuThread, - base::Unretained(this), std::move(ids)); + // impl_on_gpu_ is released on the GPU thread by a posted task from + // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained. + auto callback = + base::BindOnce(&SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource, + base::Unretained(impl_on_gpu_.get()), std::move(ids)); gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( sequence_id, std::move(callback), std::vector<gpu::SyncToken>())); } -void SkiaOutputSurfaceImpl::DidSwapBuffersComplete( - gpu::SwapBuffersCompleteParams params) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - params.swap_response.swap_id = pending_swap_completed_ids_.front(); - pending_swap_completed_ids_.pop_front(); - - client_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - &SkiaOutputSurfaceImpl::DidSwapBuffersCompleteOnClientThread, - client_thread_weak_ptr_, params)); -} - -const gpu::gles2::FeatureInfo* SkiaOutputSurfaceImpl::GetFeatureInfo() const { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - NOTIMPLEMENTED(); - return nullptr; -} - -const gpu::GpuPreferences& SkiaOutputSurfaceImpl::GetGpuPreferences() const { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - NOTIMPLEMENTED(); - return gpu_preferences_; -} - -void SkiaOutputSurfaceImpl::SetSnapshotRequestedCallback( - const base::Closure& callback) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - NOTIMPLEMENTED(); -} - -void SkiaOutputSurfaceImpl::UpdateVSyncParameters(base::TimeTicks timebase, - base::TimeDelta interval) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - DCHECK(!gl::IsPresentationCallbackEnabled()); - - client_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - &SkiaOutputSurfaceImpl::UpdateVSyncParametersOnClientThread, - client_thread_weak_ptr_, timebase, interval)); -} - -void SkiaOutputSurfaceImpl::BufferPresented( - const gfx::PresentationFeedback& feedback) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - DCHECK(gl::IsPresentationCallbackEnabled()); - uint64_t swap_id = pending_presented_ids_.front(); - pending_presented_ids_.pop_front(); - - client_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&SkiaOutputSurfaceImpl::BufferPresentedOnClientThread, - client_thread_weak_ptr_, swap_id, feedback)); -} - -void SkiaOutputSurfaceImpl::AddFilter(IPC::MessageFilter* message_filter) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - NOTIMPLEMENTED(); -} - -int32_t SkiaOutputSurfaceImpl::GetRouteID() const { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - NOTIMPLEMENTED(); - return 0; -} - void SkiaOutputSurfaceImpl::InitializeOnGpuThread(base::WaitableEvent* event) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - base::ScopedClosureRunner scoped_runner( base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event))); - - sync_point_client_state_ = - gpu_service_->sync_point_manager()->CreateSyncPointClientState( - gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE, command_buffer_id_, - gpu_service_->skia_output_surface_sequence_id()); - - surface_ = gpu::ImageTransportSurface::CreateNativeSurface( - gpu_thread_weak_ptr_factory_.GetWeakPtr(), surface_handle_, - gl::GLSurfaceFormat()); - DCHECK(surface_); - - if (!gpu_service_->CreateGrContextIfNecessary(surface_.get())) { - LOG(FATAL) << "Failed to create GrContext"; - // TODO(penghuang): handle the failure. - } - - DCHECK(gpu_service_->context_for_skia()); - DCHECK(gpu_service_->gr_context()); - - if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { - LOG(FATAL) << "Failed to make current."; - // TODO(penghuang): Handle the failure. - } - - capabilities_.flipped_output_surface = surface_->FlipsVertically(); - - // Get stencil bits from the default frame buffer. - auto* current_gl = gpu_service_->context_for_skia()->GetCurrentGL(); - const auto* version = current_gl->Version; - auto* api = current_gl->Api; - GLint stencil_bits = 0; - if (version->is_desktop_core_profile) { - api->glGetFramebufferAttachmentParameterivEXTFn( - GL_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, - &stencil_bits); - } else { - api->glGetIntegervFn(GL_STENCIL_BITS, &stencil_bits); - } - - capabilities_.supports_stencil = stencil_bits > 0; -} - -void SkiaOutputSurfaceImpl::DestroyOnGpuThread(base::WaitableEvent* event) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - - base::ScopedClosureRunner scoped_runner( - base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event))); - gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs(); - - // Destroy the surface with the context current, some surface destructors - // make GL calls. - if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { - LOG(FATAL) << "Failed to make current."; - // TODO(penghuang): Handle the failure. - } - surface_ = nullptr; - sync_point_client_state_ = nullptr; -} - -void SkiaOutputSurfaceImpl::ReshapeOnGpuThread( - const gfx::Size& size, - float device_scale_factor, - const gfx::ColorSpace& color_space, - bool has_alpha, - bool use_stencil, - SkSurfaceCharacterization* characterization, - base::WaitableEvent* event) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - - std::unique_ptr<base::ScopedClosureRunner> scoped_runner; - if (event) { - scoped_runner = std::make_unique<base::ScopedClosureRunner>( - base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event))); - } - - if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { - LOG(FATAL) << "Failed to make current."; - // TODO(penghuang): Handle the failure. - } - gl::GLSurface::ColorSpace surface_color_space = - color_space == gfx::ColorSpace::CreateSCRGBLinear() - ? gl::GLSurface::ColorSpace::SCRGB_LINEAR - : gl::GLSurface::ColorSpace::UNSPECIFIED; - if (!surface_->Resize(size, device_scale_factor, surface_color_space, - has_alpha)) { - LOG(FATAL) << "Failed to resize."; - // TODO(penghuang): Handle the failure. - } - DCHECK(gpu_service_->context_for_skia()->IsCurrent(surface_.get())); - DCHECK(gpu_service_->gr_context()); - - SkSurfaceProps surface_props = - SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType); - - GrGLFramebufferInfo framebuffer_info; - framebuffer_info.fFBOID = 0; - const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo(); - framebuffer_info.fFormat = version_info->is_es ? GL_BGRA8_EXT : GL_RGBA8; - - GrBackendRenderTarget render_target(size.width(), size.height(), 0, 8, - framebuffer_info); - - sk_surface_ = SkSurface::MakeFromBackendRenderTarget( - gpu_service_->gr_context(), render_target, kBottomLeft_GrSurfaceOrigin, - kBGRA_8888_SkColorType, nullptr, &surface_props); - DCHECK(sk_surface_); - - if (characterization) { - sk_surface_->characterize(characterization); - DCHECK(characterization->isValid()); - } -} - -void SkiaOutputSurfaceImpl::SwapBuffersOnGpuThread( - OutputSurfaceFrame frame, - std::unique_ptr<SkDeferredDisplayList> ddl, - std::vector<YUVResourceMetadata*> yuv_resource_metadatas, - uint64_t sync_fence_release) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - DCHECK(ddl); - DCHECK(sk_surface_); - - if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { - LOG(FATAL) << "Failed to make current."; - // TODO(penghuang): Handle the failure. - } - - PreprocessYUVResources(std::move(yuv_resource_metadatas)); - - sk_surface_->draw(ddl.get()); - gpu_service_->gr_context()->flush(); - OnSwapBuffers(); - surface_->SwapBuffers( - base::BindRepeating([](const gfx::PresentationFeedback&) {})); - sync_point_client_state_->ReleaseFenceSync(sync_fence_release); -} - -void SkiaOutputSurfaceImpl::FinishPaintRenderPassOnGpuThread( - RenderPassId id, - std::unique_ptr<SkDeferredDisplayList> ddl, - std::vector<YUVResourceMetadata*> yuv_resource_metadatas, - uint64_t sync_fence_release) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - DCHECK(ddl); - - if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { - LOG(FATAL) << "Failed to make current."; - // TODO(penghuang): Handle resize failure. - } - - PreprocessYUVResources(std::move(yuv_resource_metadatas)); - - auto& surface = offscreen_surfaces_[id]; - SkSurfaceCharacterization characterization; - // TODO(penghuang): Using characterization != ddl->characterization(), when - // the SkSurfaceCharacterization::operator!= is implemented in Skia. - if (!surface || !surface->characterize(&characterization) || - characterization != ddl->characterization()) { - surface = SkSurface::MakeRenderTarget( - gpu_service_->gr_context(), ddl->characterization(), SkBudgeted::kNo); - DCHECK(surface); - } - surface->draw(ddl.get()); - surface->flush(); - sync_point_client_state_->ReleaseFenceSync(sync_fence_release); -} - -void SkiaOutputSurfaceImpl::RemoveRenderPassResourceOnGpuThread( - std::vector<RenderPassId> ids) { - DCHECK(!ids.empty()); - for (const auto& id : ids) { - auto it = offscreen_surfaces_.find(id); - DCHECK(it != offscreen_surfaces_.end()); - offscreen_surfaces_.erase(it); - } + auto did_swap_buffer_complete_callback = base::BindRepeating( + &SkiaOutputSurfaceImpl::DidSwapBuffersComplete, weak_ptr_); + auto update_vsync_parameters_callback = base::BindRepeating( + &SkiaOutputSurfaceImpl::UpdateVSyncParameters, weak_ptr_); + auto buffer_presented_callback = + base::BindRepeating(&SkiaOutputSurfaceImpl::BufferPresented, weak_ptr_); + impl_on_gpu_ = std::make_unique<SkiaOutputSurfaceImplOnGpu>( + gpu_service_, surface_handle_, + CreateSafeCallback(client_thread_task_runner_, + did_swap_buffer_complete_callback), + CreateSafeCallback(client_thread_task_runner_, + update_vsync_parameters_callback), + CreateSafeCallback(client_thread_task_runner_, + buffer_presented_callback)); + capabilities_ = impl_on_gpu_->capabilities(); } void SkiaOutputSurfaceImpl::RecreateRecorder() { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(characterization_.isValid()); recorder_ = std::make_unique<SkDeferredDisplayListRecorder>(characterization_); @@ -732,83 +486,9 @@ recorder_->getCanvas(); } -void SkiaOutputSurfaceImpl::PreprocessYUVResources( - std::vector<YUVResourceMetadata*> yuv_resource_metadatas) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - - // Create SkImage for fullfilling YUV promise image, before drawing the ddl. - // TODO(penghuang): Remove the extra step when Skia supports drawing YUV - // textures directly. - auto* mailbox_manager = gpu_service_->mailbox_manager(); - for (auto* yuv_metadata : yuv_resource_metadatas) { - const auto& metadatas = yuv_metadata->metadatas(); - DCHECK(metadatas.size() == 2 || metadatas.size() == 3); - GrBackendTexture backend_textures[3]; - size_t i = 0; - for (const auto& metadata : metadatas) { - auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox); - if (!texture_base) - break; - BindOrCopyTextureIfNecessary(texture_base); - GrGLTextureInfo texture_info; - texture_info.fTarget = texture_base->target(); - texture_info.fID = texture_base->service_id(); - texture_info.fFormat = *metadata.backend_format.getGLFormat(); - backend_textures[i++] = - GrBackendTexture(metadata.size.width(), metadata.size.height(), - GrMipMapped::kNo, texture_info); - } - - if (i != metadatas.size()) - continue; - - sk_sp<SkImage> image; - if (metadatas.size() == 2) { - image = SkImage::MakeFromNV12TexturesCopy( - gpu_service_->gr_context(), yuv_metadata->yuv_color_space(), - backend_textures, kTopLeft_GrSurfaceOrigin, - nullptr /* image_color_space */); - DCHECK(image); - } else { - image = SkImage::MakeFromYUVTexturesCopy( - gpu_service_->gr_context(), yuv_metadata->yuv_color_space(), - backend_textures, kTopLeft_GrSurfaceOrigin, - nullptr /* image_color_space */); - DCHECK(image); - } - yuv_metadata->set_image(std::move(image)); - } -} - -void SkiaOutputSurfaceImpl::BindOrCopyTextureIfNecessary( - gpu::TextureBase* texture_base) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - if (gpu_service_->gpu_preferences().use_passthrough_cmd_decoder) - return; - - // If a texture created with non-passthrough command buffer and bind with - // an image, the Chrome will defer copying the image to the texture until - // the texture is used. It is for implementing low latency drawing and - // avoiding unnecessary texture copy. So we need check the texture image - // state, and bind or copy the image to the texture if necessary. - auto* texture = static_cast<gpu::gles2::Texture*>(texture_base); - gpu::gles2::Texture::ImageState image_state; - auto* image = texture->GetLevelImage(GL_TEXTURE_2D, 0, &image_state); - if (image && image_state == gpu::gles2::Texture::UNBOUND) { - glBindTexture(texture_base->target(), texture_base->service_id()); - if (image->BindTexImage(texture_base->target())) { - } else { - texture->SetLevelImageState(texture_base->target(), 0, - gpu::gles2::Texture::COPIED); - if (!image->CopyTexImage(texture_base->target())) - LOG(ERROR) << "Failed to copy a gl image to texture."; - } - } -} - -void SkiaOutputSurfaceImpl::DidSwapBuffersCompleteOnClientThread( +void SkiaOutputSurfaceImpl::DidSwapBuffersComplete( gpu::SwapBuffersCompleteParams params) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(client_); if (!params.texture_in_use_responses.empty()) @@ -818,10 +498,9 @@ client_->DidReceiveSwapBuffersAck(params.swap_response.swap_id); } -void SkiaOutputSurfaceImpl::UpdateVSyncParametersOnClientThread( - base::TimeTicks timebase, - base::TimeDelta interval) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); +void SkiaOutputSurfaceImpl::UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (synthetic_begin_frame_source_) { // TODO(brianderson): We should not be receiving 0 intervals. @@ -831,67 +510,13 @@ } } -void SkiaOutputSurfaceImpl::BufferPresentedOnClientThread( +void SkiaOutputSurfaceImpl::BufferPresented( uint64_t swap_id, const gfx::PresentationFeedback& feedback) { - DCHECK_CALLED_ON_VALID_THREAD(client_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(client_); client_->DidReceivePresentationFeedback(swap_id, feedback); } -void SkiaOutputSurfaceImpl::OnPromiseTextureFullfill( - const ResourceMetadata& metadata, - GrBackendTexture* backend_texture) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - auto* mailbox_manager = gpu_service_->mailbox_manager(); - auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox); - if (!texture_base) { - DLOG(ERROR) << "Failed to full fill the promise texture."; - return; - } - BindOrCopyTextureIfNecessary(texture_base); - GrGLTextureInfo texture_info; - texture_info.fTarget = texture_base->target(); - texture_info.fID = texture_base->service_id(); - texture_info.fFormat = *metadata.backend_format.getGLFormat(); - *backend_texture = - GrBackendTexture(metadata.size.width(), metadata.size.height(), - metadata.mip_mapped, texture_info); -} - -void SkiaOutputSurfaceImpl::OnPromiseTextureFullfill( - const YUVResourceMetadata& yuv_metadata, - GrBackendTexture* backend_texture) { - DCHECK_CALLED_ON_VALID_THREAD(gpu_thread_checker_); - - if (yuv_metadata.image()) - *backend_texture = yuv_metadata.image()->getBackendTexture(true); - DLOG_IF(ERROR, !backend_texture->isValid()) - << "Failed to full fill the promise texture from yuv resources."; -} - -void SkiaOutputSurfaceImpl::OnPromiseTextureFullfill( - const RenderPassId id, - GrBackendTexture* backend_texture) { - auto it = offscreen_surfaces_.find(id); - DCHECK(it != offscreen_surfaces_.end()); - sk_sp<SkSurface>& surface = it->second; - *backend_texture = - surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess); - DLOG_IF(ERROR, !backend_texture->isValid()) - << "Failed to full fill the promise texture created from RenderPassId:" - << id; -} - -void SkiaOutputSurfaceImpl::OnSwapBuffers() { - uint64_t swap_id = swap_id_++; - pending_swap_completed_ids_.push_back(swap_id); - - // Only push to |pending_presented_ids_| if presentation callbacks - // are enabled, otherwise these will never be popped. - if (gl::IsPresentationCallbackEnabled()) - pending_presented_ids_.push_back(swap_id); -} - } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index 5cae56f..fb17b7f 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -11,39 +11,33 @@ #include "gpu/command_buffer/common/sync_token.h" #include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/in_process_command_buffer.h" -#include "gpu/ipc/service/image_transport_surface_delegate.h" #include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h" -#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/core/SkSurfaceCharacterization.h" namespace base { class WaitableEvent; } -namespace gl { -class GLSurface; -} - -namespace gpu { -class SyncPointClientState; -class TextureBase; -} - namespace viz { class GpuServiceImpl; class VizProcessContextProvider; +class SkiaOutputSurfaceImplOnGpu; class SyntheticBeginFrameSource; +class YUVResourceMetadata; + // The SkiaOutputSurface implementation. It is the output surface for // SkiaRenderer. It lives on the compositor thread, but it will post tasks -// to the GPU thread for initializing, reshaping and swapping buffers, etc. -// Currently, SkiaOutputSurfaceImpl sets up SkSurface from the default GL -// framebuffer, creates SkDeferredDisplayListRecorder and SkCanvas for -// SkiaRenderer to render into. In SwapBuffers, it detaches a -// SkDeferredDisplayList from the recorder and plays it back on the framebuffer -// SkSurface on the GPU thread. -class SkiaOutputSurfaceImpl : public SkiaOutputSurface, - public gpu::ImageTransportSurfaceDelegate { +// to the GPU thread for initializing. Currently, SkiaOutputSurfaceImpl +// create a SkiaOutputSurfaceImplOnGpu on the GPU thread. It will be used +// for creating a SkSurface from the default framebuffer and providing the +// SkSurfaceCharacterization for the SkSurface. And then SkiaOutputSurfaceImpl +// will create SkDeferredDisplayListRecorder and SkCanvas for SkiaRenderer to +// render into. In SwapBuffers, it detaches a SkDeferredDisplayList from the +// recorder and plays it back on the framebuffer SkSurface on the GPU thread +// through SkiaOutputSurfaceImpleOnGpu. +class SkiaOutputSurfaceImpl : public SkiaOutputSurface { public: SkiaOutputSurfaceImpl( GpuServiceImpl* gpu_service, @@ -93,80 +87,23 @@ bool mipmap) override; void RemoveRenderPassResource(std::vector<RenderPassId> ids) override; - // gpu::ImageTransportSurfaceDelegate implementation: - void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params) override; - const gpu::gles2::FeatureInfo* GetFeatureInfo() const override; - const gpu::GpuPreferences& GetGpuPreferences() const override; - - void SetSnapshotRequestedCallback(const base::Closure& callback) override; - void UpdateVSyncParameters(base::TimeTicks timebase, - base::TimeDelta interval) override; - void BufferPresented(const gfx::PresentationFeedback& feedback) override; - - void AddFilter(IPC::MessageFilter* message_filter) override; - int32_t GetRouteID() const override; - private: - class YUVResourceMetadata; - void InitializeOnGpuThread(base::WaitableEvent* event); - void DestroyOnGpuThread(base::WaitableEvent* event); - void ReshapeOnGpuThread(const gfx::Size& size, - float device_scale_factor, - const gfx::ColorSpace& color_space, - bool has_alpha, - bool use_stencil, - SkSurfaceCharacterization* characterization, - base::WaitableEvent* event); - void SwapBuffersOnGpuThread( - OutputSurfaceFrame frame, - std::unique_ptr<SkDeferredDisplayList> ddl, - std::vector<YUVResourceMetadata*> yuv_resource_metadatas, - uint64_t sync_fence_release); - void FinishPaintRenderPassOnGpuThread( - RenderPassId id, - std::unique_ptr<SkDeferredDisplayList> ddl, - std::vector<YUVResourceMetadata*> yuv_resource_metadatas, - uint64_t sync_fence_release); - void RemoveRenderPassResourceOnGpuThread(std::vector<RenderPassId> ids); - void RecreateRecorder(); - void PreprocessYUVResources( - std::vector<YUVResourceMetadata*> yuv_resource_metadatas); - void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base); - void DidSwapBuffersCompleteOnClientThread( - gpu::SwapBuffersCompleteParams params); - void UpdateVSyncParametersOnClientThread(base::TimeTicks timebase, - base::TimeDelta interval); - void BufferPresentedOnClientThread(uint64_t swap_id, - const gfx::PresentationFeedback& feedback); - template <class T> class PromiseTextureHelper; - // Fullfill callback for promise SkImage created from a resource. - void OnPromiseTextureFullfill(const ResourceMetadata& metadata, - GrBackendTexture* backend_texture); - // Fullfill callback for promise SkImage created from YUV resources. - void OnPromiseTextureFullfill(const YUVResourceMetadata& metadata, - GrBackendTexture* backend_texture); - // Fullfill callback for promise SkImage created from a render pass. - void OnPromiseTextureFullfill(const RenderPassId id, - GrBackendTexture* backend_texture); + void InitializeOnGpuThread(base::WaitableEvent* event); + void RecreateRecorder(); + void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params); + void UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval); + void BufferPresented(uint64_t swap_id, + const gfx::PresentationFeedback& feedback); - // Generage the next swap ID and push it to our pending swap ID queues. - void OnSwapBuffers(); - - const gpu::CommandBufferId command_buffer_id_; uint64_t sync_fence_release_ = 0; GpuServiceImpl* const gpu_service_; const gpu::SurfaceHandle surface_handle_; SyntheticBeginFrameSource* const synthetic_begin_frame_source_; OutputSurfaceClient* client_ = nullptr; - scoped_refptr<gpu::SyncPointClientState> sync_point_client_state_; - - gpu::GpuPreferences gpu_preferences_; - scoped_refptr<gl::GLSurface> surface_; - - sk_sp<SkSurface> sk_surface_; SkSurfaceCharacterization characterization_; std::unique_ptr<SkDeferredDisplayListRecorder> recorder_; @@ -178,10 +115,6 @@ // the GPU thread. std::unique_ptr<SkDeferredDisplayListRecorder> offscreen_surface_recorder_; - // Offscreen surfaces for render passes. It must be accessed on the GPU - // thread. - base::flat_map<RenderPassId, sk_sp<SkSurface>> offscreen_surfaces_; - // Sync tokens for resources which are used for the current frame. std::vector<gpu::SyncToken> resource_sync_tokens_; @@ -191,21 +124,16 @@ // directly. std::vector<YUVResourceMetadata*> yuv_resource_metadatas_; - // ID is pushed each time we begin a swap, and popped each time we present or - // complete a swap. - base::circular_deque<uint64_t> pending_presented_ids_; - base::circular_deque<uint64_t> pending_swap_completed_ids_; - uint64_t swap_id_ = 0; - // The task runner for running task on the client (compositor) thread. scoped_refptr<base::SingleThreadTaskRunner> client_thread_task_runner_; - THREAD_CHECKER(client_thread_checker_); - THREAD_CHECKER(gpu_thread_checker_); + // |impl_on_gpu| is created and destroyed on the GPU thread. + std::unique_ptr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_; - base::WeakPtr<SkiaOutputSurfaceImpl> client_thread_weak_ptr_; - base::WeakPtrFactory<SkiaOutputSurfaceImpl> gpu_thread_weak_ptr_factory_; - base::WeakPtrFactory<SkiaOutputSurfaceImpl> client_thread_weak_ptr_factory_; + THREAD_CHECKER(thread_checker_); + + base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr_; + base::WeakPtrFactory<SkiaOutputSurfaceImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceImpl); };
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc new file mode 100644 index 0000000..60296cdd --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -0,0 +1,426 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h" + +#include "base/atomic_sequence_num.h" +#include "base/callback_helpers.h" +#include "base/synchronization/waitable_event.h" +#include "components/viz/service/display/output_surface_frame.h" +#include "components/viz/service/gl/gpu_service_impl.h" +#include "gpu/command_buffer/common/swap_buffers_complete_params.h" +#include "gpu/command_buffer/service/gpu_preferences.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/scheduler.h" +#include "gpu/command_buffer/service/sync_point_manager.h" +#include "gpu/command_buffer/service/texture_base.h" +#include "gpu/command_buffer/service/texture_manager.h" +#include "gpu/ipc/service/image_transport_surface.h" +#include "third_party/skia/include/private/SkDeferredDisplayList.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/gl_switches_util.h" +#include "ui/gl/gl_version_info.h" + +namespace viz { +namespace { + +base::AtomicSequenceNumber g_next_command_buffer_id; + +} // namespace + +YUVResourceMetadata::YUVResourceMetadata( + std::vector<ResourceMetadata> metadatas, + SkYUVColorSpace yuv_color_space) + : metadatas_(std::move(metadatas)), yuv_color_space_(yuv_color_space) { + DCHECK(metadatas_.size() == 2 || metadatas_.size() == 3); +} + +YUVResourceMetadata::YUVResourceMetadata(YUVResourceMetadata&& other) = default; + +YUVResourceMetadata::~YUVResourceMetadata() = default; + +YUVResourceMetadata& YUVResourceMetadata::operator=( + YUVResourceMetadata&& other) = default; + +SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu( + GpuServiceImpl* gpu_service, + gpu::SurfaceHandle surface_handle, + const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, + const UpdateVSyncParametersCallback& update_vsync_parameters_callback, + const BufferPresentedCallback& buffer_presented_callback) + : command_buffer_id_(gpu::CommandBufferId::FromUnsafeValue( + g_next_command_buffer_id.GetNext() + 1)), + gpu_service_(gpu_service), + surface_handle_(surface_handle), + did_swap_buffer_complete_callback_(did_swap_buffer_complete_callback), + update_vsync_parameters_callback_(update_vsync_parameters_callback), + buffer_presented_callback_(buffer_presented_callback), + weak_ptr_factory_(this) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + weak_ptr_ = weak_ptr_factory_.GetWeakPtr(); + + sync_point_client_state_ = + gpu_service_->sync_point_manager()->CreateSyncPointClientState( + gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE, command_buffer_id_, + gpu_service_->skia_output_surface_sequence_id()); + + surface_ = gpu::ImageTransportSurface::CreateNativeSurface( + weak_ptr_factory_.GetWeakPtr(), surface_handle_, gl::GLSurfaceFormat()); + DCHECK(surface_); + + if (!gpu_service_->CreateGrContextIfNecessary(surface_.get())) { + LOG(FATAL) << "Failed to create GrContext"; + // TODO(penghuang): handle the failure. + } + + DCHECK(gpu_service_->context_for_skia()); + DCHECK(gpu_service_->gr_context()); + + if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { + LOG(FATAL) << "Failed to make current."; + // TODO(penghuang): Handle the failure. + } + + capabilities_.flipped_output_surface = surface_->FlipsVertically(); + + // Get stencil bits from the default frame buffer. + auto* current_gl = gpu_service_->context_for_skia()->GetCurrentGL(); + const auto* version = current_gl->Version; + auto* api = current_gl->Api; + GLint stencil_bits = 0; + if (version->is_desktop_core_profile) { + api->glGetFramebufferAttachmentParameterivEXTFn( + GL_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, + &stencil_bits); + } else { + api->glGetIntegervFn(GL_STENCIL_BITS, &stencil_bits); + } + + capabilities_.supports_stencil = stencil_bits > 0; +} + +SkiaOutputSurfaceImplOnGpu::~SkiaOutputSurfaceImplOnGpu() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + // Destroy the surface with the context current, some surface destructors + // make GL calls. + if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { + LOG(FATAL) << "Failed to make current."; + // TODO(penghuang): Handle the failure. + } + surface_ = nullptr; + sync_point_client_state_ = nullptr; +} + +void SkiaOutputSurfaceImplOnGpu::Reshape( + const gfx::Size& size, + float device_scale_factor, + const gfx::ColorSpace& color_space, + bool has_alpha, + bool use_stencil, + SkSurfaceCharacterization* characterization, + base::WaitableEvent* event) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + std::unique_ptr<base::ScopedClosureRunner> scoped_runner; + if (event) { + scoped_runner = std::make_unique<base::ScopedClosureRunner>( + base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event))); + } + + if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { + LOG(FATAL) << "Failed to make current."; + // TODO(penghuang): Handle the failure. + } + gl::GLSurface::ColorSpace surface_color_space = + color_space == gfx::ColorSpace::CreateSCRGBLinear() + ? gl::GLSurface::ColorSpace::SCRGB_LINEAR + : gl::GLSurface::ColorSpace::UNSPECIFIED; + if (!surface_->Resize(size, device_scale_factor, surface_color_space, + has_alpha)) { + LOG(FATAL) << "Failed to resize."; + // TODO(penghuang): Handle the failure. + } + DCHECK(gpu_service_->context_for_skia()->IsCurrent(surface_.get())); + DCHECK(gpu_service_->gr_context()); + + SkSurfaceProps surface_props = + SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType); + + GrGLFramebufferInfo framebuffer_info; + framebuffer_info.fFBOID = 0; + const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo(); + framebuffer_info.fFormat = version_info->is_es ? GL_BGRA8_EXT : GL_RGBA8; + + GrBackendRenderTarget render_target(size.width(), size.height(), 0, 8, + framebuffer_info); + + sk_surface_ = SkSurface::MakeFromBackendRenderTarget( + gpu_service_->gr_context(), render_target, kBottomLeft_GrSurfaceOrigin, + kBGRA_8888_SkColorType, nullptr, &surface_props); + DCHECK(sk_surface_); + + if (characterization) { + sk_surface_->characterize(characterization); + DCHECK(characterization->isValid()); + } +} + +void SkiaOutputSurfaceImplOnGpu::SwapBuffers( + OutputSurfaceFrame frame, + std::unique_ptr<SkDeferredDisplayList> ddl, + std::vector<YUVResourceMetadata*> yuv_resource_metadatas, + uint64_t sync_fence_release) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(ddl); + DCHECK(sk_surface_); + + if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { + LOG(FATAL) << "Failed to make current."; + // TODO(penghuang): Handle the failure. + } + + PreprocessYUVResources(std::move(yuv_resource_metadatas)); + + sk_surface_->draw(ddl.get()); + gpu_service_->gr_context()->flush(); + OnSwapBuffers(); + surface_->SwapBuffers( + base::BindRepeating([](const gfx::PresentationFeedback&) {})); + sync_point_client_state_->ReleaseFenceSync(sync_fence_release); +} + +void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass( + RenderPassId id, + std::unique_ptr<SkDeferredDisplayList> ddl, + std::vector<YUVResourceMetadata*> yuv_resource_metadatas, + uint64_t sync_fence_release) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(ddl); + + if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) { + LOG(FATAL) << "Failed to make current."; + // TODO(penghuang): Handle resize failure. + } + + PreprocessYUVResources(std::move(yuv_resource_metadatas)); + + auto& surface = offscreen_surfaces_[id]; + SkSurfaceCharacterization characterization; + // TODO(penghuang): Using characterization != ddl->characterization(), when + // the SkSurfaceCharacterization::operator!= is implemented in Skia. + if (!surface || !surface->characterize(&characterization) || + characterization != ddl->characterization()) { + surface = SkSurface::MakeRenderTarget( + gpu_service_->gr_context(), ddl->characterization(), SkBudgeted::kNo); + DCHECK(surface); + } + surface->draw(ddl.get()); + surface->flush(); + sync_point_client_state_->ReleaseFenceSync(sync_fence_release); +} + +void SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource( + std::vector<RenderPassId> ids) { + DCHECK(!ids.empty()); + for (const auto& id : ids) { + auto it = offscreen_surfaces_.find(id); + DCHECK(it != offscreen_surfaces_.end()); + offscreen_surfaces_.erase(it); + } +} + +void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture( + const ResourceMetadata& metadata, + GrBackendTexture* backend_texture) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + auto* mailbox_manager = gpu_service_->mailbox_manager(); + auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox); + if (!texture_base) { + DLOG(ERROR) << "Failed to full fill the promise texture."; + return; + } + BindOrCopyTextureIfNecessary(texture_base); + GrGLTextureInfo texture_info; + texture_info.fTarget = texture_base->target(); + texture_info.fID = texture_base->service_id(); + texture_info.fFormat = *metadata.backend_format.getGLFormat(); + *backend_texture = + GrBackendTexture(metadata.size.width(), metadata.size.height(), + metadata.mip_mapped, texture_info); +} + +void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture( + const YUVResourceMetadata& yuv_metadata, + GrBackendTexture* backend_texture) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (yuv_metadata.image()) + *backend_texture = yuv_metadata.image()->getBackendTexture(true); + DLOG_IF(ERROR, !backend_texture->isValid()) + << "Failed to full fill the promise texture from yuv resources."; +} + +void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture( + const RenderPassId id, + GrBackendTexture* backend_texture) { + auto it = offscreen_surfaces_.find(id); + DCHECK(it != offscreen_surfaces_.end()); + sk_sp<SkSurface>& surface = it->second; + *backend_texture = + surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess); + DLOG_IF(ERROR, !backend_texture->isValid()) + << "Failed to full fill the promise texture created from RenderPassId:" + << id; +} + +#if defined(OS_WIN) +void SkiaOutputSurfaceImplOnGpu::DidCreateAcceleratedSurfaceChildWindow( + gpu::SurfaceHandle parent_window, + gpu::SurfaceHandle child_window) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NOTIMPLEMENTED(); +} +#endif + +void SkiaOutputSurfaceImplOnGpu::DidSwapBuffersComplete( + gpu::SwapBuffersCompleteParams params) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + params.swap_response.swap_id = pending_swap_completed_ids_.front(); + pending_swap_completed_ids_.pop_front(); + did_swap_buffer_complete_callback_.Run(params); +} + +const gpu::gles2::FeatureInfo* SkiaOutputSurfaceImplOnGpu::GetFeatureInfo() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NOTIMPLEMENTED(); + return nullptr; +} + +const gpu::GpuPreferences& SkiaOutputSurfaceImplOnGpu::GetGpuPreferences() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NOTIMPLEMENTED(); + return gpu_preferences_; +} + +void SkiaOutputSurfaceImplOnGpu::SetSnapshotRequestedCallback( + const base::Closure& callback) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NOTIMPLEMENTED(); +} + +void SkiaOutputSurfaceImplOnGpu::UpdateVSyncParameters( + base::TimeTicks timebase, + base::TimeDelta interval) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!gl::IsPresentationCallbackEnabled()); + update_vsync_parameters_callback_.Run(timebase, interval); +} + +void SkiaOutputSurfaceImplOnGpu::BufferPresented( + const gfx::PresentationFeedback& feedback) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(gl::IsPresentationCallbackEnabled()); + uint64_t swap_id = pending_presented_ids_.front(); + pending_presented_ids_.pop_front(); + buffer_presented_callback_.Run(swap_id, feedback); +} + +void SkiaOutputSurfaceImplOnGpu::AddFilter(IPC::MessageFilter* message_filter) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NOTIMPLEMENTED(); +} + +int32_t SkiaOutputSurfaceImplOnGpu::GetRouteID() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + NOTIMPLEMENTED(); + return 0; +} + +void SkiaOutputSurfaceImplOnGpu::BindOrCopyTextureIfNecessary( + gpu::TextureBase* texture_base) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (gpu_service_->gpu_preferences().use_passthrough_cmd_decoder) + return; + // If a texture created with non-passthrough command buffer and bind with + // an image, the Chrome will defer copying the image to the texture until + // the texture is used. It is for implementing low latency drawing and + // avoiding unnecessary texture copy. So we need check the texture image + // state, and bind or copy the image to the texture if necessary. + auto* texture = static_cast<gpu::gles2::Texture*>(texture_base); + gpu::gles2::Texture::ImageState image_state; + auto* image = texture->GetLevelImage(GL_TEXTURE_2D, 0, &image_state); + if (image && image_state == gpu::gles2::Texture::UNBOUND) { + glBindTexture(texture_base->target(), texture_base->service_id()); + if (image->BindTexImage(texture_base->target())) { + } else { + texture->SetLevelImageState(texture_base->target(), 0, + gpu::gles2::Texture::COPIED); + if (!image->CopyTexImage(texture_base->target())) + LOG(ERROR) << "Failed to copy a gl image to texture."; + } + } +} + +void SkiaOutputSurfaceImplOnGpu::PreprocessYUVResources( + std::vector<YUVResourceMetadata*> yuv_resource_metadatas) { + // Create SkImage for fullfilling YUV promise image, before drawing the ddl. + // TODO(penghuang): Remove the extra step when Skia supports drawing YUV + // textures directly. + auto* mailbox_manager = gpu_service_->mailbox_manager(); + for (auto* yuv_metadata : yuv_resource_metadatas) { + const auto& metadatas = yuv_metadata->metadatas(); + DCHECK(metadatas.size() == 2 || metadatas.size() == 3); + GrBackendTexture backend_textures[3]; + size_t i = 0; + for (const auto& metadata : metadatas) { + auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox); + if (!texture_base) + break; + BindOrCopyTextureIfNecessary(texture_base); + GrGLTextureInfo texture_info; + texture_info.fTarget = texture_base->target(); + texture_info.fID = texture_base->service_id(); + texture_info.fFormat = *metadata.backend_format.getGLFormat(); + backend_textures[i++] = + GrBackendTexture(metadata.size.width(), metadata.size.height(), + GrMipMapped::kNo, texture_info); + } + + if (i != metadatas.size()) + continue; + + sk_sp<SkImage> image; + if (metadatas.size() == 2) { + image = SkImage::MakeFromNV12TexturesCopy( + gpu_service_->gr_context(), yuv_metadata->yuv_color_space(), + backend_textures, kTopLeft_GrSurfaceOrigin, + nullptr /* image_color_space */); + DCHECK(image); + } else { + image = SkImage::MakeFromYUVTexturesCopy( + gpu_service_->gr_context(), yuv_metadata->yuv_color_space(), + backend_textures, kTopLeft_GrSurfaceOrigin, + nullptr /* image_color_space */); + DCHECK(image); + } + yuv_metadata->set_image(std::move(image)); + } +} + +void SkiaOutputSurfaceImplOnGpu::OnSwapBuffers() { + uint64_t swap_id = swap_id_++; + pending_swap_completed_ids_.push_back(swap_id); + + // Only push to |pending_presented_ids_| if presentation callbacks + // are enabled, otherwise these will never be popped. + if (gl::IsPresentationCallbackEnabled()) + pending_presented_ids_.push_back(swap_id); +} + +} // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h new file mode 100644 index 0000000..fea55b8 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -0,0 +1,181 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_ + +#include "base/containers/circular_deque.h" +#include "base/macros.h" +#include "base/threading/thread_checker.h" +#include "build/build_config.h" +#include "components/viz/common/quads/render_pass.h" +#include "components/viz/common/resources/resource_metadata.h" +#include "components/viz/service/display/output_surface.h" +#include "components/viz/service/display/output_surface_frame.h" +#include "gpu/command_buffer/common/sync_token.h" +#include "gpu/ipc/common/surface_handle.h" +#include "gpu/ipc/in_process_command_buffer.h" +#include "gpu/ipc/service/image_transport_surface_delegate.h" +#include "third_party/skia/include/core/SkSurface.h" + +class SkDeferredDisplayList; + +namespace base { +class WaitableEvent; +} + +namespace gl { +class GLSurface; +} + +namespace gpu { +class SyncPointClientState; +} + +namespace viz { + +class GpuServiceImpl; + +// Metadata for YUV promise SkImage. +class YUVResourceMetadata { + public: + YUVResourceMetadata(std::vector<ResourceMetadata> metadatas, + SkYUVColorSpace yuv_color_space); + YUVResourceMetadata(YUVResourceMetadata&& other); + ~YUVResourceMetadata(); + YUVResourceMetadata& operator=(YUVResourceMetadata&& other); + + const std::vector<ResourceMetadata>& metadatas() const { return metadatas_; } + SkYUVColorSpace yuv_color_space() const { return yuv_color_space_; } + const sk_sp<SkImage> image() const { return image_; } + void set_image(sk_sp<SkImage> image) { image_ = image; } + const gfx::Size size() const { return metadatas_[0].size; } + + private: + // Metadatas for YUV planes. + std::vector<ResourceMetadata> metadatas_; + + SkYUVColorSpace yuv_color_space_; + + // The image copied from YUV textures, it is for fullfilling the promise + // image. + // TODO(penghuang): Remove it when Skia supports drawing YUV textures + // directly. + sk_sp<SkImage> image_; + + DISALLOW_COPY_AND_ASSIGN(YUVResourceMetadata); +}; + +// The SkiaOutputSurface implementation running on the GPU thread. This class +// should be created, used and destroyed on the GPU thread. +class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate { + public: + using DidSwapBufferCompleteCallback = + base::RepeatingCallback<void(gpu::SwapBuffersCompleteParams)>; + using UpdateVSyncParametersCallback = + base::RepeatingCallback<void(base::TimeTicks, base::TimeDelta)>; + using BufferPresentedCallback = + base::RepeatingCallback<void(uint64_t swap_id, + const gfx::PresentationFeedback& feedback)>; + SkiaOutputSurfaceImplOnGpu( + GpuServiceImpl* gpu_service, + gpu::SurfaceHandle surface_handle, + const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, + const UpdateVSyncParametersCallback& update_vsync_parameters_callback, + const BufferPresentedCallback& buffer_presented_callback); + ~SkiaOutputSurfaceImplOnGpu() override; + + gpu::CommandBufferId command_buffer_id() const { return command_buffer_id_; } + const OutputSurface::Capabilities capabilities() const { + return capabilities_; + } + const base::WeakPtr<SkiaOutputSurfaceImplOnGpu>& weak_ptr() const { + return weak_ptr_; + } + + void Reshape(const gfx::Size& size, + float device_scale_factor, + const gfx::ColorSpace& color_space, + bool has_alpha, + bool use_stencil, + SkSurfaceCharacterization* characterization, + base::WaitableEvent* event); + void SwapBuffers(OutputSurfaceFrame frame, + std::unique_ptr<SkDeferredDisplayList> ddl, + std::vector<YUVResourceMetadata*> yuv_resource_metadatas, + uint64_t sync_fence_release); + void FinishPaintRenderPass( + RenderPassId id, + std::unique_ptr<SkDeferredDisplayList> ddl, + std::vector<YUVResourceMetadata*> yuv_resource_metadatas, + uint64_t sync_fence_release); + void RemoveRenderPassResource(std::vector<RenderPassId> ids); + + // Fullfill callback for promise SkImage created from a resource. + void FullfillPromiseTexture(const ResourceMetadata& metadata, + GrBackendTexture* backend_texture); + // Fullfill callback for promise SkImage created from YUV resources. + void FullfillPromiseTexture(const YUVResourceMetadata& metadata, + GrBackendTexture* backend_texture); + // Fullfill callback for promise SkImage created from a render pass. + void FullfillPromiseTexture(const RenderPassId id, + GrBackendTexture* backend_texture); + + private: +// gpu::ImageTransportSurfaceDelegate implementation: +#if defined(OS_WIN) + void DidCreateAcceleratedSurfaceChildWindow( + gpu::SurfaceHandle parent_window, + gpu::SurfaceHandle child_window) override; +#endif + void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params) override; + const gpu::gles2::FeatureInfo* GetFeatureInfo() const override; + const gpu::GpuPreferences& GetGpuPreferences() const override; + void SetSnapshotRequestedCallback(const base::Closure& callback) override; + void UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) override; + void BufferPresented(const gfx::PresentationFeedback& feedback) override; + void AddFilter(IPC::MessageFilter* message_filter) override; + int32_t GetRouteID() const override; + + void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base); + void PreprocessYUVResources( + std::vector<YUVResourceMetadata*> yuv_resource_metadatas); + + // Generage the next swap ID and push it to our pending swap ID queues. + void OnSwapBuffers(); + + const gpu::CommandBufferId command_buffer_id_; + GpuServiceImpl* const gpu_service_; + const gpu::SurfaceHandle surface_handle_; + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback_; + UpdateVSyncParametersCallback update_vsync_parameters_callback_; + BufferPresentedCallback buffer_presented_callback_; + scoped_refptr<gpu::SyncPointClientState> sync_point_client_state_; + gpu::GpuPreferences gpu_preferences_; + scoped_refptr<gl::GLSurface> surface_; + sk_sp<SkSurface> sk_surface_; + OutputSurface::Capabilities capabilities_; + + // Offscreen surfaces for render passes. It can only be accessed on GPU + // thread. + base::flat_map<RenderPassId, sk_sp<SkSurface>> offscreen_surfaces_; + + // ID is pushed each time we begin a swap, and popped each time we present or + // complete a swap. + base::circular_deque<uint64_t> pending_presented_ids_; + base::circular_deque<uint64_t> pending_swap_completed_ids_; + uint64_t swap_id_ = 0; + + THREAD_CHECKER(thread_checker_); + + base::WeakPtr<SkiaOutputSurfaceImplOnGpu> weak_ptr_; + base::WeakPtrFactory<SkiaOutputSurfaceImplOnGpu> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceImplOnGpu); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_
diff --git a/components/zucchini/BUILD.gn b/components/zucchini/BUILD.gn index 800216e..f36c949 100644 --- a/components/zucchini/BUILD.gn +++ b/components/zucchini/BUILD.gn
@@ -2,9 +2,22 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") import("//chrome/process_version_rc_template.gni") import("//testing/test.gni") +buildflag_header("buildflags") { + header = "buildflags.h" + + # Disable DEX on Windows Official Builds. + _enable_dex = !(is_win && is_official_build) + _enable_win = true + flags = [ + "ENABLE_DEX=$_enable_dex", + "ENABLE_WIN=$_enable_win", + ] +} + static_library("zucchini_lib") { sources = [ "abs32_utils.cc", @@ -79,6 +92,7 @@ ] deps = [ + ":buildflags", "//base", ] }
diff --git a/components/zucchini/element_detection.cc b/components/zucchini/element_detection.cc index 2fa3604..a826f5423 100644 --- a/components/zucchini/element_detection.cc +++ b/components/zucchini/element_detection.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/logging.h" +#include "components/zucchini/buildflags.h" #include "components/zucchini/disassembler.h" #include "components/zucchini/disassembler_dex.h" #include "components/zucchini/disassembler_no_op.h" @@ -17,7 +18,7 @@ namespace { // Impose a minimal program size to eliminate pathological cases. -constexpr size_t kMinProgramSize = 16; +enum : size_t { kMinProgramSize = 16 }; } // namespace @@ -25,6 +26,7 @@ std::unique_ptr<Disassembler> MakeDisassemblerWithoutFallback( ConstBufferView image) { +#if BUILDFLAG(ENABLE_WIN) if (DisassemblerWin32X86::QuickDetect(image)) { auto disasm = Disassembler::Make<DisassemblerWin32X86>(image); if (disasm && disasm->size() >= kMinProgramSize) @@ -36,12 +38,15 @@ if (disasm && disasm->size() >= kMinProgramSize) return disasm; } +#endif // BUILDFLAG(ENABLE_WIN) +#if BUILDFLAG(ENABLE_DEX) if (DisassemblerDex::QuickDetect(image)) { auto disasm = Disassembler::Make<DisassemblerDex>(image); if (disasm && disasm->size() >= kMinProgramSize) return disasm; } +#endif // BUILDFLAG(ENABLE_DEX) return nullptr; } @@ -49,15 +54,20 @@ std::unique_ptr<Disassembler> MakeDisassemblerOfType(ConstBufferView image, ExecutableType exe_type) { switch (exe_type) { +#if BUILDFLAG(ENABLE_WIN) case kExeTypeWin32X86: return Disassembler::Make<DisassemblerWin32X86>(image); case kExeTypeWin32X64: return Disassembler::Make<DisassemblerWin32X64>(image); +#endif // BUILDFLAG(ENABLE_WIN) +#if BUILDFLAG(ENABLE_DEX) case kExeTypeDex: return Disassembler::Make<DisassemblerDex>(image); +#endif // BUILDFLAG(ENABLE_DEX) case kExeTypeNoOp: return Disassembler::Make<DisassemblerNoOp>(image); default: + // If an architecture is disabled then null is handled gracefully. return nullptr; } }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7c00f50..17e450a 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2056,6 +2056,8 @@ "android/gesture_listener_manager.h", "android/ime_adapter_android.cc", "android/ime_adapter_android.h", + "android/interstitial_page_delegate_android.cc", + "android/interstitial_page_delegate_android.h", "android/java/gin_java_bound_object.cc", "android/java/gin_java_bound_object.h", "android/java/gin_java_bound_object_delegate.cc", @@ -2148,10 +2150,11 @@ deps += [ ":reflection_jni_headers", "//content/public/android:jni", - "//device/gamepad/public/mojom", "//media", "//media/capture/content/android", "//media/capture/video/android", + "//ui/accessibility:ax_assistant", + "//ui/accessibility/mojom", "//ui/android", "//ui/compositor", ]
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 89e57e0e..041eac9 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -16,9 +16,9 @@ #include "content/common/accessibility_messages.h" #include "content/public/common/content_client.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/accessibility/ax_assistant_structure.h" #include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/platform/ax_android_constants.h" -#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h" #include "ui/accessibility/platform/ax_unique_id.h" namespace { @@ -265,7 +265,7 @@ } bool BrowserAccessibilityAndroid::IsLink() const { - return ui::AXSnapshotNodeAndroid::AXRoleIsLink(GetRole()); + return ui::AXRoleIsLink(GetRole()); } bool BrowserAccessibilityAndroid::IsMultiLine() const { @@ -370,8 +370,8 @@ } const char* BrowserAccessibilityAndroid::GetClassName() const { - return ui::AXSnapshotNodeAndroid::AXRoleToAndroidClassName( - GetRole(), PlatformGetParent() != nullptr); + return ui::AXRoleToAndroidClassName(GetRole(), + PlatformGetParent() != nullptr); } base::string16 BrowserAccessibilityAndroid::GetText() const { @@ -421,7 +421,7 @@ if (text.empty() && (IsLink() || GetRole() == ax::mojom::Role::kImage) && !HasExplicitlyEmptyName()) { base::string16 url = GetString16Attribute(ax::mojom::StringAttribute::kUrl); - text = ui::AXSnapshotNodeAndroid::AXUrlBaseText(url); + text = ui::AXUrlBaseText(url); } return text;
diff --git a/content/public/test/android/interstitial_page_delegate_android.cc b/content/browser/android/interstitial_page_delegate_android.cc similarity index 76% rename from content/public/test/android/interstitial_page_delegate_android.cc rename to content/browser/android/interstitial_page_delegate_android.cc index d59c07d..81b57c0f 100644 --- a/content/public/test/android/interstitial_page_delegate_android.cc +++ b/content/browser/android/interstitial_page_delegate_android.cc
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/test/android/interstitial_page_delegate_android.h" +#include "content/browser/android/interstitial_page_delegate_android.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "content/public/browser/interstitial_page.h" -#include "content/public/browser/web_contents.h" #include "jni/InterstitialPageDelegateAndroid_jni.h" using base::android::AttachCurrentThread; @@ -21,7 +20,10 @@ JNIEnv* env, jobject obj, const std::string& html_content) - : weak_java_obj_(env, obj), html_content_(html_content), page_(NULL) {} + : weak_java_obj_(env, obj), + html_content_(html_content), + page_(NULL) { +} InterstitialPageDelegateAndroid::~InterstitialPageDelegateAndroid() { JNIEnv* env = AttachCurrentThread(); @@ -44,20 +46,6 @@ page_->DontProceed(); } -void InterstitialPageDelegateAndroid::ShowInterstitialPage( - JNIEnv* env, - const JavaParamRef<jobject>& obj, - const JavaParamRef<jstring>& jurl, - const JavaParamRef<jobject>& jweb_contents) { - WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents); - DCHECK(web_contents); - GURL url(base::android::ConvertJavaStringToUTF8(env, jurl)); - InterstitialPage* interstitial = - InterstitialPage::Create(web_contents, false, url, this); - set_interstitial_page(interstitial); - interstitial->Show(); -} - std::string InterstitialPageDelegateAndroid::GetHTMLContents() { return html_content_; } @@ -84,8 +72,8 @@ std::string sanitized_command(command); // The JSONified response has quotes, remove them. if (sanitized_command.length() > 1 && sanitized_command[0] == '"') { - sanitized_command = - sanitized_command.substr(1, sanitized_command.length() - 2); + sanitized_command = sanitized_command.substr( + 1, sanitized_command.length() - 2); } Java_InterstitialPageDelegateAndroid_commandReceived(
diff --git a/content/public/test/android/interstitial_page_delegate_android.h b/content/browser/android/interstitial_page_delegate_android.h similarity index 77% rename from content/public/test/android/interstitial_page_delegate_android.h rename to content/browser/android/interstitial_page_delegate_android.h index a2ef9f0..b4900e2 100644 --- a/content/public/test/android/interstitial_page_delegate_android.h +++ b/content/browser/android/interstitial_page_delegate_android.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_PUBLIC_TEST_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_ -#define CONTENT_PUBLIC_TEST_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_ +#ifndef CONTENT_BROWSER_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_ +#define CONTENT_BROWSER_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_ #include <jni.h> #include <string> @@ -11,6 +11,7 @@ #include "base/android/jni_weak_ref.h" #include "base/compiler_specific.h" #include "base/macros.h" +#include "content/common/content_export.h" #include "content/public/browser/interstitial_page_delegate.h" namespace content { @@ -32,11 +33,6 @@ void Proceed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void DontProceed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - void ShowInterstitialPage( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jstring>& jurl, - const base::android::JavaParamRef<jobject>& jweb_contents); // Implementation of InterstitialPageDelegate std::string GetHTMLContents() override; @@ -55,4 +51,4 @@ } // namespace content -#endif // CONTENT_PUBLIC_TEST_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_ +#endif // CONTENT_BROWSER_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index e482a432..75021cf 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1151,8 +1151,8 @@ // CompositingModeReporter. return; #else - if (features::IsMusEnabled()) { - // Mus == ChromeOS, which doesn't support software compositing, so no need + if (features::IsMashEnabled()) { + // Mash == ChromeOS, which doesn't support software compositing, so no need // to report compositing mode. return; } @@ -1189,7 +1189,7 @@ InitializeMojo(); #if BUILDFLAG(ENABLE_MUS) - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableSurfaceSynchronization); } @@ -1460,12 +1460,13 @@ // Env creates the compositor. Aura widgets need the compositor to be created // before they can be initialized by the browser. - env_ = aura::Env::CreateInstance( - features::IsMusEnabled() ? aura::Env::Mode::MUS : aura::Env::Mode::LOCAL); + env_ = aura::Env::CreateInstance(features::IsMashEnabled() + ? aura::Env::Mode::MUS + : aura::Env::Mode::LOCAL); #endif // defined(USE_AURA) #if BUILDFLAG(ENABLE_MUS) - if (features::IsMusEnabled()) + if (features::IsMashEnabled()) image_cursors_set_ = std::make_unique<ui::ImageCursorsSet>(); #endif
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc index 751c113..04799d6 100644 --- a/content/browser/devtools/devtools_url_loader_interceptor.cc +++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -172,6 +172,7 @@ const base::UnguessableToken& frame_token, int32_t process_id, std::unique_ptr<CreateLoaderParameters> create_loader_params, + bool is_download, network::mojom::URLLoaderRequest loader_request, network::mojom::URLLoaderClientPtr client, network::mojom::URLLoaderFactoryPtr target_factory); @@ -263,6 +264,7 @@ InterceptionStage stage_; std::unique_ptr<CreateLoaderParameters> create_loader_params_; + const bool is_download_; mojo::Binding<network::mojom::URLLoaderClient> client_binding_; mojo::Binding<network::mojom::URLLoader> loader_binding_; @@ -308,6 +310,7 @@ void CreateJob(const base::UnguessableToken& frame_token, int32_t process_id, + bool is_download, std::unique_ptr<CreateLoaderParameters> create_params, network::mojom::URLLoaderRequest loader_request, network::mojom::URLLoaderClientPtr client, @@ -317,10 +320,10 @@ static int last_id = 0; std::string id = base::StringPrintf("interception-job-%d", ++last_id); - InterceptionJob* job = - new InterceptionJob(this, id, frame_token, process_id, - std::move(create_params), std::move(loader_request), - std::move(client), std::move(target_factory)); + InterceptionJob* job = new InterceptionJob( + this, id, frame_token, process_id, std::move(create_params), + is_download, std::move(loader_request), std::move(client), + std::move(target_factory)); jobs_.emplace(std::move(id), job); } @@ -400,6 +403,7 @@ DevToolsURLLoaderFactoryProxy( const base::UnguessableToken& frame_token, int32_t process_id, + bool is_download, network::mojom::URLLoaderFactoryRequest loader_request, network::mojom::URLLoaderFactoryPtrInfo target_factory_info, base::WeakPtr<DevToolsURLLoaderInterceptor::Impl> interceptor); @@ -424,6 +428,7 @@ const base::UnguessableToken frame_token_; const int32_t process_id_; + const bool is_download_; network::mojom::URLLoaderFactoryPtr target_factory_; base::WeakPtr<DevToolsURLLoaderInterceptor::Impl> interceptor_; @@ -435,11 +440,13 @@ DevToolsURLLoaderFactoryProxy::DevToolsURLLoaderFactoryProxy( const base::UnguessableToken& frame_token, int32_t process_id, + bool is_download, network::mojom::URLLoaderFactoryRequest loader_request, network::mojom::URLLoaderFactoryPtrInfo target_factory_info, base::WeakPtr<DevToolsURLLoaderInterceptor::Impl> interceptor) : frame_token_(frame_token), process_id_(process_id), + is_download_(is_download), interceptor_(std::move(interceptor)) { DETACH_FROM_SEQUENCE(sequence_checker_); BrowserThread::PostTask( @@ -472,9 +479,9 @@ routing_id, request_id, options, request, traffic_annotation); network::mojom::URLLoaderFactoryPtr factory_clone; target_factory_->Clone(MakeRequest(&factory_clone)); - interceptor->CreateJob(frame_token_, process_id_, std::move(creation_params), - std::move(loader), std::move(client), - std::move(factory_clone)); + interceptor->CreateJob(frame_token_, process_id_, is_download_, + std::move(creation_params), std::move(loader), + std::move(client), std::move(factory_clone)); } void DevToolsURLLoaderFactoryProxy::StartOnIO( @@ -593,6 +600,7 @@ bool DevToolsURLLoaderInterceptor::CreateProxyForInterception( const base::UnguessableToken frame_token, int process_id, + bool is_download, network::mojom::URLLoaderFactoryRequest* request) const { if (!enabled_) return false; @@ -601,7 +609,7 @@ network::mojom::URLLoaderFactoryPtrInfo target_ptr_info; *request = MakeRequest(&target_ptr_info); - new DevToolsURLLoaderFactoryProxy(frame_token, process_id, + new DevToolsURLLoaderFactoryProxy(frame_token, process_id, is_download, std::move(original_request), std::move(target_ptr_info), weak_impl_); return true; @@ -613,6 +621,7 @@ const base::UnguessableToken& frame_token, int process_id, std::unique_ptr<CreateLoaderParameters> create_loader_params, + bool is_download, network::mojom::URLLoaderRequest loader_request, network::mojom::URLLoaderClientPtr client, network::mojom::URLLoaderFactoryPtr target_factory) @@ -627,6 +636,7 @@ report_upload_(!!create_loader_params->request.request_body), interceptor_(interceptor), create_loader_params_(std::move(create_loader_params)), + is_download_(is_download), client_binding_(this), loader_binding_(this), client_(std::move(client)), @@ -1132,8 +1142,8 @@ const network::ResourceRequest& request = create_loader_params_->request; request_info->is_download = request_info->is_navigation && request.allow_download && - navigation_loader_util::IsDownload(request.url, head.headers.get(), - head.mime_type); + (is_download_ || navigation_loader_util::IsDownload( + request.url, head.headers.get(), head.mime_type)); NotifyClient(std::move(request_info)); }
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.h b/content/browser/devtools/devtools_url_loader_interceptor.h index 36f3774..3957091 100644 --- a/content/browser/devtools/devtools_url_loader_interceptor.h +++ b/content/browser/devtools/devtools_url_loader_interceptor.h
@@ -53,6 +53,7 @@ bool CreateProxyForInterception( const base::UnguessableToken frame_token, int process_id, // 0 for navigation + bool is_download, network::mojom::URLLoaderFactoryRequest* request) const; private:
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 567b26c7..65963b2 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1857,10 +1857,11 @@ bool NetworkHandler::MaybeCreateProxyForInterception( const base::UnguessableToken& frame_token, int process_id, + bool is_download, network::mojom::URLLoaderFactoryRequest* target_factory_request) { return url_loader_interceptor_ && url_loader_interceptor_->CreateProxyForInterception( - frame_token, process_id, target_factory_request); + frame_token, process_id, is_download, target_factory_request); } void NetworkHandler::ApplyOverrides(net::HttpRequestHeaders* headers,
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h index 2669e08..a2f0a5c 100644 --- a/content/browser/devtools/protocol/network_handler.h +++ b/content/browser/devtools/protocol/network_handler.h
@@ -135,6 +135,7 @@ bool MaybeCreateProxyForInterception( const base::UnguessableToken& frame_token, int process_id, + bool is_download, network::mojom::URLLoaderFactoryRequest* target_factory_request); void ApplyOverrides(net::HttpRequestHeaders* headers,
diff --git a/content/browser/devtools/protocol/target_auto_attacher.cc b/content/browser/devtools/protocol/target_auto_attacher.cc index e8091de..c194d82 100644 --- a/content/browser/devtools/protocol/target_auto_attacher.cc +++ b/content/browser/devtools/protocol/target_auto_attacher.cc
@@ -170,7 +170,10 @@ DCHECK(old_cross_process); auto it = auto_attached_hosts_.find(agent_host); - DCHECK(it != auto_attached_hosts_.end()); + // This should not happen in theory, but error pages are sometimes not + // picked up. See https://crbug.com/836511 and https://crbug.com/817881. + if (it == auto_attached_hosts_.end()) + return nullptr; auto_attached_hosts_.erase(it); detach_callback_.Run(agent_host.get()); return nullptr;
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc index 7a3e181..1ebf94f 100644 --- a/content/browser/devtools/protocol/target_handler.cc +++ b/content/browser/devtools/protocol/target_handler.cc
@@ -392,8 +392,12 @@ return Response::Error("Not supported"); } -Response TargetHandler::DisposeBrowserContext(const std::string& context_id, - bool* out_success) { +Response TargetHandler::DisposeBrowserContext(const std::string& context_id) { + return Response::Error("Not supported"); +} + +Response TargetHandler::GetBrowserContexts( + std::unique_ptr<protocol::Array<String>>* browser_context_ids) { return Response::Error("Not supported"); }
diff --git a/content/browser/devtools/protocol/target_handler.h b/content/browser/devtools/protocol/target_handler.h index 6bb18ca..7d75e62a 100644 --- a/content/browser/devtools/protocol/target_handler.h +++ b/content/browser/devtools/protocol/target_handler.h
@@ -63,8 +63,9 @@ Response CloseTarget(const std::string& target_id, bool* out_success) override; Response CreateBrowserContext(std::string* out_context_id) override; - Response DisposeBrowserContext(const std::string& context_id, - bool* out_success) override; + Response DisposeBrowserContext(const std::string& context_id) override; + Response GetBrowserContexts( + std::unique_ptr<protocol::Array<String>>* browser_context_ids) override; Response CreateTarget(const std::string& url, Maybe<int> width, Maybe<int> height,
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 572843f..52325be 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -296,6 +296,7 @@ bool RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( RenderFrameHostImpl* rfh, bool is_navigation, + bool is_download, network::mojom::URLLoaderFactoryRequest* target_factory_request) { FrameTreeNode* frame_tree_node = rfh->frame_tree_node(); base::UnguessableToken frame_token = frame_tree_node->devtools_frame_token(); @@ -304,9 +305,10 @@ if (!agent_host) return false; int process_id = is_navigation ? 0 : rfh->GetProcess()->GetID(); + DCHECK(!is_download || is_navigation); for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) { - if (network->MaybeCreateProxyForInterception(frame_token, process_id, - target_factory_request)) { + if (network->MaybeCreateProxyForInterception( + frame_token, process_id, is_download, target_factory_request)) { return true; } }
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index afd6191..448d71a 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -73,6 +73,7 @@ static bool WillCreateURLLoaderFactory( RenderFrameHostImpl* rfh, bool is_navigation, + bool is_download, network::mojom::URLLoaderFactoryRequest* loader_factory_request); static void OnNavigationRequestWillBeSent(
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 7d2fb68..eb14d25 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -251,7 +251,8 @@ scoped_refptr<download::DownloadURLLoaderFactoryGetter> CreateDownloadURLLoaderFactoryGetter(StoragePartitionImpl* storage_partition, - RenderFrameHost* rfh) { + RenderFrameHost* rfh, + bool is_download) { network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info; network::mojom::URLLoaderFactoryRequest proxy_factory_request; if (rfh) { @@ -259,7 +260,7 @@ network::mojom::URLLoaderFactoryRequest devtools_factory_request = MakeRequest(&devtools_factory_ptr_info); if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( - static_cast<RenderFrameHostImpl*>(rfh), true, + static_cast<RenderFrameHostImpl*>(rfh), true, is_download, &devtools_factory_request)) { proxy_factory_ptr_info = std::move(devtools_factory_ptr_info); proxy_factory_request = std::move(devtools_factory_request); @@ -1010,8 +1011,8 @@ std::move(resource_request), render_process_id, render_frame_id, site_url, tab_url, tab_referrer_url, std::move(url_chain), std::move(response), std::move(cert_status), std::move(url_loader_client_endpoints), - CreateDownloadURLLoaderFactoryGetter(storage_partition, - render_frame_host)); + CreateDownloadURLLoaderFactoryGetter(storage_partition, render_frame_host, + false)); } void DownloadManagerImpl::BeginDownloadInternal( @@ -1057,7 +1058,7 @@ params->url(), std::move(blob_data_handle)); } else { url_loader_factory_getter = - CreateDownloadURLLoaderFactoryGetter(storage_partition, rfh); + CreateDownloadURLLoaderFactoryGetter(storage_partition, rfh, true); } in_progress_manager_->BeginDownload(
diff --git a/content/browser/find_request_manager.cc b/content/browser/find_request_manager.cc index f6b9b80..c53d5005 100644 --- a/content/browser/find_request_manager.cc +++ b/content/browser/find_request_manager.cc
@@ -9,6 +9,7 @@ #include "base/containers/queue.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/associated_interface_provider_impl.h" #include "content/common/frame_messages.h" #include "content/public/browser/guest_mode.h" @@ -337,8 +338,7 @@ // The new active match is in a different frame than the previous, so // the previous active frame needs to be informed (to clear its active // match highlighting). - active_frame_->Send(new FrameMsg_ClearActiveFindMatch( - active_frame_->GetRoutingID())); + ClearActiveFindMatch(); } active_frame_ = rfh; relative_active_match_ordinal_ = active_match_ordinal; @@ -435,6 +435,13 @@ } } +void FindRequestManager::ClearActiveFindMatch() { + blink::mojom::FindInPageAssociatedPtr active_frame_ptr; + active_frame_->GetRemoteAssociatedInterfaces()->GetInterface( + &active_frame_ptr); + active_frame_ptr->ClearActiveFindMatch(); +} + #if defined(OS_ANDROID) void FindRequestManager::ActivateNearestFindResult(float x, float y) { if (current_session_id_ == kInvalidId)
diff --git a/content/browser/find_request_manager.h b/content/browser/find_request_manager.h index 1939bc5..ae8a289a 100644 --- a/content/browser/find_request_manager.h +++ b/content/browser/find_request_manager.h
@@ -14,6 +14,7 @@ #include "content/common/content_export.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/stop_find_action.h" +#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" #include "third_party/blink/public/web/web_find_options.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" @@ -58,6 +59,9 @@ // called whenever a frame is discovered to no longer exist. void RemoveFrame(RenderFrameHost* rfh); + // Tells active frame to clear the active match highlighting. + void ClearActiveFindMatch(); + #if defined(OS_ANDROID) // Selects and zooms to the find result nearest to the point (x, y), defined // in find-in-page coordinates.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 0fd6993..f289fb7 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3794,7 +3794,8 @@ this, false /* is_navigation */, &factory_request); // Keep DevTools proxy lasy, i.e. closest to the network. RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( - this, false, &factory_request); + this, false /* is_navigation */, false /* is_download */, + &factory_request); factory.second->Clone(std::move(factory_request)); subresource_loader_factories->factories_info().emplace( factory.first, std::move(factory_proxy_info)); @@ -4366,7 +4367,8 @@ this, false /* is_navigation */, &default_factory_request); // Keep DevTools proxy lasy, i.e. closest to the network. RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( - this, false, &default_factory_request); + this, false /* is_navigation */, false /* is_download */, + &default_factory_request); StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>( BrowserContext::GetStoragePartition(context, GetSiteInstance())); if (g_create_network_factory_callback_for_test.Get().is_null()) {
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc index d6ae186..91bf248 100644 --- a/content/browser/frame_host/render_frame_message_filter.cc +++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -13,6 +13,7 @@ #include "base/debug/alias.h" #include "base/macros.h" #include "base/strings/string_util.h" +#include "base/syslog_logging.h" #include "base/unguessable_token.h" #include "build/build_config.h" #include "components/download/public/common/download_url_parameters.h" @@ -490,8 +491,11 @@ ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (!policy->CanAccessDataForOrigin(render_process_id_, url)) { - bad_message::ReceivedBadMessage(this, - bad_message::RFMF_SET_COOKIE_BAD_ORIGIN); + bad_message::BadMessageReason reason = + bad_message::RFMF_SET_COOKIE_BAD_ORIGIN; + SYSLOG(WARNING) << "Killing renderer: illegal cookie write. Reason: " + << reason; + bad_message::ReceivedBadMessage(this, reason); return; } @@ -531,8 +535,11 @@ ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (!policy->CanAccessDataForOrigin(render_process_id_, url)) { - bad_message::ReceivedBadMessage(this, - bad_message::RFMF_GET_COOKIES_BAD_ORIGIN); + bad_message::BadMessageReason reason = + bad_message::RFMF_GET_COOKIES_BAD_ORIGIN; + SYSLOG(WARNING) << "Killing renderer: illegal cookie read. Reason: " + << reason; + bad_message::ReceivedBadMessage(this, reason); std::move(callback).Run(std::string()); return; }
diff --git a/content/browser/gpu/gpu_data_manager_testing_autogen.cc b/content/browser/gpu/gpu_data_manager_testing_autogen.cc index 43b1d39..adb983a 100644 --- a/content/browser/gpu/gpu_data_manager_testing_autogen.cc +++ b/content/browser/gpu/gpu_data_manager_testing_autogen.cc
@@ -19,14 +19,14 @@ { 1, // id "GpuDataManagerImplPrivateTest.GpuSideBlacklisting.0", - arraysize(kFeatureListForEntry1), // features size - kFeatureListForEntry1, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry1), // features size + kFeatureListForEntry1, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -39,6 +39,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -47,14 +49,14 @@ { 2, // id "GpuDataManagerImplPrivateTest.GpuSideBlacklisting.1", - arraysize(kFeatureListForEntry2), // features size - kFeatureListForEntry2, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry2), // features size + kFeatureListForEntry2, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -67,6 +69,8 @@ nullptr, // driver info &kGLStringsForEntry2, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -75,14 +79,14 @@ { 3, // id "GpuDataManagerImplPrivateTest.GpuSideBlacklistingWebGL.0", - arraysize(kFeatureListForEntry3), // features size - kFeatureListForEntry3, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry3), // features size + kFeatureListForEntry3, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -95,6 +99,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -103,14 +109,14 @@ { 4, // id "GpuDataManagerImplPrivateTest.GpuSideBlacklistingWebGL.1", - arraysize(kFeatureListForEntry4), // features size - kFeatureListForEntry4, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry4), // features size + kFeatureListForEntry4, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -123,6 +129,8 @@ nullptr, // driver info &kGLStringsForEntry4, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -131,14 +139,14 @@ { 5, // id "GpuDataManagerImplPrivateTest.GpuSideException", - arraysize(kFeatureListForEntry5), // features size - kFeatureListForEntry5, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry5), // features size + kFeatureListForEntry5, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -151,22 +159,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry5), // exceptions count - kExceptionsForEntry5, // exceptions + base::size(kExceptionsForEntry5), // exceptions count + kExceptionsForEntry5, // exceptions }, { 6, // id "GpuDataManagerImplPrivateTest.BlacklistAllFeatures", - arraysize(kFeatureListForEntry6), // features size - kFeatureListForEntry6, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry6), // features size + kFeatureListForEntry6, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -179,6 +189,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -187,14 +199,14 @@ { 7, // id "GpuDataManagerImplPrivateTest.UpdateActiveGpu", - arraysize(kFeatureListForEntry7), // features size - kFeatureListForEntry7, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry7), // features size + kFeatureListForEntry7, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -207,6 +219,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count
diff --git a/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h b/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h index 12a2a5491..9c282ee 100644 --- a/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h +++ b/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h
@@ -25,6 +25,8 @@ nullptr, // driver info &kGLStringsForEntry5Exception0, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, };
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 41a7ad5..266e6b74 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -445,7 +445,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(USE_AURA) - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( ui::mojom::kServiceName, std::move(request)); return;
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc index 76e8358a..494ecda0 100644 --- a/content/browser/loader/cross_site_document_blocking_browsertest.cc +++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -433,7 +433,8 @@ "valid.js", "json-list.js", "nosniff.json-list.js", - "js-html-polyglot.html"}; + "js-html-polyglot.html", + "js-html-polyglot2.html"}; for (const char* resource : sniff_allowed_resources) { SCOPED_TRACE(base::StringPrintf("... while testing page: %s", resource)); base::HistogramTester histograms;
diff --git a/content/browser/loader/cross_site_document_resource_handler_unittest.cc b/content/browser/loader/cross_site_document_resource_handler_unittest.cc index 1625ce1a..7f66b56 100644 --- a/content/browser/loader/cross_site_document_resource_handler_unittest.cc +++ b/content/browser/loader/cross_site_document_resource_handler_unittest.cc
@@ -850,10 +850,10 @@ false, // include_no_sniff_header false, // simulate_range_response AccessControlAllowOriginHeader::kOmit, // cors_response - {" <!--", "\t -", "-", "->", "<", "s", "c", "r", "i", "p", + {" <!--", "\t -", "-", "->", "\n", "<", "s", "c", "r", "i", "p", "t"}, // packets Verdict::kBlock, // verdict - 10, // verdict_packet + 11, // verdict_packet }, { "Blocked: slow-arriving html with commented-out xml tag", @@ -867,8 +867,8 @@ false, // include_no_sniff_header false, // simulate_range_response AccessControlAllowOriginHeader::kOmit, // cors_response - {" <!--", " <?xml ", "-->", "<", "h", "e", "a", "d"}, // packets - Verdict::kBlock, // verdict + {" <!--", " <?xml ", "-->\n", "<", "h", "e", "a", "d"}, // packets + Verdict::kBlock, // verdict 7, // verdict_packet }, {
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc index c8d2ef8..3cc782fc 100644 --- a/content/browser/loader/navigation_url_loader_network_service.cc +++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -1231,7 +1231,8 @@ frame_tree_node->current_frame_host(), true /* is_navigation */, &factory_request); if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( - frame_tree_node->current_frame_host(), true, &factory_request)) { + frame_tree_node->current_frame_host(), true, false, + &factory_request)) { use_proxy = true; } if (use_proxy) {
diff --git a/content/browser/media/audio_input_stream_broker.cc b/content/browser/media/audio_input_stream_broker.cc index d4bbd8c..8b5ae78 100644 --- a/content/browser/media/audio_input_stream_broker.cc +++ b/content/browser/media/audio_input_stream_broker.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/command_line.h" +#include "base/memory/read_only_shared_memory_region.h" #include "content/browser/browser_main_loop.h" #include "content/browser/media/media_internals.h" #include "content/public/browser/browser_thread.h" @@ -16,6 +17,7 @@ #include "content/public/common/content_client.h" #include "media/audio/audio_logging.h" #include "media/base/media_switches.h" +#include "media/base/user_input_monitor.h" #include "mojo/public/cpp/system/platform_handle.h" #if defined(OS_CHROMEOS) @@ -61,15 +63,19 @@ params_.set_format(media::AudioParameters::AUDIO_FAKE); } + BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance(); + // May be null in unit tests. + if (!browser_main_loop) + return; + #if defined(OS_CHROMEOS) if (params_.channel_layout() == media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { - BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance(); - - // May be null in unit tests. - if (browser_main_loop) browser_main_loop->keyboard_mic_registration()->Register(); } +#else + user_input_monitor_ = static_cast<media::UserInputMonitorBase*>( + browser_main_loop->user_input_monitor()); #endif } @@ -85,6 +91,9 @@ if (browser_main_loop) browser_main_loop->keyboard_mic_registration()->Deregister(); } +#else + // Check that DisableKeyPressMonitoring() was called. + DCHECK(!user_input_monitor_); #endif auto* process_host = RenderProcessHost::FromID(render_process_id()); @@ -100,6 +109,12 @@ DCHECK(!observer_binding_.is_bound()); DCHECK(!client_request_); + base::ReadOnlySharedMemoryRegion key_press_count_buffer; + if (user_input_monitor_) { + key_press_count_buffer = + user_input_monitor_->EnableKeyPressMonitoringWithMapping(); + } + media::mojom::AudioInputStreamClientPtr client; client_request_ = mojo::MakeRequest(&client); @@ -126,7 +141,7 @@ media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER, log_component_id, render_process_id(), render_frame_id()), device_id_, params_, shared_memory_count_, enable_agc_, - mojo::ScopedSharedBufferHandle(), + mojo::WrapReadOnlySharedMemoryRegion(std::move(key_press_count_buffer)), base::BindOnce(&AudioInputStreamBroker::StreamCreated, weak_ptr_factory_.GetWeakPtr(), std::move(stream))); } @@ -155,6 +170,14 @@ void AudioInputStreamBroker::Cleanup() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (user_input_monitor_) { + user_input_monitor_->DisableKeyPressMonitoring(); + + // Set to nullptr to check that DisableKeyPressMonitoring() was called + // before destructor + user_input_monitor_ = nullptr; + } + std::move(deleter_).Run(this); }
diff --git a/content/browser/media/audio_input_stream_broker.h b/content/browser/media/audio_input_stream_broker.h index 4697479..52f5ab0 100644 --- a/content/browser/media/audio_input_stream_broker.h +++ b/content/browser/media/audio_input_stream_broker.h
@@ -17,6 +17,10 @@ #include "mojo/public/cpp/bindings/binding.h" #include "services/audio/public/mojom/stream_factory.mojom.h" +namespace media { +class UserInputMonitorBase; +} + namespace content { // AudioInputStreamBroker is used to broker a connection between a client @@ -53,6 +57,7 @@ media::AudioParameters params_; const uint32_t shared_memory_count_; const bool enable_agc_; + media::UserInputMonitorBase* user_input_monitor_ = nullptr; DeleterCallback deleter_;
diff --git a/content/browser/media/forwarding_audio_stream_factory.cc b/content/browser/media/forwarding_audio_stream_factory.cc index e94f4b3..30edea5 100644 --- a/content/browser/media/forwarding_audio_stream_factory.cc +++ b/content/browser/media/forwarding_audio_stream_factory.cc
@@ -7,6 +7,7 @@ #include <utility> #include "content/browser/media/capture/audio_mirroring_manager.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" @@ -34,6 +35,17 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); } +// static +ForwardingAudioStreamFactory* ForwardingAudioStreamFactory::ForFrame( + RenderFrameHost* frame) { + auto* contents = + static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(frame)); + if (!contents) + return nullptr; + + return contents->GetAudioStreamFactory(); +} + void ForwardingAudioStreamFactory::CreateInputStream( RenderFrameHost* frame, const std::string& device_id,
diff --git a/content/browser/media/forwarding_audio_stream_factory.h b/content/browser/media/forwarding_audio_stream_factory.h index fce7320d..ea0748aa 100644 --- a/content/browser/media/forwarding_audio_stream_factory.h +++ b/content/browser/media/forwarding_audio_stream_factory.h
@@ -43,6 +43,11 @@ ~ForwardingAudioStreamFactory() final; + // Returns the ForwardingAudioStreamFactory which takes care of stream + // creation for |frame|. Returns null if |frame| is null or if the frame + // doesn't belong to a WebContents. + static ForwardingAudioStreamFactory* ForFrame(RenderFrameHost* frame); + const base::UnguessableToken& group_id() { return group_id_; } // TODO(https://crbug.com/803102): Add loopback and muting streams.
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc index b29284a..9e9fd954 100644 --- a/content/browser/media/media_interface_proxy.cc +++ b/content/browser/media/media_interface_proxy.cc
@@ -195,6 +195,14 @@ #endif } +void MediaInterfaceProxy::CreateDecryptor( + int cdm_id, + media::mojom::DecryptorRequest request) { + InterfaceFactory* factory = GetMediaInterfaceFactory(); + if (factory) + factory->CreateDecryptor(cdm_id, std::move(request)); +} + void MediaInterfaceProxy::CreateCdmProxy( const std::string& cdm_guid, media::mojom::CdmProxyRequest request) {
diff --git a/content/browser/media/media_interface_proxy.h b/content/browser/media/media_interface_proxy.h index 08b7661..ce7e4dfb 100644 --- a/content/browser/media/media_interface_proxy.h +++ b/content/browser/media/media_interface_proxy.h
@@ -51,6 +51,8 @@ media::mojom::RendererRequest request) final; void CreateCdm(const std::string& key_system, media::mojom::ContentDecryptionModuleRequest request) final; + void CreateDecryptor(int cdm_id, + media::mojom::DecryptorRequest request) final; void CreateCdmProxy(const std::string& cdm_guid, media::mojom::CdmProxyRequest request) final;
diff --git a/content/browser/oop_browsertest.cc b/content/browser/oop_browsertest.cc index e3502bb0..5fe99fd 100644 --- a/content/browser/oop_browsertest.cc +++ b/content/browser/oop_browsertest.cc
@@ -35,7 +35,7 @@ command_line->AppendSwitch(switches::kEnablePixelOutputInTests); command_line->AppendSwitch(switches::kEnableOOPRasterization); - const bool use_gpu_in_tests = !features::IsMusEnabled(); + const bool use_gpu_in_tests = !features::IsMashEnabled(); if (use_gpu_in_tests) command_line->AppendSwitch(switches::kUseGpuInTests); }
diff --git a/content/browser/picture_in_picture/overlay_surface_embedder.cc b/content/browser/picture_in_picture/overlay_surface_embedder.cc index 27263a6..5a7da3d 100644 --- a/content/browser/picture_in_picture/overlay_surface_embedder.cc +++ b/content/browser/picture_in_picture/overlay_surface_embedder.cc
@@ -40,15 +40,21 @@ void OverlaySurfaceEmbedder::UpdateLayerBounds() { // Update the size and position of the video to stretch on the entire window. gfx::Size window_size = window_->GetBounds().size(); - video_layer_->SetBounds(gfx::Rect(gfx::Point(0, 0), window_size)); + gfx::Rect window_bounds = gfx::Rect(gfx::Point(0, 0), window_size); + video_layer_->SetBounds(window_bounds); video_layer_->SetSurfaceSize(window_size); // Update the size and position of controls. + controls_background_layer_->SetBounds(window_bounds); close_controls_layer_->SetBounds(window_->GetCloseControlsBounds()); play_pause_controls_layer_->SetBounds(window_->GetPlayPauseControlsBounds()); } void OverlaySurfaceEmbedder::AddControlsLayers() { + controls_background_layer_ = window_->GetControlsBackgroundLayer(); + controls_background_layer_->SetBounds( + gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size())); + close_controls_layer_ = window_->GetCloseControlsLayer(); close_controls_layer_->SetFillsBoundsOpaquely(false); close_controls_layer_->SetBounds(window_->GetCloseControlsBounds()); @@ -57,6 +63,7 @@ play_pause_controls_layer_->SetFillsBoundsOpaquely(false); play_pause_controls_layer_->SetBounds(window_->GetPlayPauseControlsBounds()); + window_->GetLayer()->Add(controls_background_layer_); window_->GetLayer()->Add(close_controls_layer_); window_->GetLayer()->Add(play_pause_controls_layer_); }
diff --git a/content/browser/picture_in_picture/overlay_surface_embedder.h b/content/browser/picture_in_picture/overlay_surface_embedder.h index d4a2ae9..d4b977f 100644 --- a/content/browser/picture_in_picture/overlay_surface_embedder.h +++ b/content/browser/picture_in_picture/overlay_surface_embedder.h
@@ -37,6 +37,7 @@ // Owned by the OverlayWindow implementation. ui::Layer* video_layer_ = nullptr; + ui::Layer* controls_background_layer_ = nullptr; ui::Layer* close_controls_layer_ = nullptr; ui::Layer* play_pause_controls_layer_ = nullptr;
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc index c0c092a..c3ed32b 100644 --- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc +++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -57,8 +57,6 @@ media_web_contents_observer_ = static_cast<WebContentsImpl* const>(initiator_) ->media_web_contents_observer(); - media_player_id_ = - media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId(); window_ = GetContentClient()->browser()->CreateWindowForPictureInPicture(this); @@ -88,6 +86,13 @@ DCHECK(surface_id.is_valid()); surface_id_ = surface_id; + // Update the media player id in step with the video surface id. If the + // surface id was updated for the same video, this is a no-op. This could + // be updated for a different video if another media player on the same + // |initiator_| enters Picture-in-Picture mode. + media_player_id_ = + media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId(); + window_->UpdateVideoSize(natural_size); if (!embedder_)
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index 7f0ce8a..f823af11 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -212,6 +212,8 @@ uint32_t capture_sequence_number_ = 0; + bool is_first_navigation_ = true; + base::WeakPtrFactory<BrowserCompositorMac> weak_factory_; };
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index c1c7a42..a03b35db 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -529,12 +529,17 @@ } void BrowserCompositorMac::DidNavigate() { - const viz::LocalSurfaceId& new_local_surface_id = - dfh_local_surface_id_allocator_.GenerateId(); + // The first navigation does not need a new LocalSurfaceID. The renderer can + // use the ID that was already provided. + if (!is_first_navigation_) { + const viz::LocalSurfaceId& new_local_surface_id = + dfh_local_surface_id_allocator_.GenerateId(); + delegated_frame_host_->SynchronizeVisualProperties( + new_local_surface_id, dfh_size_dip_, + cc::DeadlinePolicy::UseExistingDeadline()); + } + is_first_navigation_ = false; client_->SynchronizeVisualProperties(); - delegated_frame_host_->SynchronizeVisualProperties( - new_local_surface_id, dfh_size_dip_, - cc::DeadlinePolicy::UseExistingDeadline()); delegated_frame_host_->DidNavigate(); }
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 4218e10..e5c4d8d 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -257,7 +257,7 @@ public: AndroidOutputSurface( scoped_refptr<ui::ContextProviderCommandBuffer> context_provider, - base::Closure swap_buffers_callback) + base::RepeatingCallback<void(gfx::Size)> swap_buffers_callback) : viz::OutputSurface(std::move(context_provider)), swap_buffers_callback_(std::move(swap_buffers_callback)), overlay_candidate_validator_( @@ -272,9 +272,10 @@ if (LatencyInfoHasSnapshotRequest(frame.latency_info)) GetCommandBufferProxy()->SetSnapshotRequested(); - auto callback = base::BindOnce( - &AndroidOutputSurface::OnSwapBuffersCompleted, - weak_ptr_factory_.GetWeakPtr(), std::move(frame.latency_info)); + auto callback = + base::BindOnce(&AndroidOutputSurface::OnSwapBuffersCompleted, + weak_ptr_factory_.GetWeakPtr(), + std::move(frame.latency_info), frame.size); uint32_t flags = 0; if (frame.need_presentation_feedback) flags |= gpu::SwapBuffersFlags::kPresentationFeedback; @@ -347,9 +348,10 @@ } void OnSwapBuffersCompleted(std::vector<ui::LatencyInfo> latency_info, + gfx::Size swap_size, const gpu::SwapBuffersCompleteParams& params) { client_->DidReceiveSwapBuffersAck(params.swap_response.swap_id); - swap_buffers_callback_.Run(); + swap_buffers_callback_.Run(swap_size); UpdateLatencyInfoOnSwap(params.swap_response, &latency_info); RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info); latency_tracker_.OnGpuSwapBuffersCompleted(latency_info); @@ -362,7 +364,7 @@ private: viz::OutputSurfaceClient* client_ = nullptr; - base::Closure swap_buffers_callback_; + base::RepeatingCallback<void(gfx::Size)> swap_buffers_callback_; std::unique_ptr<viz::OverlayCandidateValidator> overlay_candidate_validator_; ui::LatencyTracker latency_tracker_; @@ -852,6 +854,7 @@ viz::RendererSettings renderer_settings; renderer_settings.allow_antialiasing = false; renderer_settings.highp_threshold_min = 2048; + renderer_settings.auto_resize_output_surface = false; auto* gpu_memory_buffer_manager = BrowserMainLoop::GetInstance() ->gpu_channel_establish_factory() ->GetGpuMemoryBufferManager(); @@ -880,8 +883,8 @@ host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); } -void CompositorImpl::DidSwapBuffers() { - client_->DidSwapBuffers(); +void CompositorImpl::DidSwapBuffers(gfx::Size swap_size) { + client_->DidSwapBuffers(swap_size); } cc::UIResourceId CompositorImpl::CreateUIResource(
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index a037726..7237d4f 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -160,7 +160,7 @@ void InitializeDisplay( std::unique_ptr<viz::OutputSurface> display_output_surface, scoped_refptr<viz::ContextProvider> context_provider); - void DidSwapBuffers(); + void DidSwapBuffers(gfx::Size swap_size); bool HavePendingReadbacks();
diff --git a/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc b/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc index e9960e21..f3565b6c 100644 --- a/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc +++ b/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc
@@ -104,14 +104,14 @@ MOCK_METHOD1(OnStreamError, void(int)); }; -class MockUserInputMonitor : public media::UserInputMonitorBase { +class MockUserInputMonitor : public media::UserInputMonitor { public: MockUserInputMonitor() {} uint32_t GetKeyPressCount() const override { return 0; } - MOCK_METHOD0(StartKeyboardMonitoring, void()); - MOCK_METHOD0(StopKeyboardMonitoring, void()); + MOCK_METHOD0(EnableKeyPressMonitoring, void()); + MOCK_METHOD0(DisableKeyPressMonitoring, void()); }; class MockAudioInputStream : public media::AudioInputStream {
diff --git a/content/browser/renderer_host/overscroll_configuration.cc b/content/browser/renderer_host/overscroll_configuration.cc index 51b4e0d..34496b1 100644 --- a/content/browser/renderer_host/overscroll_configuration.cc +++ b/content/browser/renderer_host/overscroll_configuration.cc
@@ -29,6 +29,10 @@ bool g_is_touchpad_overscroll_history_navigation_enabled_initialized = false; bool g_touchpad_overscroll_history_navigation_enabled = false; +// On Windows, we only process 0.3 second inertial events then cancel the +// overscroll if it is not completed yet. +int g_max_inertial_events_before_overscroll_cancellation_in_ms = 300; + float GetStartThresholdMultiplier() { base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); if (!cmd->HasSwitch(switches::kOverscrollStartThreshold)) @@ -148,4 +152,11 @@ g_is_touchpad_overscroll_history_navigation_enabled_initialized = false; } +// static +base::TimeDelta +OverscrollConfig::MaxInertialEventsBeforeOverscrollCancellation() { + return base::TimeDelta::FromMilliseconds( + g_max_inertial_events_before_overscroll_cancellation_in_ms); +} + } // namespace content
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc index 4e323f3..a4bb1af 100644 --- a/content/browser/renderer_host/overscroll_controller.cc +++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -29,6 +29,16 @@ return gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad; } +bool IsGestureScrollUpdateInertialEvent(const blink::WebInputEvent& event) { + if (event.GetType() != blink::WebInputEvent::kGestureScrollUpdate) + return false; + + const blink::WebGestureEvent& gesture = + static_cast<const blink::WebGestureEvent&>(event); + return gesture.data.scroll_update.inertial_phase == + blink::WebGestureEvent::kMomentumPhase; +} + float ClampAbsoluteValue(float value, float max_abs) { DCHECK_LT(0.f, max_abs); return std::max(-max_abs, std::min(value, max_abs)); @@ -86,17 +96,10 @@ bool OverscrollController::ShouldIgnoreInertialEvent( const blink::WebInputEvent& event) const { - if (!ignore_following_inertial_events_ || - event.GetType() != blink::WebInputEvent::kGestureScrollUpdate) { - return false; + return ignore_following_inertial_events_ && + IsGestureScrollUpdateInertialEvent(event); } - const blink::WebGestureEvent& gesture = - static_cast<const blink::WebGestureEvent&>(event); - return gesture.data.scroll_update.inertial_phase == - blink::WebGestureEvent::kMomentumPhase; -} - bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) { if (!ShouldProcessEvent(event)) return false; @@ -108,6 +111,7 @@ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) { ignore_following_inertial_events_ = false; + first_inertial_event_time_.reset(); time_since_last_ignored_scroll_ = event.TimeStamp() - last_ignored_scroll_time_; // Will handle events when processing ACKs to ensure the correct order. @@ -379,10 +383,29 @@ case blink::WebInputEvent::kGestureScrollUpdate: { const blink::WebGestureEvent& gesture = static_cast<const blink::WebGestureEvent&>(event); + bool is_gesture_scroll_update_inertial_event = + IsGestureScrollUpdateInertialEvent(event); event_processed = ProcessOverscroll( gesture.data.scroll_update.delta_x, gesture.data.scroll_update.delta_y, - gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad); + gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad, + is_gesture_scroll_update_inertial_event); + if (is_gesture_scroll_update_inertial_event) { + // Record the timestamp of first inertial event. + if (!first_inertial_event_time_) { + first_inertial_event_time_ = event.TimeStamp(); + break; + } + base::TimeDelta inertial_event_interval = + event.TimeStamp() - first_inertial_event_time_.value(); + if (inertial_event_interval >= + OverscrollConfig::MaxInertialEventsBeforeOverscrollCancellation()) { + ignore_following_inertial_events_ = true; + // Reset overscroll state if fling didn't complete the overscroll + // gesture within the first 20 inertial events. + Cancel(); + } + } break; } case blink::WebInputEvent::kGestureFlingStart: { @@ -422,10 +445,15 @@ bool OverscrollController::ProcessOverscroll(float delta_x, float delta_y, - bool is_touchpad) { + bool is_touchpad, + bool is_inertial) { if (scroll_state_ == ScrollState::CONTENT_CONSUMING) return false; + // Do not start overscroll for inertial events. + if (overscroll_mode_ == OVERSCROLL_NONE && is_inertial) + return false; + overscroll_delta_x_ += delta_x; overscroll_delta_y_ += delta_y;
diff --git a/content/browser/renderer_host/overscroll_controller.h b/content/browser/renderer_host/overscroll_controller.h index 9479f5f..dbc94c17 100644 --- a/content/browser/renderer_host/overscroll_controller.h +++ b/content/browser/renderer_host/overscroll_controller.h
@@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/optional.h" #include "base/time/time.h" #include "cc/input/overscroll_behavior.h" #include "content/common/content_export.h" @@ -112,7 +113,10 @@ // and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_| // and |overscroll_delta_y_|). Returns true if overscroll was handled by the // delegate. - bool ProcessOverscroll(float delta_x, float delta_y, bool is_touchpad); + bool ProcessOverscroll(float delta_x, + float delta_y, + bool is_touchpad, + bool is_inertial); // Completes the desired action from the current gesture. void CompleteAction(); @@ -162,8 +166,9 @@ bool wheel_scroll_latching_enabled_; // A inertial scroll (fling) event may complete an overscroll gesture and - // navigate to a new page, but the inertial scroll can continue to generate - // scroll-update events. These events need to be ignored. + // navigate to a new page or cancel the overscroll animation. In both cases + // inertial scroll can continue to generate scroll-update events. These events + // need to be ignored. bool ignore_following_inertial_events_ = false; // Specifies whether last overscroll was ignored, either due to a command line @@ -177,6 +182,14 @@ // of the current one. base::TimeDelta time_since_last_ignored_scroll_; + // On Windows, we don't generate the inertial events (fling) but receive them + // from Win API. In some cases, we get a long tail of inertial events for a + // couple of seconds. The overscroll animation feels like stuck in these + // cases. So we only process 0.3 second inertial events then cancel the + // overscroll if it is not completed yet. + // Timestamp for the first inertial event (fling) in current stream. + base::Optional<base::TimeTicks> first_inertial_event_time_; + DISALLOW_COPY_AND_ASSIGN(OverscrollController); };
diff --git a/content/browser/renderer_host/overscroll_controller_unittest.cc b/content/browser/renderer_host/overscroll_controller_unittest.cc index aefe4b3..166d1fe3 100644 --- a/content/browser/renderer_host/overscroll_controller_unittest.cc +++ b/content/browser/renderer_host/overscroll_controller_unittest.cc
@@ -201,6 +201,75 @@ 100, 0, blink::kWebGestureDeviceTouchpad, timestamp, true)); } +// Ensure inertial gesture scroll update can not start overscroll. +TEST_F(OverscrollControllerTest, InertialGSUsDoNotStartOverscroll) { + base::TimeTicks timestamp = + blink::WebInputEvent::GetStaticTimeStampForTests(); + // Inertial update event complete the overscroll action. + EXPECT_FALSE(SimulateGestureScrollUpdate( + 100, 0, blink::kWebGestureDeviceTouchpad, timestamp, true)); + SimulateAck(false); + EXPECT_EQ(OVERSCROLL_NONE, controller_mode()); + EXPECT_EQ(OverscrollSource::NONE, controller_source()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode()); +} + +// After 300ms inertial gesture scroll updates, overscroll must get cancelled +// if not completed. +TEST_F(OverscrollControllerTest, OnlyProcessLimitedInertialGSUEvents) { + base::TimeTicks timestamp = + blink::WebInputEvent::GetStaticTimeStampForTests(); + + EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin, + blink::kWebGestureDeviceTouchpad, + timestamp)); + SimulateAck(false); + + EXPECT_FALSE(SimulateGestureScrollUpdate( + 61, 0, blink::kWebGestureDeviceTouchpad, timestamp, false)); + SimulateAck(false); + EXPECT_EQ(OVERSCROLL_EAST, controller_mode()); + EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source()); + EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode()); + + // First inertial. + timestamp += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(SimulateGestureScrollUpdate( + 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true)); + SimulateAck(true); + EXPECT_EQ(OVERSCROLL_EAST, controller_mode()); + EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source()); + EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode()); + + // Not cancel in 10ms. + timestamp += base::TimeDelta::FromMilliseconds(10); + EXPECT_TRUE(SimulateGestureScrollUpdate( + 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true)); + SimulateAck(true); + EXPECT_EQ(OVERSCROLL_EAST, controller_mode()); + EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source()); + EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode()); + + // Cancel after 300ms. + timestamp += base::TimeDelta::FromMilliseconds(291); + EXPECT_TRUE(SimulateGestureScrollUpdate( + 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true)); + SimulateAck(true); + EXPECT_EQ(OVERSCROLL_NONE, controller_mode()); + EXPECT_EQ(OverscrollSource::NONE, controller_source()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode()); + EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode()); + + // Next event should be ignored. + timestamp += base::TimeDelta::FromMilliseconds(100); + EXPECT_TRUE(SimulateGestureScrollUpdate( + 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true)); +} + // Verifies that when pull-to-refresh is disabled, it is not triggered for // neither touchpad nor touchscreen. TEST_F(OverscrollControllerTest, PullToRefreshDisabled) {
diff --git a/content/browser/renderer_host/pepper/ssl_context_helper.cc b/content/browser/renderer_host/pepper/ssl_context_helper.cc index 0596302..1d6fb4c9 100644 --- a/content/browser/renderer_host/pepper/ssl_context_helper.cc +++ b/content/browser/renderer_host/pepper/ssl_context_helper.cc
@@ -35,7 +35,7 @@ net::CTPolicyEnforcer* SSLContextHelper::GetCTPolicyEnforcer() { if (!ct_policy_enforcer_) - ct_policy_enforcer_.reset(new net::CTPolicyEnforcer()); + ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer()); return ct_policy_enforcer_.get(); }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 87436fac..2cec58a 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -264,8 +264,15 @@ } bool RenderWidgetHostViewAndroid::SynchronizeVisualProperties() { - if (delegated_frame_host_) + if (delegated_frame_host_) { delegated_frame_host_->SynchronizeVisualProperties(); + + // TODO(ericrk): This can be removed once surface synchronization is + // enabled. https://crbug.com/835102 + delegated_frame_host_->PixelSizeWillChange( + GetCompositorViewportPixelSize()); + } + return host()->SynchronizeVisualProperties(); }
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 02a7b71..6a0753f 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1714,7 +1714,7 @@ void RenderWidgetHostViewAura::ScheduleEmbed( ui::mojom::WindowTreeClientPtr client, base::OnceCallback<void(const base::UnguessableToken&)> callback) { - DCHECK(features::IsMusEnabled()); + DCHECK(features::IsMashEnabled()); aura::Env::GetInstance()->ScheduleEmbed(std::move(client), std::move(callback)); } @@ -1935,7 +1935,7 @@ if (frame_sink_id_.is_valid()) window_->SetEmbedFrameSinkId(frame_sink_id_); - if (!features::IsMusEnabled()) + if (!features::IsMashEnabled()) return; // Embed the renderer into the Window. @@ -2500,10 +2500,17 @@ } void RenderWidgetHostViewAura::DidNavigate() { - SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(), - base::nullopt); + // The first navigation does not need a new LocalSurfaceID. The renderer can + // use the ID that was already provided. + if (is_first_navigation_) { + SyncSurfaceProperties(cc::DeadlinePolicy::UseExistingDeadline()); + } else { + SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(), + base::nullopt); + } if (delegated_frame_host_) delegated_frame_host_->DidNavigate(); + is_first_navigation_ = false; } // static
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index ae64f09f..4193729a 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -682,6 +682,8 @@ ui::EventPointerType last_pointer_type_before_focus_ = ui::EventPointerType::POINTER_TYPE_UNKNOWN; + bool is_first_navigation_ = true; + base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
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 bcf071ec..67f8a47b 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
@@ -6088,16 +6088,31 @@ if (base::FeatureList::IsEnabled(features::kMash)) return; + constexpr base::TimeDelta kTimeout = base::TimeDelta::FromMicroseconds(10); + view_->InitAsChild(nullptr); aura::client::ParentWindowWithContext( view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(), gfx::Rect()); - viz::LocalSurfaceId id1 = view_->GetLocalSurfaceId(); - EXPECT_TRUE(id1.is_valid()); + widget_host_->set_new_content_rendering_delay_for_testing(kTimeout); - widget_host_->set_new_content_rendering_delay_for_testing( - base::TimeDelta::FromMicroseconds(10)); + viz::LocalSurfaceId id0 = view_->GetLocalSurfaceId(); + EXPECT_TRUE(id0.is_valid()); + + // No new LocalSurfaceId should be allocated for the first navigation but the + // timer should fire. + widget_host_->DidNavigate(1); + viz::LocalSurfaceId id1 = view_->GetLocalSurfaceId(); + EXPECT_EQ(id0, id1); + { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), 2 * kTimeout); + run_loop.Run(); + } + EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired()); + widget_host_->reset_new_content_rendering_timeout_fired(); // Start the timer. Verify that a new LocalSurfaceId is allocated. widget_host_->DidNavigate(5); @@ -6113,8 +6128,7 @@ { base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), - base::TimeDelta::FromMicroseconds(20)); + FROM_HERE, run_loop.QuitClosure(), 2 * kTimeout); run_loop.Run(); } EXPECT_TRUE(widget_host_->new_content_rendering_timeout_fired()); @@ -6131,8 +6145,7 @@ { base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), - base::TimeDelta::FromMicroseconds(20)); + FROM_HERE, run_loop.QuitClosure(), 2 * kTimeout); run_loop.Run(); } EXPECT_FALSE(widget_host_->new_content_rendering_timeout_fired());
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 457ad28..4563b7f 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -171,7 +171,7 @@ } #if defined(USE_AURA) - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { frame_connector_->EmbedRendererWindowTreeClientInParent( GetWindowTreeClientFromRenderer()); }
diff --git a/content/browser/service_manager/common_browser_interfaces.cc b/content/browser/service_manager/common_browser_interfaces.cc index 55e5293..af1a24e 100644 --- a/content/browser/service_manager/common_browser_interfaces.cc +++ b/content/browser/service_manager/common_browser_interfaces.cc
@@ -44,7 +44,7 @@ #elif defined(OS_MACOSX) registry_.AddInterface(base::BindRepeating(&FontLoaderDispatcher::Create)); #endif - if (!features::IsMusEnabled()) { + if (!features::IsMashEnabled()) { // For mus, the mojom::discardable_memory::DiscardableSharedMemoryManager // is exposed from ui::Service. So we don't need bind the interface here. auto* browser_main_loop = BrowserMainLoop::GetInstance();
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc index 47d8042f8..ea66245 100644 --- a/content/browser/service_manager/service_manager_context.cc +++ b/content/browser/service_manager/service_manager_context.cc
@@ -91,14 +91,6 @@ #include "ui/aura/env.h" #endif -#if BUILDFLAG(ENABLE_MUS) -#include "components/discardable_memory/service/discardable_shared_memory_manager.h" -#include "content/public/browser/discardable_shared_memory_manager.h" -#include "services/ui/common/image_cursors_set.h" -#include "services/ui/public/interfaces/constants.mojom.h" -#include "services/ui/service.h" -#endif - namespace content { namespace { @@ -282,44 +274,6 @@ #endif } -#if BUILDFLAG(ENABLE_MUS) -std::unique_ptr<service_manager::Service> CreateEmbeddedUIService( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr, - discardable_memory::DiscardableSharedMemoryManager* memory_manager) { - ui::Service::InitParams params; - params.running_standalone = false; - params.resource_runner = task_runner; - params.image_cursors_set_weak_ptr = image_cursors_set_weak_ptr; - params.memory_manager = memory_manager; - params.should_host_viz = base::FeatureList::IsEnabled(features::kMash); - return std::make_unique<ui::Service>(params); -} - -void RegisterUIServiceInProcessIfNecessary( - ServiceManagerConnection* connection) { - // Some tests don't create BrowserMainLoop. - if (!BrowserMainLoop::GetInstance()) - return; - // Do not embed the UI service when running in mash. - if (base::FeatureList::IsEnabled(features::kMash)) - return; - // Do not embed the UI service if not running with mus. - if (!features::IsMusEnabled()) - return; - - service_manager::EmbeddedServiceInfo info; - info.factory = base::Bind( - &CreateEmbeddedUIService, base::ThreadTaskRunnerHandle::Get(), - BrowserMainLoop::GetInstance()->image_cursors_set()->GetWeakPtr(), - GetDiscardableSharedMemoryManager()); - info.use_own_thread = true; - info.message_loop_type = base::MessageLoop::TYPE_UI; - info.thread_priority = base::ThreadPriority::DISPLAY; - connection->AddEmbeddedService(ui::mojom::kServiceName, info); -} -#endif - std::unique_ptr<service_manager::Service> CreateNetworkService() { // The test interface doesn't need to be implemented in the in-process case. auto registry = std::make_unique<service_manager::BinderRegistry>(); @@ -548,10 +502,6 @@ entry.second); } -#if BUILDFLAG(ENABLE_MUS) - RegisterUIServiceInProcessIfNecessary(packaged_services_connection_.get()); -#endif - // This is safe to assign directly from any thread, because // ServiceManagerContext must be constructed before anyone can call // GetConnectorForIOThread().
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 5468b8e..65b35e07 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -17,6 +17,7 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" +#include "base/syslog_logging.h" #include "content/browser/background_fetch/background_fetch_context.h" #include "content/browser/blob_storage/blob_registry_wrapper.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" @@ -831,6 +832,7 @@ int process_id = bindings_.dispatch_context(); if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin( process_id, origin.GetURL())) { + SYSLOG(WARNING) << "Killing renderer: illegal localStorage request."; bindings_.ReportBadMessage("Access denied for localStorage request"); return; }
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc index 85aff036..30d546d 100644 --- a/content/browser/web_contents/web_contents_android.cc +++ b/content/browser/web_contents/web_contents_android.cc
@@ -22,6 +22,7 @@ #include "content/browser/accessibility/browser_accessibility_android.h" #include "content/browser/accessibility/browser_accessibility_manager_android.h" #include "content/browser/android/content_view_core.h" +#include "content/browser/android/interstitial_page_delegate_android.h" #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h" #include "content/browser/frame_host/interstitial_page_impl.h" #include "content/browser/media/android/browser_media_player_manager.h" @@ -41,8 +42,9 @@ #include "content/public/common/content_switches.h" #include "jni/WebContentsImpl_jni.h" #include "net/android/network_library.h" +#include "ui/accessibility/ax_assistant_structure.h" #include "ui/accessibility/ax_node_data.h" -#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h" +#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" #include "ui/android/overscroll_refresh_handler.h" #include "ui/android/window_android.h" #include "ui/gfx/android/java_bitmap.h" @@ -90,7 +92,8 @@ ScopedJavaLocalRef<jobject> JNI_WebContentsImpl_CreateJavaAXSnapshot( JNIEnv* env, - const ui::AXSnapshotNodeAndroid* node, + const ui::AssistantTree* tree, + const ui::AssistantNode* node, bool is_root) { ScopedJavaLocalRef<jstring> j_text = ConvertUTF16ToJavaString(env, node->text); @@ -103,15 +106,16 @@ node->text_size, node->bold, node->italic, node->underline, node->line_through, j_class); - if (node->has_selection) { + if (node->selection.has_value()) { Java_WebContentsImpl_setAccessibilitySnapshotSelection( - env, j_node, node->start_selection, node->end_selection); + env, j_node, node->selection->start(), node->selection->end()); } - for (auto& child : node->children) { + for (int child : node->children_indices) { Java_WebContentsImpl_addAccessibilityNodeAsChild( env, j_node, - JNI_WebContentsImpl_CreateJavaAXSnapshot(env, child.get(), false)); + JNI_WebContentsImpl_CreateJavaAXSnapshot( + env, tree, tree->nodes[child].get(), false)); } return j_node; } @@ -127,10 +131,10 @@ std::unique_ptr<BrowserAccessibilityManagerAndroid> manager( static_cast<BrowserAccessibilityManagerAndroid*>( BrowserAccessibilityManager::Create(result, nullptr))); - auto snapshot = ui::AXSnapshotNodeAndroid::Create( - result, manager->ShouldExposePasswordText()); - ScopedJavaLocalRef<jobject> j_root = - JNI_WebContentsImpl_CreateJavaAXSnapshot(env, snapshot.get(), true); + std::unique_ptr<ui::AssistantTree> assistant_tree = + ui::CreateAssistantTree(result, manager->ShouldExposePasswordText()); + ScopedJavaLocalRef<jobject> j_root = JNI_WebContentsImpl_CreateJavaAXSnapshot( + env, assistant_tree.get(), assistant_tree->nodes.front().get(), true); Java_WebContentsImpl_onAccessibilitySnapshot(env, j_root, callback); } @@ -420,6 +424,19 @@ web_contents_->SetAudioMuted(mute); } +void WebContentsAndroid::ShowInterstitialPage(JNIEnv* env, + const JavaParamRef<jobject>& obj, + const JavaParamRef<jstring>& jurl, + jlong delegate_ptr) { + GURL url(base::android::ConvertJavaStringToUTF8(env, jurl)); + InterstitialPageDelegateAndroid* delegate = + reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr); + InterstitialPage* interstitial = InterstitialPage::Create( + web_contents_, false, url, delegate); + delegate->set_interstitial_page(interstitial); + interstitial->Show(); +} + jboolean WebContentsAndroid::IsShowingInterstitialPage( JNIEnv* env, const JavaParamRef<jobject>& obj) {
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h index 04455bd0..52b0769 100644 --- a/content/browser/web_contents/web_contents_android.h +++ b/content/browser/web_contents/web_contents_android.h
@@ -100,6 +100,10 @@ const base::android::JavaParamRef<jobject>& jobj, jboolean mute); + void ShowInterstitialPage(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jstring>& jurl, + jlong delegate_ptr); jboolean IsShowingInterstitialPage( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 189b3f0..6a9a264 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -60,6 +60,7 @@ #include "content/browser/loader/loader_io_thread_notifier.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/manifest/manifest_manager_host.h" +#include "content/browser/media/audio_stream_broker.h" #include "content/browser/media/audio_stream_monitor.h" #include "content/browser/media/capture/web_contents_audio_muter.h" #include "content/browser/media/media_web_contents_observer.h" @@ -6158,6 +6159,19 @@ view_size_before_emulation_ = gfx::Size(); } +ForwardingAudioStreamFactory* WebContentsImpl::GetAudioStreamFactory() { + if (!audio_stream_factory_) { + audio_stream_factory_.emplace( + this, + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->Clone(), + AudioStreamBrokerFactory::CreateImpl()); + } + + return &*audio_stream_factory_; +} + void WebContentsImpl::MediaStartedPlaying( const WebContentsObserver::MediaPlayerInfo& media_info, const WebContentsObserver::MediaPlayerId& id) {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index a5cfbff9..730b9d3 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -19,6 +19,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/observer_list.h" +#include "base/optional.h" #include "base/process/process.h" #include "base/time/time.h" #include "base/values.h" @@ -33,6 +34,7 @@ #include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/frame_host/render_frame_host_manager.h" #include "content/browser/media/audio_stream_monitor.h" +#include "content/browser/media/forwarding_audio_stream_factory.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" @@ -871,6 +873,8 @@ return &audio_stream_monitor_; } + ForwardingAudioStreamFactory* GetAudioStreamFactory(); + // Called by MediaWebContentsObserver when playback starts or stops. See the // WebContentsObserver function stubs for more details. void MediaStartedPlaying( @@ -1649,6 +1653,9 @@ // Monitors power levels for audio streams associated with this WebContents. AudioStreamMonitor audio_stream_monitor_; + // Coordinates all the audio streams for this WebContents. Lazily initialized. + base::Optional<ForwardingAudioStreamFactory> audio_stream_factory_; + // Created on-demand to mute all audio output from this WebContents. std::unique_ptr<WebContentsAudioMuter> audio_muter_;
diff --git a/content/browser/web_package/signed_exchange_header_parser.cc b/content/browser/web_package/signed_exchange_header_parser.cc index cac1f6d..5a9c66a 100644 --- a/content/browser/web_package/signed_exchange_header_parser.cc +++ b/content/browser/web_package/signed_exchange_header_parser.cc
@@ -238,7 +238,7 @@ "'certUrl' parameter is not a valid URL."); return base::nullopt; } - const std::string cert_sha256_string = value.params["certSha256"]; + const std::string cert_sha256_string = value.params[kCertSha256Key]; if (cert_sha256_string.size() != crypto::kSHA256Length) { // TODO(https://crbug.com/819467) : When we will support "ed25519Key", the // params may not have "certSha256". @@ -252,7 +252,7 @@ sig.cert_sha256 = std::move(cert_sha256); // TODO(https://crbug.com/819467): Support ed25519key. // sig.ed25519_key = value.params["ed25519Key"]; - sig.validity_url = GURL(value.params["validityUrl"]); + sig.validity_url = GURL(value.params[kValidityUrlKey]); if (!sig.validity_url.is_valid()) { signed_exchange_utils::ReportErrorAndEndTraceEvent( devtools_proxy, "SignedExchangeHeaderParser::ParseSignature", @@ -265,13 +265,13 @@ "'validityUrl' parameter can't have a fragment."); return base::nullopt; } - if (!base::StringToUint64(value.params["date"], &sig.date)) { + if (!base::StringToUint64(value.params[kDateKey], &sig.date)) { signed_exchange_utils::ReportErrorAndEndTraceEvent( devtools_proxy, "SignedExchangeHeaderParser::ParseSignature", "'date' parameter is not a number."); return base::nullopt; } - if (!base::StringToUint64(value.params["expires"], &sig.expires)) { + if (!base::StringToUint64(value.params[kExpiresKey], &sig.expires)) { signed_exchange_utils::ReportErrorAndEndTraceEvent( devtools_proxy, "SignedExchangeHeaderParser::ParseSignature", "'expires' parameter is not a number.");
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc index ab6ccbba4..5dad37a 100644 --- a/content/browser/webui/web_ui_data_source_impl.cc +++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -43,6 +43,15 @@ std::move(update)); } +namespace { + +std::string CleanUpPath(const std::string& path) { + // Remove the query string for named resource lookups. + return path.substr(0, path.find_first_of('?')); +} + +} // namespace + // Internal class to hide the fact that WebUIDataSourceImpl implements // URLDataSource. class WebUIDataSourceImpl::InternalDataSource : public URLDataSource { @@ -88,8 +97,7 @@ return parent_->deny_xframe_options_; } bool IsGzipped(const std::string& path) const override { - return parent_->use_gzip_ && - parent_->excluded_paths_.find(path) == parent_->excluded_paths_.end(); + return parent_->IsGzipped(path); } private: @@ -275,8 +283,7 @@ int resource_id = default_resource_; std::map<std::string, int>::iterator result; // Remove the query string for named resource lookups. - std::string file_path = path.substr(0, path.find_first_of('?')); - result = path_to_idr_map_.find(file_path); + result = path_to_idr_map_.find(CleanUpPath(path)); if (result != path_to_idr_map_.end()) resource_id = result->second; DCHECK_NE(resource_id, -1); @@ -292,4 +299,8 @@ callback.Run(base::RefCountedString::TakeString(&template_data)); } +bool WebUIDataSourceImpl::IsGzipped(const std::string& path) const { + return use_gzip_ && excluded_paths_.count(CleanUpPath(path)) == 0; +} + } // namespace content
diff --git a/content/browser/webui/web_ui_data_source_impl.h b/content/browser/webui/web_ui_data_source_impl.h index 18c4875..06c1bd9 100644 --- a/content/browser/webui/web_ui_data_source_impl.h +++ b/content/browser/webui/web_ui_data_source_impl.h
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/values.h" #include "content/browser/webui/url_data_manager.h" @@ -69,6 +70,8 @@ friend class WebUIDataSource; friend class WebUIDataSourceTest; + FRIEND_TEST_ALL_PREFIXES(WebUIDataSourceTest, IsGzipped); + explicit WebUIDataSourceImpl(const std::string& source_name); // Methods that match URLDataSource which are called by @@ -85,6 +88,8 @@ add_load_time_data_defaults_ = false; } + bool IsGzipped(const std::string& path) const; + // The name of this source. // E.g., for favicons, this could be "favicon", which results in paths for // specific resources like "favicon/34" getting sent to this source.
diff --git a/content/browser/webui/web_ui_data_source_unittest.cc b/content/browser/webui/web_ui_data_source_unittest.cc index f2974ff..6125eb9 100644 --- a/content/browser/webui/web_ui_data_source_unittest.cc +++ b/content/browser/webui/web_ui_data_source_unittest.cc
@@ -212,4 +212,24 @@ EXPECT_EQ(GetMimeType("foo.js?abc?abc"), js); } +TEST_F(WebUIDataSourceTest, IsGzipped) { + EXPECT_FALSE(source()->IsGzipped("foobar")); + + source()->AddResourcePath("foobar", kDummyResourceId); + source()->SetDefaultResource(kDummyDefaultResourceId); + source()->SetJsonPath("strings.js"); + source()->UseGzip({"json/special/path"}); + + EXPECT_TRUE(source()->IsGzipped("foobar")); + EXPECT_TRUE(source()->IsGzipped("foobar?query")); + + EXPECT_TRUE(source()->IsGzipped("unknown_path")); + EXPECT_TRUE(source()->IsGzipped("unknown_path?query")); + + EXPECT_FALSE(source()->IsGzipped("json/special/path")); + EXPECT_FALSE(source()->IsGzipped("json/special/path?query")); + EXPECT_FALSE(source()->IsGzipped("strings.js")); + EXPECT_FALSE(source()->IsGzipped("strings.js?query")); +} + } // namespace content
diff --git a/content/common/OWNERS b/content/common/OWNERS index 5baee777..c3390635 100644 --- a/content/common/OWNERS +++ b/content/common/OWNERS
@@ -7,10 +7,14 @@ per-file sandbox_init_win.cc=file://sandbox/win/OWNERS # Mac Sandbox. -per-file sandbox_init_mac.*=rsesek@chromium.org -per-file sandbox_mac*=rsesek@chromium.org +per-file sandbox_init_mac.cc=set noparent +per-file sandbox_init_mac.cc=file://sandbox/mac/OWNERS + +per-file sandbox_mac*=set noparent +per-file sandbox_mac*=file://sandbox/mac/OWNERS + per-file *.sb=set noparent -per-file *.sb=rsesek@chromium.org +per-file *.sb=file://sandbox/mac/OWNERS per-file pepper*=bauerb@chromium.org per-file plugin*=bauerb@chromium.org
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index f61f24dd..1b5b3ad3 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -1095,11 +1095,6 @@ base::string16 /* search_text */, blink::WebFindOptions) -// This message notifies the frame that it is no longer the active frame in the -// current find session, and so it should clear its active find match (and no -// longer highlight it with special coloring). -IPC_MESSAGE_ROUTED0(FrameMsg_ClearActiveFindMatch) - // This message notifies the frame that the user has closed the find-in-page // window (and what action to take regarding the selection). IPC_MESSAGE_ROUTED1(FrameMsg_StopFinding, content::StopFindAction /* action */)
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index 2ee1e8c..bb0abafb 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -115,7 +115,7 @@ // allocator. if (!command_line.HasSwitch(switches::kSingleProcess)) { discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr);
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index f21c02e..43f1a6e 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -129,6 +129,7 @@ "java/src/org/chromium/content/browser/GestureListenerManagerImpl.java", "java/src/org/chromium/content/browser/GpuProcessCallback.java", "java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java", + "java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java", "java/src/org/chromium/content/browser/JavascriptInjectorImpl.java", "java/src/org/chromium/content/browser/JavascriptInterface.java", "java/src/org/chromium/content/browser/JoystickHandler.java", @@ -364,6 +365,7 @@ "java/src/org/chromium/content/browser/GestureListenerManagerImpl.java", "java/src/org/chromium/content/browser/GpuProcessCallback.java", "java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java", + "java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java", "java/src/org/chromium/content/browser/JavascriptInjectorImpl.java", "java/src/org/chromium/content/browser/LauncherThread.java", "java/src/org/chromium/content/browser/MediaSessionImpl.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java index 246cbf6..ae520378ef 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
@@ -172,8 +172,7 @@ } private void hidePopupsAndClearSelection() { - getSelectionPopupController().destroyActionModeAndUnselect(); - mWebContents.dismissTextHandles(); + getSelectionPopupController().clearSelection(); PopupController.hideAll(mWebContents); } @@ -266,10 +265,6 @@ hidePopupsAndPreserveSelection(); } else { hidePopupsAndClearSelection(); - // Clear the selection. The selection is cleared on destroying IME - // and also here since we may receive destroy first, for example - // when focus is lost in webview. - controller.clearSelection(); } } if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, mHasInputFocus);
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java b/content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java similarity index 71% rename from content/public/test/android/javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java rename to content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java index b952f78..9af0cd5 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java +++ b/content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.content.browser.test; +package org.chromium.content.browser; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; -import org.chromium.content_public.browser.WebContents; /** * Allows the specification and handling of Interstitial pages in java. */ @JNINamespace("content") public class InterstitialPageDelegateAndroid { + private long mNativePtr; /** @@ -27,16 +27,26 @@ } /** + * @return The pointer to the underlying native counterpart. + */ + @VisibleForTesting + public long getNative() { + return mNativePtr; + } + + /** * Called when "proceed" is triggered on the interstitial. */ @CalledByNative - protected void onProceed() {} + protected void onProceed() { + } /** * Called when "dont' proceed" is triggered on the interstitial. */ @CalledByNative - protected void onDontProceed() {} + protected void onDontProceed() { + } /** * Called when a command has been received from the interstitial. @@ -44,7 +54,8 @@ * @param command The command that was received. */ @CalledByNative - protected void commandReceived(String command) {} + protected void commandReceived(String command) { + } @CalledByNative private void onNativeDestroyed() { @@ -65,19 +76,7 @@ if (mNativePtr != 0) nativeDontProceed(mNativePtr); } - /** - * Shows an interstitial page driven by this delegate. - * - * @param url The URL being blocked by the interstitial. - * @param webContents The {@link WebContents} the interstitial to show on. - */ - public void showInterstitialPage(String url, WebContents webContents) { - if (mNativePtr != 0) nativeShowInterstitialPage(mNativePtr, url, webContents); - } - private native long nativeInit(String htmlContent); private native void nativeProceed(long nativeInterstitialPageDelegateAndroid); private native void nativeDontProceed(long nativeInterstitialPageDelegateAndroid); - private native void nativeShowInterstitialPage( - long nativeInterstitialPageDelegateAndroid, String url, WebContents webContents); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/PopupController.java b/content/public/android/java/src/org/chromium/content/browser/PopupController.java index caaad3bb..27ca475 100644 --- a/content/public/android/java/src/org/chromium/content/browser/PopupController.java +++ b/content/public/android/java/src/org/chromium/content/browser/PopupController.java
@@ -5,7 +5,6 @@ package org.chromium.content.browser; import org.chromium.content.browser.selection.SelectionPopupControllerImpl; -import org.chromium.content.browser.webcontents.WebContentsImpl; import org.chromium.content.browser.webcontents.WebContentsUserData; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents.UserDataFactory; @@ -57,7 +56,6 @@ SelectionPopupControllerImpl controller = SelectionPopupControllerImpl.fromWebContents(webContents); if (controller != null) controller.destroyActionModeAndUnselect(); - ((WebContentsImpl) webContents).dismissTextHandles(); PopupController.hideAll(webContents); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java index 2fa7ac0..d566d42 100644 --- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -921,7 +921,6 @@ public void onDestroyActionMode() { mActionMode = null; if (mUnselectAllOnDismiss) { - mWebContents.dismissTextHandles(); clearSelection(); } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index 1cc500f..edd12fd 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -429,6 +429,12 @@ } @Override + public void showInterstitialPage( + String url, long interstitialPageDelegateAndroid) { + nativeShowInterstitialPage(mNativeWebContentsAndroid, url, interstitialPageDelegateAndroid); + } + + @Override public boolean isShowingInterstitialPage() { return nativeIsShowingInterstitialPage(mNativeWebContentsAndroid); } @@ -870,6 +876,8 @@ private native void nativeSuspendAllMediaPlayers(long nativeWebContentsAndroid); private native void nativeSetAudioMuted(long nativeWebContentsAndroid, boolean mute); private native int nativeGetBackgroundColor(long nativeWebContentsAndroid); + private native void nativeShowInterstitialPage(long nativeWebContentsAndroid, + String url, long nativeInterstitialPageDelegateAndroid); private native boolean nativeIsShowingInterstitialPage(long nativeWebContentsAndroid); private native boolean nativeFocusLocationBarByDefault(long nativeWebContentsAndroid); private native boolean nativeIsRenderWidgetHostViewReady(long nativeWebContentsAndroid);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java index 45dcf837..094a9b9 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -211,6 +211,16 @@ int getBackgroundColor(); /** + * Shows an interstitial page driven by the passed in delegate. + * + * @param url The URL being blocked by the interstitial. + * @param interstitialPageDelegateAndroid The delegate handling the interstitial. + */ + @VisibleForTesting + void showInterstitialPage( + String url, long interstitialPageDelegateAndroid); + + /** * @return Whether the page is currently showing an interstitial, such as a bad HTTPS page. */ boolean isShowingInterstitialPage();
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java b/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java index 60d06dc..e0800ff 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java
@@ -17,7 +17,6 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.base.test.util.UrlUtils; -import org.chromium.content.browser.test.InterstitialPageDelegateAndroid; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.TouchCommon; @@ -118,7 +117,8 @@ new Callable<TestWebContentsObserver>() { @Override public TestWebContentsObserver call() throws Exception { - delegate.showInterstitialPage(URL, mActivityTestRule.getWebContents()); + mActivityTestRule.getWebContents().showInterstitialPage( + URL, delegate.getNative()); return new TestWebContentsObserver(mActivityTestRule.getWebContents()); } });
diff --git a/content/public/browser/android/compositor_client.h b/content/public/browser/android/compositor_client.h index bb03a251..38257521 100644 --- a/content/public/browser/android/compositor_client.h +++ b/content/public/browser/android/compositor_client.h
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "content/common/content_export.h" +#include "ui/gfx/geometry/size.h" namespace content { @@ -21,7 +22,7 @@ virtual void DidSwapFrame(int pending_frames) {} // This is called on all swap buffers, regardless of cause. - virtual void DidSwapBuffers() {} + virtual void DidSwapBuffers(const gfx::Size& swap_size) {} protected: CompositorClient() {}
diff --git a/content/public/browser/desktop_capture.cc b/content/public/browser/desktop_capture.cc index 016a774..2d41880 100644 --- a/content/public/browser/desktop_capture.cc +++ b/content/public/browser/desktop_capture.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "build/build_config.h" +#include "content/public/common/content_features.h" namespace content { namespace desktop_capture { @@ -24,7 +25,11 @@ } else { options.set_allow_use_magnification_api(true); } -#endif // defined(OS_WIN) +#elif defined(OS_MACOSX) + if (base::FeatureList::IsEnabled(features::kIOSurfaceCapturer)) { + options.set_allow_iosurface(true); + } +#endif return options; }
diff --git a/content/public/browser/overlay_window.h b/content/public/browser/overlay_window.h index 96c468a..553fc06 100644 --- a/content/public/browser/overlay_window.h +++ b/content/public/browser/overlay_window.h
@@ -48,6 +48,7 @@ // Retrieve the ui::Layers corresponding to the video and controls. virtual ui::Layer* GetVideoLayer() = 0; + virtual ui::Layer* GetControlsBackgroundLayer() = 0; virtual ui::Layer* GetCloseControlsLayer() = 0; virtual ui::Layer* GetPlayPauseControlsLayer() = 0;
diff --git a/content/public/browser/overscroll_configuration.h b/content/public/browser/overscroll_configuration.h index 1cfca76..9df88576 100644 --- a/content/public/browser/overscroll_configuration.h +++ b/content/public/browser/overscroll_configuration.h
@@ -6,6 +6,7 @@ #define CONTENT_PUBLIC_BROWSER_OVERSCROLL_CONFIGURATION_H_ #include "base/macros.h" +#include "base/time/time.h" #include "content/common/content_export.h" namespace content { @@ -62,6 +63,8 @@ static bool TouchpadOverscrollHistoryNavigationEnabled(); + static base::TimeDelta MaxInertialEventsBeforeOverscrollCancellation(); + private: friend class ScopedHistoryNavigationMode; friend class ScopedPullToRefreshMode;
diff --git a/content/public/browser/render_frame_metadata_provider.h b/content/public/browser/render_frame_metadata_provider.h index 25b86d3..6ee7068f 100644 --- a/content/public/browser/render_frame_metadata_provider.h +++ b/content/public/browser/render_frame_metadata_provider.h
@@ -33,10 +33,9 @@ virtual void OnRenderFrameSubmission() = 0; // Called to indicate that the viz::LocalSurfaceId within the - // RenderFrameMetadata has changed. For production builds, this means that - // the child_sequence_number of the viz::LocalSurfaceId has changed. For - // unit tests, this means that any part of the viz::LocalSurfaceId has - // changed. + // RenderFrameMetadata has changed. Note that this is called as + // soon as |metadata| arrives and does not wait for the frame token + // to pass in Viz. virtual void OnLocalSurfaceIdChanged( const cc::RenderFrameMetadata& metadata) = 0; };
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index f3300dd..5c9bb09 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -239,7 +239,7 @@ // Off-main-thread WebSocket. See https://crbug.com/825740 const base::Feature kOffMainThreadWebSocket{"OffMainThreadWebSocket", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Origin Manifest. See crbug.com/751996 const base::Feature kOriginManifest{"OriginManifest", @@ -619,6 +619,10 @@ const base::Feature kDeviceMonitorMac{"DeviceMonitorMac", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enable IOSurface based screen capturer. +const base::Feature kIOSurfaceCapturer{"IOSurfaceCapturer", + base::FEATURE_DISABLED_BY_DEFAULT}; + // The V2 sandbox on MacOS removes the unsandboed warmup phase and sandboxes the // entire life of the process. const base::Feature kMacV2Sandbox{"MacV2Sandbox",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 293dad7e..c328fb68 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -148,6 +148,7 @@ #if defined(OS_MACOSX) CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac; +CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer; CONTENT_EXPORT extern const base::Feature kMacV2Sandbox; #endif // defined(OS_MACOSX)
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn index 08de4404..beebfd7 100644 --- a/content/public/test/android/BUILD.gn +++ b/content/public/test/android/BUILD.gn
@@ -33,7 +33,6 @@ "javatests/src/org/chromium/content/browser/test/ChildProcessAllocatorSettings.java", "javatests/src/org/chromium/content/browser/test/ChildProcessAllocatorSettingsHook.java", "javatests/src/org/chromium/content/browser/test/ContentJUnit4ClassRunner.java", - "javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java", "javatests/src/org/chromium/content/browser/test/NativeLibraryTestRule.java", "javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java", "javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java", @@ -57,26 +56,3 @@ "javatests/src/org/chromium/content/browser/test/util/UiUtils.java", ] } - -generate_jni("content_test_jni") { - testonly = true - jni_package = "content/public/test" - sources = [ - "javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java", - ] -} - -static_library("content_native_test_support") { - testonly = true - sources = [ - "interstitial_page_delegate_android.cc", - "interstitial_page_delegate_android.h", - ] - deps = [ - ":content_test_jni", - "//base", - "//content/public/browser", - "//device/gamepad", - "//media/midi", - ] -}
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java index e12e265..afbd264 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java +++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java
@@ -127,6 +127,9 @@ } @Override + public void showInterstitialPage(String url, long interstitialPageDelegateAndroid) {} + + @Override public boolean isShowingInterstitialPage() { return false; }
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index 03bd1e4db..8bb6e40 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -334,7 +334,7 @@ // When no accessibility events are in-flight post a task to send // the events to the browser. We use PostTask so that we can queue // up additional events. - render_frame_->GetTaskRunner(blink::TaskType::kInternalAccessibility) + render_frame_->GetTaskRunner(blink::TaskType::kInternalDefault) ->PostTask(FROM_HERE, base::BindOnce( &RenderAccessibilityImpl::SendPendingAccessibilityEvents,
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index e2cf1e3..b0b24bc 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -315,7 +315,7 @@ sent_visual_properties_ = pending_visual_properties_; #if defined(USE_AURA) - if (features::IsMusEnabled() && mus_embedded_frame_) { + if (features::IsMashEnabled() && mus_embedded_frame_) { mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(), FrameRectInPixels()); }
diff --git a/content/renderer/media/media_interface_factory.cc b/content/renderer/media/media_interface_factory.cc index 77c7287..f457c38 100644 --- a/content/renderer/media/media_interface_factory.cc +++ b/content/renderer/media/media_interface_factory.cc
@@ -82,6 +82,20 @@ GetMediaInterfaceFactory()->CreateCdm(key_system, std::move(request)); } +void MediaInterfaceFactory::CreateDecryptor( + int cdm_id, + media::mojom::DecryptorRequest request) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&MediaInterfaceFactory::CreateDecryptor, + weak_this_, cdm_id, std::move(request))); + return; + } + + DVLOG(1) << __func__; + GetMediaInterfaceFactory()->CreateDecryptor(cdm_id, std::move(request)); +} + void MediaInterfaceFactory::CreateCdmProxy( const std::string& cdm_guid, media::mojom::CdmProxyRequest request) {
diff --git a/content/renderer/media/media_interface_factory.h b/content/renderer/media/media_interface_factory.h index ee4a33d..54f8ab77 100644 --- a/content/renderer/media/media_interface_factory.h +++ b/content/renderer/media/media_interface_factory.h
@@ -37,6 +37,8 @@ media::mojom::RendererRequest request) final; void CreateCdm(const std::string& key_system, media::mojom::ContentDecryptionModuleRequest request) final; + void CreateDecryptor(int cdm_id, + media::mojom::DecryptorRequest request) final; // TODO(xhwang): We should not expose this here. void CreateCdmProxy(const std::string& cdm_guid, media::mojom::CdmProxyRequest request) final;
diff --git a/content/renderer/media/webrtc/rtc_video_decoder.cc b/content/renderer/media/webrtc/rtc_video_decoder.cc index e82cf263..238e3a9d 100644 --- a/content/renderer/media/webrtc/rtc_video_decoder.cc +++ b/content/renderer/media/webrtc/rtc_video_decoder.cc
@@ -159,7 +159,6 @@ int32_t RTCVideoDecoder::Decode( const webrtc::EncodedImage& inputImage, bool missingFrames, - const webrtc::RTPFragmentationHeader* /*fragmentation*/, const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/, int64_t /*renderTimeMs*/) { DVLOG(3) << "Decode"; @@ -470,8 +469,8 @@ frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY, picture.allow_overlay()); #if defined(OS_ANDROID) - frame->metadata()->SetBoolean(media::VideoFrameMetadata::SURFACE_TEXTURE, - picture.surface_texture()); + frame->metadata()->SetBoolean(media::VideoFrameMetadata::TEXTURE_OWNER, + picture.texture_owner()); frame->metadata()->SetBoolean( media::VideoFrameMetadata::WANTS_PROMOTION_HINT, picture.wants_promotion_hint());
diff --git a/content/renderer/media/webrtc/rtc_video_decoder.h b/content/renderer/media/webrtc/rtc_video_decoder.h index 8a29b580..4db50b3 100644 --- a/content/renderer/media/webrtc/rtc_video_decoder.h +++ b/content/renderer/media/webrtc/rtc_video_decoder.h
@@ -70,9 +70,8 @@ // Called on WebRTC DecodingThread. int32_t Decode(const webrtc::EncodedImage& inputImage, bool missingFrames, - const webrtc::RTPFragmentationHeader* fragmentation, - const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL, - int64_t renderTimeMs = -1) override; + const webrtc::CodecSpecificInfo* codecSpecificInfo, + int64_t renderTimeMs) override; // Called on WebRTC DecodingThread. int32_t RegisterDecodeCompleteCallback( webrtc::DecodedImageCallback* callback) override;
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc b/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc index cd52471..050c9f6 100644 --- a/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc +++ b/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc
@@ -208,7 +208,7 @@ CreateDecoder(webrtc::kVideoCodecVP8); webrtc::EncodedImage input_image; EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); } TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) { @@ -217,7 +217,7 @@ webrtc::EncodedImage input_image; input_image._completeFrame = false; EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); } TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { @@ -228,7 +228,7 @@ bool missingFrames = true; EXPECT_EQ( WEBRTC_VIDEO_CODEC_ERROR, - rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, missingFrames, nullptr, 0)); } TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { @@ -336,7 +336,7 @@ input_image._frameType = webrtc::kVideoFrameDelta; input_image._length = kMinResolutionWidth * kMaxResolutionHeight; EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); RunUntilIdle(); // Notify the decoder about a platform error. @@ -347,13 +347,13 @@ // Expect decode call to reset decoder, and set up a new VDA to track it. SetUpResetVDA(); EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting()); // Decoder expects a frame with size after reset, so drops any other frames. // However, we should still increment the error counter. EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); EXPECT_EQ(2, rtc_decoder_->GetVDAErrorCounterForTesting()); } @@ -379,7 +379,7 @@ uint32_t i = 0; while (i++ < kMaxNumDecodeRequests) { const int32_t result = - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0); + rtc_decoder_->Decode(input_image, false, nullptr, 0); RunUntilIdle(); if (result == WEBRTC_VIDEO_CODEC_OK) EXPECT_EQ(0, rtc_decoder_->GetVDAErrorCounterForTesting()); @@ -411,7 +411,7 @@ input_image._length = sizeof(buffer); EXPECT_CALL(*mock_vda_, Decode(_)).Times(1); EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); RunUntilIdle(); // InitDecode and Decode after Release should succeed. @@ -419,7 +419,7 @@ rtc_decoder_->Release(); Initialize(); EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, - rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0)); + rtc_decoder_->Decode(input_image, false, nullptr, 0)); } INSTANTIATE_TEST_CASE_P(CodecProfiles,
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc index 9143e53..78e689e 100644 --- a/content/renderer/mus/renderer_window_tree_client.cc +++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -32,7 +32,7 @@ // static void RendererWindowTreeClient::CreateIfNecessary(int routing_id) { - if (!features::IsMusEnabled() || Get(routing_id)) + if (!features::IsMashEnabled() || Get(routing_id)) return; RendererWindowTreeClient* connection = new RendererWindowTreeClient(routing_id);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index beff6e0..cba2c9cc 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1751,7 +1751,6 @@ OnGetSerializedHtmlWithLocalLinks) IPC_MESSAGE_HANDLER(FrameMsg_SerializeAsMHTML, OnSerializeAsMHTML) IPC_MESSAGE_HANDLER(FrameMsg_Find, OnFind) - IPC_MESSAGE_HANDLER(FrameMsg_ClearActiveFindMatch, OnClearActiveFindMatch) IPC_MESSAGE_HANDLER(FrameMsg_StopFinding, OnStopFinding) IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode) IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs, @@ -6167,11 +6166,6 @@ frame_->RequestFind(request_id, WebString::FromUTF16(search_text), options); } -void RenderFrameImpl::OnClearActiveFindMatch() { - frame_->ExecuteCommand(WebString::FromUTF8("CollapseSelection")); - frame_->ClearActiveFindMatch(); -} - #define STATIC_ASSERT_ENUM(a, b) \ static_assert(static_cast<int>(a) == static_cast<int>(b), \ "mismatching enums: " #a)
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 6d3deeb..51a5f1b 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1044,7 +1044,6 @@ void OnFind(int request_id, const base::string16& search_text, const blink::WebFindOptions& options); - void OnClearActiveFindMatch(); void OnStopFinding(StopFindAction action); void OnEnableViewSourceMode(); void OnSuppressFurtherDialogs();
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index a355de34..5dbe0ff 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -243,7 +243,7 @@ render_widget_->GetOriginalScreenInfo(); #if defined(USE_AURA) - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { RendererWindowTreeClient* renderer_window_tree_client = RendererWindowTreeClient::Get(render_widget_->routing_id()); // It's possible a MusEmbeddedFrame has already been scheduled for creation
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 0bbf5675..03b9de4 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -861,7 +861,7 @@ AddFilter(midi_message_filter_.get()); #if defined(USE_AURA) - if (features::IsMusEnabled()) + if (features::IsMashEnabled()) CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection()); #endif @@ -1035,7 +1035,7 @@ categorized_worker_pool_->Start(num_raster_threads); discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (features::IsMusEnabled()) { + if (features::IsMashEnabled()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 424f38f..2533785 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -2304,6 +2304,12 @@ } void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) { + // If the main frame is remote, return immediately. Page level focus + // should be set from the browser process, so if needed by tests it should + // be properly supported. + if (webview()->MainFrame()->IsWebRemoteFrame()) + return; + if (enable) { if (has_focus()) return;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 9d8f93a..f7e9b62 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -425,7 +425,7 @@ } #if defined(USE_AURA) RendererWindowTreeClient::CreateIfNecessary(routing_id_); - if (features::IsMusEnabled()) + if (features::IsMashEnabled()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_); #endif } @@ -2040,7 +2040,7 @@ is_hidden_ = hidden; #if defined(USE_AURA) - if (features::IsMusEnabled()) + if (features::IsMashEnabled()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden); #endif
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index a0560dd..89dd771 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn
@@ -52,20 +52,6 @@ ] } -shared_library("libcontent_native_test") { - testonly = true - deps = [ - ":content_test_jni_registration", - "//base", - "//content/public/test/android:content_native_test_support", - "//content/shell:content_shell_lib", - ] - - sources = [ - "shell_test_library_loader.cc", - ] -} - android_resources("content_shell_java_resources") { testonly = true resource_dirs = [ "java/res" ] @@ -211,13 +197,6 @@ ] } -generate_jni_registration("content_test_jni_registration") { - testonly = true - target = ":content_shell_test_apk__apk" - output = "$root_gen_dir/content/shell/android/${target_name}.h" - exception_files = jni_exception_files -} - instrumentation_test_apk("content_shell_test_apk") { deps = [ "//base:base_java_test_support", @@ -228,7 +207,6 @@ ] apk_under_test = ":content_shell_apk" apk_name = "ContentShellTest" - shared_libraries = [ ":libcontent_native_test" ] android_manifest = "javatests/AndroidManifest.xml" }
diff --git a/content/shell/android/shell_test_library_loader.cc b/content/shell/android/shell_test_library_loader.cc deleted file mode 100644 index 7b47e54c..0000000 --- a/content/shell/android/shell_test_library_loader.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_android.h" -#include "base/android/jni_utils.h" -#include "content/public/app/content_jni_onload.h" -#include "content/public/app/content_main.h" -#include "content/public/browser/android/compositor.h" -#include "content/shell/android/content_test_jni_registration.h" -#include "content/shell/app/shell_main_delegate.h" - -// This is called by the VM when the shared library is first loaded. -JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - base::android::InitVM(vm); - JNIEnv* env = base::android::AttachCurrentThread(); - if (!base::android::IsSelectiveJniRegistrationEnabled(env)) { - if (!RegisterNonMainDexNatives(env)) { - return -1; - } - } - - if (!RegisterMainDexNatives(env)) { - return -1; - } - if (!content::android::OnJNIOnLoadInit()) - return -1; - content::Compositor::Initialize(); - content::SetContentMainDelegate(new content::ShellMainDelegate()); - return JNI_VERSION_1_4; -}
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc index 5c284110..ec6bb262 100644 --- a/content/shell/browser/shell_url_request_context_getter.cc +++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -49,25 +49,6 @@ namespace content { -namespace { - -// TODO(rsleevi): Embedders should see https://crbug.com/700973 before using -// this pattern. -class IgnoresCTPolicyEnforcer : public net::CTPolicyEnforcer { - public: - IgnoresCTPolicyEnforcer() = default; - ~IgnoresCTPolicyEnforcer() override = default; - - net::ct::CTPolicyCompliance CheckCompliance( - net::X509Certificate* cert, - const net::SCTList& verified_scts, - const net::NetLogWithSource& net_log) override { - return net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } -}; - -} // namespace - ShellURLRequestContextGetter::ShellURLRequestContextGetter( bool ignore_certificate_errors, bool off_the_record, @@ -151,7 +132,6 @@ builder.SetCertVerifier(GetCertVerifier()); builder.set_ct_verifier(std::make_unique<net::DoNothingCTVerifier>()); - builder.set_ct_policy_enforcer(std::make_unique<IgnoresCTPolicyEnforcer>()); std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service = GetProxyService();
diff --git a/content/test/data/site_isolation/js-html-polyglot2.html b/content/test/data/site_isolation/js-html-polyglot2.html new file mode 100644 index 0000000..14227587 --- /dev/null +++ b/content/test/data/site_isolation/js-html-polyglot2.html
@@ -0,0 +1,10 @@ +<!-- comment --> <script type='text/javascript'> +//<![CDATA[ + +// This is a regression test for https://crbug.com/839945 +// which found out that some script resources are served +// with text/html content-type and with a body that is +// both a valid html and a valid javascript. +var blah = 123; + +//]]>--></script>
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index e95e3ac0..f4e82ad 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -44,8 +44,6 @@ # TODO(vmiura) check / generate reference images for Android devices self.Fail('Pixel_SolidColorBackground', ['mac', 'android'], bug=624256) - self.Fail('Pixel_OffscreenCanvasUnaccelerated2DGPUCompositingWorker', - ['mac', ('nvidia', 0xfe9)], bug=706016) self.Fail('Pixel_CSSFilterEffects', ['mac', ('nvidia', 0xfe9)], bug=690277) @@ -97,9 +95,9 @@ ['linux', 'mac', 'win'], bug=744658) # TODO(rjkroege): temporarily suppress this test. - self.Flaky('Pixel_OffscreenCanvas2DResizeOnWorker', - ['mac', 'nvidia'], bug=840394) + self.Flaky('Pixel_OffscreenCanvas2DResizeOnWorker', ['mac'], bug=840394) # TODO(kbr): temporary suppression for new test. self.Flaky('Pixel_WebGLSadCanvas', ['mac'], bug=575305) + self.Flaky('Pixel_WebGLSadCanvas', ['win', 'intel'], bug=575305) self.Fail('Pixel_WebGLSadCanvas', ['android', 'nvidia'], bug=575305)
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index ba19401..56b36d7 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -240,6 +240,8 @@ sources += [ "bluetooth_adapter_winrt.cc", "bluetooth_adapter_winrt.h", + "bluetooth_device_winrt.cc", + "bluetooth_device_winrt.h", ] libs = [
diff --git a/device/bluetooth/bluetooth_device_winrt.cc b/device/bluetooth/bluetooth_device_winrt.cc new file mode 100644 index 0000000..932f48c --- /dev/null +++ b/device/bluetooth/bluetooth_device_winrt.cc
@@ -0,0 +1,168 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/bluetooth_device_winrt.h" + +#include "base/logging.h" +#include "device/bluetooth/bluetooth_adapter_winrt.h" + +namespace device { + +BluetoothDeviceWinrt::BluetoothDeviceWinrt(BluetoothAdapterWinrt* adapter) + : BluetoothDevice(adapter) {} + +BluetoothDeviceWinrt::~BluetoothDeviceWinrt() = default; + +uint32_t BluetoothDeviceWinrt::GetBluetoothClass() const { + NOTIMPLEMENTED(); + return 0; +} + +std::string BluetoothDeviceWinrt::GetAddress() const { + NOTIMPLEMENTED(); + return std::string(); +} + +BluetoothDevice::VendorIDSource BluetoothDeviceWinrt::GetVendorIDSource() + const { + NOTIMPLEMENTED(); + return VendorIDSource(); +} + +uint16_t BluetoothDeviceWinrt::GetVendorID() const { + NOTIMPLEMENTED(); + return 0; +} + +uint16_t BluetoothDeviceWinrt::GetProductID() const { + NOTIMPLEMENTED(); + return 0; +} + +uint16_t BluetoothDeviceWinrt::GetDeviceID() const { + NOTIMPLEMENTED(); + return 0; +} + +uint16_t BluetoothDeviceWinrt::GetAppearance() const { + NOTIMPLEMENTED(); + return 0; +} + +base::Optional<std::string> BluetoothDeviceWinrt::GetName() const { + NOTIMPLEMENTED(); + return base::nullopt; +} + +bool BluetoothDeviceWinrt::IsPaired() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::IsConnected() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::IsGattConnected() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::IsConnectable() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::IsConnecting() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::ExpectingPinCode() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::ExpectingPasskey() const { + NOTIMPLEMENTED(); + return false; +} + +bool BluetoothDeviceWinrt::ExpectingConfirmation() const { + NOTIMPLEMENTED(); + return false; +} + +void BluetoothDeviceWinrt::GetConnectionInfo( + const ConnectionInfoCallback& callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::SetConnectionLatency( + ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::Connect(PairingDelegate* pairing_delegate, + const base::Closure& callback, + const ConnectErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::SetPinCode(const std::string& pincode) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::SetPasskey(uint32_t passkey) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::ConfirmPairing() { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::RejectPairing() { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::CancelPairing() { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::Disconnect(const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::Forget(const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::ConnectToService( + const BluetoothUUID& uuid, + const ConnectToServiceCallback& callback, + const ConnectToServiceErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::ConnectToServiceInsecurely( + const device::BluetoothUUID& uuid, + const ConnectToServiceCallback& callback, + const ConnectToServiceErrorCallback& error_callback) { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::CreateGattConnectionImpl() { + NOTIMPLEMENTED(); +} + +void BluetoothDeviceWinrt::DisconnectGatt() { + NOTIMPLEMENTED(); +} + +} // namespace device
diff --git a/device/bluetooth/bluetooth_device_winrt.h b/device/bluetooth/bluetooth_device_winrt.h new file mode 100644 index 0000000..df656cbd --- /dev/null +++ b/device/bluetooth/bluetooth_device_winrt.h
@@ -0,0 +1,77 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_WINRT_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_WINRT_H_ + +#include <string> + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "base/optional.h" +#include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_export.h" + +namespace device { + +class BluetoothAdapterWinrt; + +class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWinrt : public BluetoothDevice { + public: + explicit BluetoothDeviceWinrt(BluetoothAdapterWinrt* adapter); + ~BluetoothDeviceWinrt() override; + + // BluetoothDevice: + uint32_t GetBluetoothClass() const override; + std::string GetAddress() const override; + VendorIDSource GetVendorIDSource() const override; + uint16_t GetVendorID() const override; + uint16_t GetProductID() const override; + uint16_t GetDeviceID() const override; + uint16_t GetAppearance() const override; + base::Optional<std::string> GetName() const override; + bool IsPaired() const override; + bool IsConnected() const override; + bool IsGattConnected() const override; + bool IsConnectable() const override; + bool IsConnecting() const override; + bool ExpectingPinCode() const override; + bool ExpectingPasskey() const override; + bool ExpectingConfirmation() const override; + void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void SetConnectionLatency(ConnectionLatency connection_latency, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void Connect(PairingDelegate* pairing_delegate, + const base::Closure& callback, + const ConnectErrorCallback& error_callback) override; + void SetPinCode(const std::string& pincode) override; + void SetPasskey(uint32_t passkey) override; + void ConfirmPairing() override; + void RejectPairing() override; + void CancelPairing() override; + void Disconnect(const base::Closure& callback, + const ErrorCallback& error_callback) override; + void Forget(const base::Closure& callback, + const ErrorCallback& error_callback) override; + void ConnectToService( + const BluetoothUUID& uuid, + const ConnectToServiceCallback& callback, + const ConnectToServiceErrorCallback& error_callback) override; + void ConnectToServiceInsecurely( + const device::BluetoothUUID& uuid, + const ConnectToServiceCallback& callback, + const ConnectToServiceErrorCallback& error_callback) override; + + protected: + // BluetoothDevice: + void CreateGattConnectionImpl() override; + void DisconnectGatt() override; + + DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceWinrt); +}; + +} // namespace device + +#endif // DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_WINRT_H_
diff --git a/device/usb/usb_device_impl.cc b/device/usb/usb_device_impl.cc index 73f31da..056c6c3 100644 --- a/device/usb/usb_device_impl.cc +++ b/device/usb/usb_device_impl.cc
@@ -41,8 +41,8 @@ base::string16(), base::string16(), base::string16()), - platform_device_(std::move(platform_device)), - context_(std::move(context)) { + context_(std::move(context)), + platform_device_(std::move(platform_device)) { CHECK(platform_device_.is_valid()) << "platform_device must be valid"; ReadAllConfigurations(); RefreshActiveConfiguration();
diff --git a/device/usb/usb_device_impl.h b/device/usb/usb_device_impl.h index d4dce81..16ab891 100644 --- a/device/usb/usb_device_impl.h +++ b/device/usb/usb_device_impl.h
@@ -84,11 +84,11 @@ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); base::ThreadChecker thread_checker_; - const ScopedLibusbDeviceRef platform_device_; bool visited_ = false; - // Retain the context so that it will not be released before UsbDevice. + // The libusb_context must not be released before the libusb_device. const scoped_refptr<UsbContext> context_; + const ScopedLibusbDeviceRef platform_device_; DISALLOW_COPY_AND_ASSIGN(UsbDeviceImpl); };
diff --git a/device/usb/usb_service_impl.h b/device/usb/usb_service_impl.h index eaf669d..e7e89d0 100644 --- a/device/usb/usb_service_impl.h +++ b/device/usb/usb_service_impl.h
@@ -87,6 +87,7 @@ void EnumerationFailed(ScopedLibusbDeviceRef platform_device, const base::Closure& refresh_complete); + // The libusb_context must outlive any references to libusb_device objects. scoped_refptr<UsbContext> context_; bool usb_unavailable_ = false;
diff --git a/docs/qtcreator.md b/docs/qtcreator.md index e9da7d56..9bd13d7 100644 --- a/docs/qtcreator.md +++ b/docs/qtcreator.md
@@ -3,8 +3,8 @@ [Qt Creator](https://www.qt.io/ide/) ([Wiki](https://en.wikipedia.org/wiki/Qt_Creator)) is a cross-platform C++ IDE. -You can use Qt Creator as a daily IDE or just as a GDB frontend (which does -not require project configuration). +You can use Qt Creator as a daily IDE on Linux or Mac, or just as a GDB/LLDB +frontend (which does not require project configuration). [TOC] @@ -13,10 +13,10 @@ ### Workflow features * Built-in code completion. -* Navigate to classes, files, or symbols with `ctrl+k`. +* Navigate to classes, files, or symbols with `ctrl+k` or `cmd+k` (macOS). * Switch between declaration and definition with `F2`. -* Build with `ctrl+shift+b`. -* Build and run with `ctrl+r`, or debug with `F5`. +* Build with `ctrl+shift+b` or `shift+cmd+b` (macOS). +* Build and run with `ctrl+r` or `cmd+r` (macOS), or debug with `F5`. * Switch between the header file and cpp file with `F4`. ### Setup @@ -26,17 +26,20 @@ 3. Start it with `qtcreator out/Default/qtcreator_project/all.creator`. 4. Help - Plugins - check ClangCodeModel to enable std completion. -It takes 3 minutes to parse all of chrome's C++ files on my workstation!!! And +It takes 3 minutes to parse all of chromium's C++ files on my workstation!!! And it does not block while parsing. #### Code Style -1. Help - About Plugins, enable Beautifier. -2. Tools - Options - Beautifier - Clang Format, - change the Clang format command to: `$depot_tools_dir/clang-format`, and +1. Help - About Plugins (or app menu on macOS), enable Beautifier. +2. Tools - Options (Preferences on macOS) - Beautifier + Make sure to tick - Enable auto format on file save" + Select ClangFormat as the tool + Go to Clang Format tab + Change the Clang format command to: `$chromium_checkout_dir/src/buildtools/$os/clang-format`, and set `Use predefined style: file`. You can also set a keyboard shortcut for it. -3. Tools - Options - Code Style, import this xml file. +3. Tools - Options - C++ - Code Style, import this xml file. ``` <?xml version="1.0" encoding="UTF-8"?> @@ -100,18 +103,24 @@ ## Debugger **You can skip the project settings and use QtCreator as a single file -standalone GDB frontend.** +standalone GDB or LLDB (macOS) frontend.** +For macOS : +1. Open the file you want to debug. +2. Debug - Start Debugging - Attach to running Application, you may need to + open chromium's task manager to find the process id. + +For Linux : 1. Tools - Options - Build & Run - Debuggers, make sure GDB is set. 2. Tools - Options - Kits, change the Desktop kit to GDB (LLDB doesn't work on Linux). 3. Open the file you want to debug. 4. Debug - Start Debugging - Attach to running Application, you may need to - open chrome's task manager to find the process id. + open chromium's task manager to find the process id. ### Tips, tricks, and troubleshooting -#### The debugger exits immediately +#### [Linux] The debugger exits immediately Ensure yama allows you to attach to another process: @@ -120,11 +129,15 @@ ``` -#### The debugger does not stop on breakpoints +#### [Linux] The debugger does not stop on breakpoints Ensure you are using GDB on Linux, not LLDB. #### More +Linux : See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_debugging.md + +macOS : +https://dev.chromium.org/developers/how-tos/debugging-on-os-x
diff --git a/docs/testing/layout_tests_tips.md b/docs/testing/layout_tests_tips.md index 5911cc3..fcda5dd8 100644 --- a/docs/testing/layout_tests_tips.md +++ b/docs/testing/layout_tests_tips.md
@@ -107,7 +107,7 @@ Tests should provide as much relevant information as possible when failing. `testharness.js` tests should prefer -[rich assert_ functions](https://github.com/w3c/testharness.js/blob/master/docs/api.md#list-of-assertions) +[rich assert_ functions](https://github.com/w3c/web-platform-tests/blob/master/docs/_writing-tests/testharness-api.md#list-of-assertions) to combining `assert_true()` with a boolean operator. Using appropriate `assert_` functions results in better diagnostic output when the assertion fails.
diff --git a/docs/testing/using_breakpad_with_content_shell.md b/docs/testing/using_breakpad_with_content_shell.md index c90e26f..534e928 100644 --- a/docs/testing/using_breakpad_with_content_shell.md +++ b/docs/testing/using_breakpad_with_content_shell.md
@@ -1,7 +1,7 @@ # Using breakpad with content shell When running layout tests, it is possible to use -[breakpad](../../breakpad/) to capture stack traces on crashes while +[breakpad](../../third_party/breakpad/) to capture stack traces on crashes while running without a debugger attached and with the sandbox enabled. ## Setup
diff --git a/docs/testing/writing_layout_tests.md b/docs/testing/writing_layout_tests.md index 80b2a53..126707d 100644 --- a/docs/testing/writing_layout_tests.md +++ b/docs/testing/writing_layout_tests.md
@@ -224,9 +224,9 @@ For example, the most popular Blink-specific API is `testRunner`, which is implemented in -[components/test_runner/test_runner.h](../../components/test_runner/test_runner.h) +[content/shell/test_runner/test_runner.h](../../content/shell/test_runner/test_runner.h) and -[components/test_runner/test_runner.cc](../../components/test_runner/test_runner.cc). +[content/shell/test_runner/test_runner.cc](../../content/shell/test_runner/test_runner.cc). By skimming the `TestRunnerBindings::Install` method, we learn that the testRunner API is presented by the `window.testRunner` and `window.layoutTestsController` objects, which are synonyms. Reading the @@ -248,12 +248,12 @@ and uses the `testRunner` API. *** -See the [components/test_runner/](../../components/test_runner/) directory and +See the [content/shell/test_runner/](../../content/shell/test_runner/) directory and [WebKit's LayoutTests guide](https://trac.webkit.org/wiki/Writing%20Layout%20Tests%20for%20DumpRenderTree) for other useful APIs. For example, `window.eventSender` -([components/test_runner/event_sender.h](../../components/test_runner/event_sender.h) +([content/shell/test_runner/event_sender.h](../../content/shell/test_runner/event_sender.h) and -[components/test_runner/event_sender.cc](../../components/test_runner/event_sender.cc)) +[content/shell/test_runner/event_sender.cc](../../content/shell/test_runner/event_sender.cc)) has methods that simulate events input such as keyboard / mouse input and drag-and-drop.
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index d4bb2a78..1cf7c31 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1310,6 +1310,8 @@ WALLPAPERPRIVATE_GETCURRENTWALLPAPERTHUMBNAIL, ACCESSIBILITY_PRIVATE_ONSELECTTOSPEAKSTATECHANGED, INPUTMETHODPRIVATE_GETCOMPOSITIONBOUNDS, + FILEMANAGERPRIVATE_ISCROSTINIENABLED, + FILEMANAGERPRIVATE_MOUNTCROSTINICONTAINER, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/updater/update_service_unittest.cc b/extensions/browser/updater/update_service_unittest.cc index 195d672..40ad83f6 100644 --- a/extensions/browser/updater/update_service_unittest.cc +++ b/extensions/browser/updater/update_service_unittest.cc
@@ -395,17 +395,11 @@ // Build 3 extensions. scoped_refptr<Extension> extension1 = - ExtensionBuilder("1") - .MergeManifest(DictionaryBuilder().Set("version", "1.2").Build()) - .Build(); + ExtensionBuilder("1").SetManifestKey("version", "1.2").Build(); scoped_refptr<Extension> extension2 = - ExtensionBuilder("2") - .MergeManifest(DictionaryBuilder().Set("version", "2.3").Build()) - .Build(); + ExtensionBuilder("2").SetManifestKey("version", "2.3").Build(); scoped_refptr<Extension> extension3 = - ExtensionBuilder("3") - .MergeManifest(DictionaryBuilder().Set("version", "3.4").Build()) - .Build(); + ExtensionBuilder("3").SetManifestKey("version", "3.4").Build(); EXPECT_TRUE(extension1->id() != extension2->id() && extension1->id() != extension3->id() && extension2->id() != extension3->id());
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json index dc2681ed..57920b6 100644 --- a/extensions/common/api/_manifest_features.json +++ b/extensions/common/api/_manifest_features.json
@@ -75,7 +75,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // http://crbug.com/407693 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // http://crbug.com/407693 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // http://crbug.com/407693 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // http://crbug.com/407693 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // http://crbug.com/407693 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }], "content_capabilities": [{
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json index 72ff9bac..8d81da3 100644 --- a/extensions/common/api/_permission_features.json +++ b/extensions/common/api/_permission_features.json
@@ -146,7 +146,8 @@ "2F6F6FDB84E0290ABAB7A9D7571EB344821E5F12", // http://crbug.com/610452 "5B9E39EA374B136CBE7AED2D872003107642EAD5", // http://crbug.com/610452 "E0E94FB0C01FFB9CDC7A5F098C99B5A8D2F95902", // http://crbug.com/610452 - "52E0557059A7A28F74ED1D92DDD997E0CCD37806" // http://crbug.com/610452 + "52E0557059A7A28F74ED1D92DDD997E0CCD37806", // http://crbug.com/610452 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "cast": { @@ -169,7 +170,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // http://crbug.com/824667#c15 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // http://crbug.com/824667#c15 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // http://crbug.com/824667#c15 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // http://crbug.com/824667#c15 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // http://crbug.com/824667#c15 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "clipboard": { @@ -257,7 +259,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // http://crbug.com/407693 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // http://crbug.com/407693 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // http://crbug.com/407693 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // http://crbug.com/407693 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // http://crbug.com/407693 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "fileSystem": [{ @@ -355,7 +358,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // http://crbug.com/720495 "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // http://crbug.com/720495 "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // http://crbug.com/720495 - "81986D4F846CEDDDB962643FA501D1780DD441BB" // http://crbug.com/720495 + "81986D4F846CEDDDB962643FA501D1780DD441BB", // http://crbug.com/720495 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, { @@ -461,7 +465,8 @@ "52E0557059A7A28F74ED1D92DDD997E0CCD37806", // http://crbug.com/610452 "61FF4757F9420B62B19BA5C96084649339DB31F5", // http://crbug.com/731941 "6FB7E1B6C0247B687AC14772E87A117F5F5E4497", // http://crbug.com/731941 - "9834387FDA1F66A1B5CA06CB442137B556F12F2A" // http://crbug.com/772346 + "9834387FDA1F66A1B5CA06CB442137B556F12F2A", // http://crbug.com/772346 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }], "networkingPrivate": { @@ -494,7 +499,8 @@ "2F6F6FDB84E0290ABAB7A9D7571EB344821E5F12", // http://crbug.com/610452 "5B9E39EA374B136CBE7AED2D872003107642EAD5", // http://crbug.com/610452 "E0E94FB0C01FFB9CDC7A5F098C99B5A8D2F95902", // http://crbug.com/610452 - "52E0557059A7A28F74ED1D92DDD997E0CCD37806" // http://crbug.com/610452 + "52E0557059A7A28F74ED1D92DDD997E0CCD37806", // http://crbug.com/610452 + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "power": { @@ -682,7 +688,8 @@ "4F25792AF1AA7483936DE29C07806F203C7170A0", // Stable internal hotrod app "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9", // Beta internal hotrod app "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB", // Alpha internal hotrod app - "81986D4F846CEDDDB962643FA501D1780DD441BB" // Dev internal hotrod app + "81986D4F846CEDDDB962643FA501D1780DD441BB", // Dev internal hotrod app + "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, "vpnProvider": {
diff --git a/extensions/common/extension_builder.cc b/extensions/common/extension_builder.cc index 7e88591..170c4f5 100644 --- a/extensions/common/extension_builder.cc +++ b/extensions/common/extension_builder.cc
@@ -19,7 +19,7 @@ std::vector<std::string> permissions; base::Optional<ActionType> action; base::Optional<BackgroundPage> background_page; - std::unique_ptr<base::DictionaryValue> extra; + base::Optional<base::Value> extra; std::unique_ptr<base::DictionaryValue> GetValue() const { DictionaryBuilder manifest; @@ -78,11 +78,20 @@ } std::unique_ptr<base::DictionaryValue> result = manifest.Build(); - if (extra) - result->MergeDictionary(extra.get()); + if (extra) { + const base::DictionaryValue* extra_dict = nullptr; + extra->GetAsDictionary(&extra_dict); + result->MergeDictionary(extra_dict); + } return result; } + + base::Value* get_extra() { + if (!extra) + extra.emplace(base::Value::Type::DICTIONARY); + return &extra.value(); + } }; ExtensionBuilder::ExtensionBuilder() @@ -167,9 +176,9 @@ ExtensionBuilder& ExtensionBuilder::MergeManifest( std::unique_ptr<base::DictionaryValue> manifest) { if (manifest_data_) { - if (!manifest_data_->extra) - manifest_data_->extra = std::make_unique<base::DictionaryValue>(); - manifest_data_->extra->MergeDictionary(manifest.get()); + base::DictionaryValue* extra_dict = nullptr; + manifest_data_->get_extra()->GetAsDictionary(&extra_dict); + extra_dict->MergeDictionary(manifest.get()); } else { manifest_value_->MergeDictionary(manifest.get()); } @@ -186,4 +195,17 @@ return *this; } +void ExtensionBuilder::SetManifestKeyImpl(base::StringPiece key, + base::Value value) { + CHECK(manifest_data_); + manifest_data_->get_extra()->SetKey(key, std::move(value)); +} + +void ExtensionBuilder::SetManifestPathImpl( + std::initializer_list<base::StringPiece> path, + base::Value value) { + CHECK(manifest_data_); + manifest_data_->get_extra()->SetPath(path, std::move(value)); +} + } // namespace extensions
diff --git a/extensions/common/extension_builder.h b/extensions/common/extension_builder.h index d7c8bd1..df8b887 100644 --- a/extensions/common/extension_builder.h +++ b/extensions/common/extension_builder.h
@@ -5,12 +5,14 @@ #ifndef EXTENSIONS_COMMON_EXTENSION_BUILDER_H_ #define EXTENSIONS_COMMON_EXTENSION_BUILDER_H_ +#include <initializer_list> #include <memory> #include <string> #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/strings/string_piece.h" #include "extensions/common/manifest.h" #include "extensions/common/value_builder.h" @@ -87,6 +89,39 @@ // page will be set. ExtensionBuilder& SetBackgroundPage(BackgroundPage background_page); + // Shortcuts to setting values on the manifest dictionary without needing to + // go all the way through MergeManifest(). Sample usage: + // ExtensionBuilder("name").SetManifestKey("version", "0.2").Build(); + // Can be used in conjuction with ListBuilder and DictionaryBuilder for more + // complex types. + template <typename T> + ExtensionBuilder& SetManifestKey(base::StringPiece key, T value) { + SetManifestKeyImpl(key, base::Value(value)); + return *this; + } + template <typename T> + ExtensionBuilder& SetManifestPath( + std::initializer_list<base::StringPiece> path, + T value) { + SetManifestPathImpl(path, base::Value(value)); + return *this; + } + // Specializations for unique_ptr<> to allow passing unique_ptr<base::Value>. + // All other types will fail to compile. + template <typename T> + ExtensionBuilder& SetManifestKey(base::StringPiece key, + std::unique_ptr<T> value) { + SetManifestKeyImpl(key, std::move(*value)); + return *this; + } + template <typename T> + ExtensionBuilder& SetManifestPath( + std::initializer_list<base::StringPiece> path, + std::unique_ptr<T> value) { + SetManifestPathImpl(path, std::move(*value)); + return *this; + } + ////////////////////////////////////////////////////////////////////////////// // Utility methods for use with custom manifest construction. @@ -120,6 +155,10 @@ private: struct ManifestData; + void SetManifestKeyImpl(base::StringPiece key, base::Value value); + void SetManifestPathImpl(std::initializer_list<base::StringPiece> path, + base::Value value); + // Information for constructing the manifest; either metadata about the // manifest which will be used to construct it, or the dictionary itself. Only // one will be present.
diff --git a/extensions/common/extension_builder_unittest.cc b/extensions/common/extension_builder_unittest.cc index 0010b304..79efe1385 100644 --- a/extensions/common/extension_builder_unittest.cc +++ b/extensions/common/extension_builder_unittest.cc
@@ -167,4 +167,12 @@ } } +TEST(ExtensionBuilderTest, SetManifestKey) { + scoped_refptr<const Extension> extension = + ExtensionBuilder("foo") + .SetManifestKey("short_name", "short name") + .Build(); + EXPECT_EQ("short name", extension->short_name()); +} + } // namespace extensions
diff --git a/extensions/renderer/runtime_hooks_delegate_unittest.cc b/extensions/renderer/runtime_hooks_delegate_unittest.cc index 80013e5b..6a6843a 100644 --- a/extensions/renderer/runtime_hooks_delegate_unittest.cc +++ b/extensions/renderer/runtime_hooks_delegate_unittest.cc
@@ -104,15 +104,10 @@ v8::Local<v8::Context> context = MainContext(); { - DictionaryBuilder connectable; - connectable.Set("matches", - ListBuilder().Append("*://example.com/*").Build()); scoped_refptr<Extension> connectable_extension = ExtensionBuilder("connectable") - .MergeManifest( - DictionaryBuilder() - .Set("externally_connectable", connectable.Build()) - .Build()) + .SetManifestPath({"externally_connectable", "matches"}, + ListBuilder().Append("*://example.com/*").Build()) .Build(); RegisterExtension(connectable_extension); }
diff --git a/extensions/shell/browser/api/identity/identity_api_unittest.cc b/extensions/shell/browser/api/identity/identity_api_unittest.cc index 67567dc..f33295773 100644 --- a/extensions/shell/browser/api/identity/identity_api_unittest.cc +++ b/extensions/shell/browser/api/identity/identity_api_unittest.cc
@@ -68,11 +68,9 @@ .Append("https://www.googleapis.com/auth/drive") .Build()); // Create an extension with OAuth2 scopes. - set_extension( - ExtensionBuilder("Test") - .MergeManifest( - DictionaryBuilder().Set("oauth2", oauth2.Build()).Build()) - .Build()); + set_extension(ExtensionBuilder("Test") + .SetManifestKey("oauth2", oauth2.Build()) + .Build()); } };
diff --git a/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc b/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc index 991b78f..a0f169a 100644 --- a/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc +++ b/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc
@@ -34,7 +34,7 @@ const std::string& version, const std::string& id) { return ExtensionBuilder(name) - .MergeManifest(DictionaryBuilder().Set("version", version).Build()) + .SetManifestKey("version", version) .SetID(id) .Build(); }
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc index 35348f6..7d1e6ad 100644 --- a/google_apis/gcm/tools/mcs_probe.cc +++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -383,7 +383,7 @@ transport_security_state_ = std::make_unique<net::TransportSecurityState>(); cert_transparency_verifier_ = std::make_unique<net::MultiLogCTVerifier>(); - ct_policy_enforcer_ = std::make_unique<net::CTPolicyEnforcer>(); + ct_policy_enforcer_ = std::make_unique<net::DefaultCTPolicyEnforcer>(); http_auth_handler_factory_ = net::HttpAuthHandlerRegistryFactory::Create( &http_auth_preferences_, host_resolver_.get()); http_server_properties_ = std::make_unique<net::HttpServerPropertiesImpl>();
diff --git a/gpu/command_buffer/build_raster_cmd_buffer.py b/gpu/command_buffer/build_raster_cmd_buffer.py index 8ca97a0..2a688a3 100755 --- a/gpu/command_buffer/build_raster_cmd_buffer.py +++ b/gpu/command_buffer/build_raster_cmd_buffer.py
@@ -462,38 +462,24 @@ os.chdir(base_dir) - # TODO(backer): Uncomment once the output looks good. gen.WriteCommandIds("gpu/command_buffer/common/raster_cmd_ids_autogen.h") gen.WriteFormat("gpu/command_buffer/common/raster_cmd_format_autogen.h") gen.WriteFormatTest( "gpu/command_buffer/common/raster_cmd_format_test_autogen.h") gen.WriteGLES2InterfaceHeader( "gpu/command_buffer/client/raster_interface_autogen.h") - # gen.WriteGLES2InterfaceStub( - # "gpu/command_buffer/client/raster_interface_stub_autogen.h") - # gen.WriteGLES2InterfaceStubImpl( - # "gpu/command_buffer/client/raster_interface_stub_impl_autogen.h") gen.WriteGLES2ImplementationHeader( "gpu/command_buffer/client/raster_implementation_autogen.h") gen.WriteGLES2Implementation( "gpu/command_buffer/client/raster_implementation_impl_autogen.h") gen.WriteGLES2ImplementationUnitTests( "gpu/command_buffer/client/raster_implementation_unittest_autogen.h") - # gen.WriteGLES2TraceImplementationHeader( - # "gpu/command_buffer/client/raster_trace_implementation_autogen.h") - # gen.WriteGLES2TraceImplementation( - # "gpu/command_buffer/client/raster_trace_implementation_impl_autogen.h") - # gen.WriteGLES2CLibImplementation( - # "gpu/command_buffer/client/raster_c_lib_autogen.h") gen.WriteCmdHelperHeader( "gpu/command_buffer/client/raster_cmd_helper_autogen.h") gen.WriteServiceImplementation( "gpu/command_buffer/service/raster_decoder_autogen.h") gen.WriteServiceUnitTests( "gpu/command_buffer/service/raster_decoder_unittest_%d_autogen.h") - # gen.WriteServiceUnitTestsForExtensions( - # "gpu/command_buffer/service/" - # "raster_cmd_decoder_unittest_extensions_autogen.h") gen.WriteServiceUtilsHeader( "gpu/command_buffer/service/raster_cmd_validation_autogen.h") gen.WriteServiceUtilsImplementation(
diff --git a/gpu/command_buffer/client/raster_cmd_helper_autogen.h b/gpu/command_buffer/client/raster_cmd_helper_autogen.h index 10d9ad3..c252dac6 100644 --- a/gpu/command_buffer/client/raster_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/raster_cmd_helper_autogen.h
@@ -134,32 +134,6 @@ } } -void InitializeDiscardableTextureCHROMIUM(GLuint texture_id, - uint32_t shm_id, - uint32_t shm_offset) { - raster::cmds::InitializeDiscardableTextureCHROMIUM* c = - GetCmdSpace<raster::cmds::InitializeDiscardableTextureCHROMIUM>(); - if (c) { - c->Init(texture_id, shm_id, shm_offset); - } -} - -void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) { - raster::cmds::UnlockDiscardableTextureCHROMIUM* c = - GetCmdSpace<raster::cmds::UnlockDiscardableTextureCHROMIUM>(); - if (c) { - c->Init(texture_id); - } -} - -void LockDiscardableTextureCHROMIUM(GLuint texture_id) { - raster::cmds::LockDiscardableTextureCHROMIUM* c = - GetCmdSpace<raster::cmds::LockDiscardableTextureCHROMIUM>(); - if (c) { - c->Init(texture_id); - } -} - void BeginRasterCHROMIUM(GLuint texture_id, GLuint sk_color, GLuint msaa_sample_count,
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc index d1b6081..aa59eec 100644 --- a/gpu/command_buffer/client/raster_implementation.cc +++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -377,18 +377,19 @@ bool RasterImplementation::ThreadSafeShallowLockDiscardableTexture( uint32_t texture_id) { - return discardable_texture_manager_.TextureIsValid(texture_id) && - discardable_texture_manager_.LockTexture(texture_id); + NOTREACHED(); + return false; } void RasterImplementation::CompleteLockDiscardableTexureOnContextThread( uint32_t texture_id) { - helper_->LockDiscardableTextureCHROMIUM(texture_id); + NOTREACHED(); } bool RasterImplementation::ThreadsafeDiscardableTextureIsDeletedForTracing( uint32_t texture_id) { - return discardable_texture_manager_.TextureIsDeletedForTracing(texture_id); + NOTREACHED(); + return false; } const std::string& RasterImplementation::GetLogPrefix() const { @@ -671,7 +672,6 @@ helper_->DeleteTexturesImmediate(n, textures); for (GLsizei ii = 0; ii < n; ++ii) { texture_id_allocator_.FreeID(textures[ii]); - discardable_texture_manager_.FreeTexture(textures[ii]); } UnbindTexturesHelper(n, textures); } @@ -955,57 +955,6 @@ CheckGLError(); } -void RasterImplementation::InitializeDiscardableTextureCHROMIUM( - GLuint texture_id) { - if (discardable_texture_manager_.TextureIsValid(texture_id)) { - SetGLError(GL_INVALID_VALUE, "glInitializeDiscardableTextureCHROMIUM", - "Texture ID already initialized"); - return; - } - ClientDiscardableHandle handle = - discardable_texture_manager_.InitializeTexture(helper_->command_buffer(), - texture_id); - if (!handle.IsValid()) - return; - - helper_->InitializeDiscardableTextureCHROMIUM(texture_id, handle.shm_id(), - handle.byte_offset()); -} - -void RasterImplementation::UnlockDiscardableTextureCHROMIUM(GLuint texture_id) { - if (!discardable_texture_manager_.TextureIsValid(texture_id)) { - SetGLError(GL_INVALID_VALUE, "glUnlockDiscardableTextureCHROMIUM", - "Texture ID not initialized"); - return; - } - - // |should_unbind_texture| will be set to true if the texture has been fully - // unlocked. In this case, ensure the texture is unbound. - bool should_unbind_texture = false; - discardable_texture_manager_.UnlockTexture(texture_id, - &should_unbind_texture); - if (should_unbind_texture) - UnbindTexturesHelper(1, &texture_id); - - helper_->UnlockDiscardableTextureCHROMIUM(texture_id); -} - -bool RasterImplementation::LockDiscardableTextureCHROMIUM(GLuint texture_id) { - if (!discardable_texture_manager_.TextureIsValid(texture_id)) { - SetGLError(GL_INVALID_VALUE, "glLockDiscardableTextureCHROMIUM", - "Texture ID not initialized"); - return false; - } - if (!discardable_texture_manager_.LockTexture(texture_id)) { - // Failure to lock means that this texture has been deleted on the service - // side. Delete it here as well. - DeleteTexturesHelper(1, &texture_id); - return false; - } - helper_->LockDiscardableTextureCHROMIUM(texture_id); - return true; -} - void* RasterImplementation::MapRasterCHROMIUM(GLsizeiptr size) { if (size < 0) { SetGLError(GL_INVALID_VALUE, "glMapRasterCHROMIUM", "negative size"); @@ -1247,10 +1196,10 @@ } void RasterImplementation::BeginGpuRaster() { - NOTIMPLEMENTED(); + NOTREACHED(); } void RasterImplementation::EndGpuRaster() { - NOTIMPLEMENTED(); + NOTREACHED(); } RasterImplementation::RasterProperties::RasterProperties(
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h index e836291a..88adb82 100644 --- a/gpu/command_buffer/client/raster_implementation.h +++ b/gpu/command_buffer/client/raster_implementation.h
@@ -16,7 +16,6 @@ #include "base/macros.h" #include "base/optional.h" #include "base/trace_event/memory_dump_provider.h" -#include "gpu/command_buffer/client/client_discardable_texture_manager.h" #include "gpu/command_buffer/client/client_font_manager.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gpu_control_client.h" @@ -278,7 +277,6 @@ IdAllocator query_id_allocator_; ClientFontManager font_manager_; - ClientDiscardableTextureManager discardable_texture_manager_; mutable base::Lock lost_lock_; bool lost_;
diff --git a/gpu/command_buffer/client/raster_implementation_autogen.h b/gpu/command_buffer/client/raster_implementation_autogen.h index b2393ae..9b064384 100644 --- a/gpu/command_buffer/client/raster_implementation_autogen.h +++ b/gpu/command_buffer/client/raster_implementation_autogen.h
@@ -65,12 +65,6 @@ GLenum GetGraphicsResetStatusKHR() override; -void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) override; - -void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) override; - -bool LockDiscardableTextureCHROMIUM(GLuint texture_id) override; - void EndRasterCHROMIUM() override; GLuint CreateTexture(bool use_buffer,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc index 59ed9ab..4ea1276 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.cc +++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -2,10 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <cstddef> - #include "gpu/command_buffer/client/raster_implementation_gles.h" +#include <algorithm> +#include <cstddef> +#include <limits> +#include <set> +#include <utility> +#include <vector> + #include "base/logging.h" #include "cc/paint/color_space_transfer_cache_entry.h" #include "cc/paint/decode_stashing_image_provider.h" @@ -286,7 +291,7 @@ void RasterImplementationGLES::DeleteTextures(GLsizei n, const GLuint* textures) { - DCHECK(n > 0); + DCHECK_GT(n, 0); for (GLsizei i = 0; i < n; i++) { auto texture_iter = texture_info_.find(textures[i]); DCHECK(texture_iter != texture_info_.end()); @@ -298,7 +303,7 @@ } gl_->DeleteTextures(n, textures); -}; +} void RasterImplementationGLES::SetColorSpaceMetadata(GLuint texture_id, GLColorSpace color_space) { @@ -372,7 +377,7 @@ if (texture->use_buffer) { DCHECK(use_texture_storage_image_); - DCHECK(levels == 1); + DCHECK_EQ(levels, 1); gl_->TexStorage2DImageCHROMIUM(texture->target, viz::TextureStorageFormat(texture->format), GL_SCANOUT_CHROMIUM, width, height); @@ -381,7 +386,7 @@ viz::TextureStorageFormat(texture->format), width, height); } else { - DCHECK(levels == 1); + DCHECK_EQ(levels, 1); // TODO(vmiura): Support more than one texture level. gl_->TexImage2D(texture->target, 0, viz::GLInternalFormat(texture->format), width, height, 0, viz::GLDataFormat(texture->format), @@ -427,24 +432,6 @@ height); } -void RasterImplementationGLES::InitializeDiscardableTextureCHROMIUM( - GLuint texture_id) { - Texture* texture = GetTexture(texture_id); - gl_->InitializeDiscardableTextureCHROMIUM(texture->id); -} - -void RasterImplementationGLES::UnlockDiscardableTextureCHROMIUM( - GLuint texture_id) { - Texture* texture = GetTexture(texture_id); - gl_->UnlockDiscardableTextureCHROMIUM(texture->id); -} - -bool RasterImplementationGLES::LockDiscardableTextureCHROMIUM( - GLuint texture_id) { - Texture* texture = GetTexture(texture_id); - return gl_->LockDiscardableTextureCHROMIUM(texture->id); -} - void RasterImplementationGLES::BeginRasterCHROMIUM( GLuint texture_id, GLuint sk_color, @@ -473,7 +460,7 @@ raster_properties_.emplace(sk_color, can_use_lcd_text, raster_color_space.color_space.ToSkColorSpace()); -}; +} void RasterImplementationGLES::RasterCHROMIUM( const cc::DisplayItemList* list,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h index c3fe71c0..7dd2682 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.h +++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -110,11 +110,6 @@ GLsizei width, GLsizei height) override; - // Discardable textures. - void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) override; - void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) override; - bool LockDiscardableTextureCHROMIUM(GLuint texture_id) override; - // OOP-Raster void BeginRasterCHROMIUM( GLuint texture_id,
diff --git a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc index d15ff7f6..533bb58 100644 --- a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc +++ b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
@@ -8,6 +8,9 @@ #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include <GLES3/gl3.h> +#include <memory> +#include <utility> +#include <vector> #include "base/containers/flat_map.h" #include "cc/paint/color_space_transfer_cache_entry.h" @@ -135,11 +138,6 @@ GLsizei width, GLsizei height)); - // Discardable textures. - MOCK_METHOD1(InitializeDiscardableTextureCHROMIUM, void(GLuint texture_id)); - MOCK_METHOD1(UnlockDiscardableTextureCHROMIUM, void(GLuint texture_id)); - MOCK_METHOD1(LockDiscardableTextureCHROMIUM, bool(GLuint texture_id)); - // OOP-Raster MOCK_METHOD6(BeginRasterCHROMIUM, void(GLuint texture_id, @@ -638,41 +636,6 @@ } } -TEST_F(RasterImplementationGLESTest, InitializeDiscardableTextureCHROMIUM) { - const GLuint kTextureId = 23; - - AllocTextureId(false, gfx::BufferUsage::GPU_READ, viz::RGBA_8888, kTextureId); - - EXPECT_CALL(*gl_, InitializeDiscardableTextureCHROMIUM(kTextureId)).Times(1); - ri_->InitializeDiscardableTextureCHROMIUM(kTextureId); -} - -TEST_F(RasterImplementationGLESTest, UnlockDiscardableTextureCHROMIUM) { - const GLuint kTextureId = 23; - - AllocTextureId(false, gfx::BufferUsage::GPU_READ, viz::RGBA_8888, kTextureId); - - EXPECT_CALL(*gl_, UnlockDiscardableTextureCHROMIUM(kTextureId)).Times(1); - ri_->UnlockDiscardableTextureCHROMIUM(kTextureId); -} - -TEST_F(RasterImplementationGLESTest, LockDiscardableTextureCHROMIUM) { - const GLuint kTextureId = 23; - bool ret = false; - - AllocTextureId(false, gfx::BufferUsage::GPU_READ, viz::RGBA_8888, kTextureId); - - EXPECT_CALL(*gl_, LockDiscardableTextureCHROMIUM(kTextureId)) - .WillOnce(Return(true)); - ret = ri_->LockDiscardableTextureCHROMIUM(kTextureId); - EXPECT_EQ(true, ret); - - EXPECT_CALL(*gl_, LockDiscardableTextureCHROMIUM(kTextureId)) - .WillOnce(Return(false)); - ret = ri_->LockDiscardableTextureCHROMIUM(kTextureId); - EXPECT_EQ(false, ret); -} - TEST_F(RasterImplementationGLESTest, RasterCHROMIUM) { const GLuint texture_id = 23; const GLuint sk_color = 0x226688AAu;
diff --git a/gpu/command_buffer/client/raster_implementation_unittest.cc b/gpu/command_buffer/client/raster_implementation_unittest.cc index 5e1fa681..76df1d97 100644 --- a/gpu/command_buffer/client/raster_implementation_unittest.cc +++ b/gpu/command_buffer/client/raster_implementation_unittest.cc
@@ -200,10 +200,6 @@ QueryTracker* GetQueryTracker() { return gl_->query_tracker_.get(); } - ClientDiscardableTextureManager* discardable_texture_manager() { - return &gl_->discardable_texture_manager_; - } - void* MapRasterCHROMIUM(GLsizeiptr size) { return gl_->MapRasterCHROMIUM(size); } @@ -905,85 +901,6 @@ EXPECT_FALSE(Initialize(init_options)); } -TEST_F(RasterImplementationTest, DiscardableMemoryDelete) { - const GLuint texture_id = 1; - EXPECT_FALSE(discardable_texture_manager()->TextureIsValid(texture_id)); - gl_->InitializeDiscardableTextureCHROMIUM(texture_id); - EXPECT_TRUE(discardable_texture_manager()->TextureIsValid(texture_id)); - - // Deleting a texture should clear its discardable entry. - gl_->DeleteTextures(1, &texture_id); - EXPECT_FALSE(discardable_texture_manager()->TextureIsValid(texture_id)); -} - -TEST_F(RasterImplementationTest, DiscardableTextureLockFail) { - const GLuint texture_id = 1; - gl_->InitializeDiscardableTextureCHROMIUM(texture_id); - EXPECT_TRUE(discardable_texture_manager()->TextureIsValid(texture_id)); - - // Unlock the handle on the client side. - gl_->UnlockDiscardableTextureCHROMIUM(texture_id); - - // Unlock and delete the handle on the service side. - ClientDiscardableHandle client_handle = - discardable_texture_manager()->GetHandleForTesting(texture_id); - ServiceDiscardableHandle service_handle(client_handle.BufferForTesting(), - client_handle.byte_offset(), - client_handle.shm_id()); - service_handle.Unlock(); - EXPECT_TRUE(service_handle.Delete()); - - // Trying to re-lock the texture via GL should fail and delete the entry. - EXPECT_FALSE(gl_->LockDiscardableTextureCHROMIUM(texture_id)); - EXPECT_FALSE(discardable_texture_manager()->TextureIsValid(texture_id)); -} - -TEST_F(RasterImplementationTest, DiscardableTextureDoubleInitError) { - const GLuint texture_id = 1; - gl_->InitializeDiscardableTextureCHROMIUM(texture_id); - EXPECT_EQ(GL_NO_ERROR, CheckError()); - gl_->InitializeDiscardableTextureCHROMIUM(texture_id); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); -} - -TEST_F(RasterImplementationTest, DiscardableTextureLockError) { - const GLuint texture_id = 1; - EXPECT_FALSE(gl_->LockDiscardableTextureCHROMIUM(texture_id)); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); -} - -/* -TODO(vmiura): Update use of BindTexture. -TEST_F(RasterImplementationTest, DiscardableTextureLockCounting) { - const GLint texture_id = 1; - gl_->InitializeDiscardableTextureCHROMIUM(texture_id); - EXPECT_TRUE(discardable_texture_manager()->TextureIsValid(texture_id)); - - // Bind the texture. - gl_->BindTexture(GL_TEXTURE_2D, texture_id); - GLint bound_texture_id = 0; - gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture_id); - EXPECT_EQ(texture_id, bound_texture_id); - - // Lock the texture 3 more times (for 4 locks total). - for (int i = 0; i < 3; ++i) { - gl_->LockDiscardableTextureCHROMIUM(texture_id); - } - - // Unlock 4 times. Only after the last unlock should the texture be unbound. - for (int i = 0; i < 4; ++i) { - gl_->UnlockDiscardableTextureCHROMIUM(texture_id); - bound_texture_id = 0; - gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture_id); - if (i < 3) { - EXPECT_EQ(texture_id, bound_texture_id); - } else { - EXPECT_EQ(0, bound_texture_id); - } - } -} -*/ - #include "base/macros.h" #include "gpu/command_buffer/client/raster_implementation_unittest_autogen.h"
diff --git a/gpu/command_buffer/client/raster_interface_autogen.h b/gpu/command_buffer/client/raster_interface_autogen.h index e88018d..abdfc4e 100644 --- a/gpu/command_buffer/client/raster_interface_autogen.h +++ b/gpu/command_buffer/client/raster_interface_autogen.h
@@ -44,9 +44,6 @@ GLsizei width, GLsizei height) = 0; virtual GLenum GetGraphicsResetStatusKHR() = 0; -virtual void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) = 0; -virtual void UnlockDiscardableTextureCHROMIUM(GLuint texture_id) = 0; -virtual bool LockDiscardableTextureCHROMIUM(GLuint texture_id) = 0; virtual void EndRasterCHROMIUM() = 0; virtual GLuint CreateTexture(bool use_buffer, gfx::BufferUsage buffer_usage,
diff --git a/gpu/command_buffer/common/raster_cmd_format_autogen.h b/gpu/command_buffer/common/raster_cmd_format_autogen.h index a65a890..faad7ed 100644 --- a/gpu/command_buffer/common/raster_cmd_format_autogen.h +++ b/gpu/command_buffer/common/raster_cmd_format_autogen.h
@@ -622,122 +622,6 @@ offsetof(UnpremultiplyAndDitherCopyCHROMIUM, height) == 24, "offset of UnpremultiplyAndDitherCopyCHROMIUM height should be 24"); -struct InitializeDiscardableTextureCHROMIUM { - typedef InitializeDiscardableTextureCHROMIUM ValueType; - static const CommandId kCmdId = kInitializeDiscardableTextureCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); - - static uint32_t ComputeSize() { - return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT - } - - void SetHeader() { header.SetCmd<ValueType>(); } - - void Init(GLuint _texture_id, uint32_t _shm_id, uint32_t _shm_offset) { - SetHeader(); - texture_id = _texture_id; - shm_id = _shm_id; - shm_offset = _shm_offset; - } - - void* Set(void* cmd, - GLuint _texture_id, - uint32_t _shm_id, - uint32_t _shm_offset) { - static_cast<ValueType*>(cmd)->Init(_texture_id, _shm_id, _shm_offset); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t texture_id; - uint32_t shm_id; - uint32_t shm_offset; -}; - -static_assert(sizeof(InitializeDiscardableTextureCHROMIUM) == 16, - "size of InitializeDiscardableTextureCHROMIUM should be 16"); -static_assert( - offsetof(InitializeDiscardableTextureCHROMIUM, header) == 0, - "offset of InitializeDiscardableTextureCHROMIUM header should be 0"); -static_assert( - offsetof(InitializeDiscardableTextureCHROMIUM, texture_id) == 4, - "offset of InitializeDiscardableTextureCHROMIUM texture_id should be 4"); -static_assert( - offsetof(InitializeDiscardableTextureCHROMIUM, shm_id) == 8, - "offset of InitializeDiscardableTextureCHROMIUM shm_id should be 8"); -static_assert( - offsetof(InitializeDiscardableTextureCHROMIUM, shm_offset) == 12, - "offset of InitializeDiscardableTextureCHROMIUM shm_offset should be 12"); - -struct UnlockDiscardableTextureCHROMIUM { - typedef UnlockDiscardableTextureCHROMIUM ValueType; - static const CommandId kCmdId = kUnlockDiscardableTextureCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); - - static uint32_t ComputeSize() { - return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT - } - - void SetHeader() { header.SetCmd<ValueType>(); } - - void Init(GLuint _texture_id) { - SetHeader(); - texture_id = _texture_id; - } - - void* Set(void* cmd, GLuint _texture_id) { - static_cast<ValueType*>(cmd)->Init(_texture_id); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t texture_id; -}; - -static_assert(sizeof(UnlockDiscardableTextureCHROMIUM) == 8, - "size of UnlockDiscardableTextureCHROMIUM should be 8"); -static_assert(offsetof(UnlockDiscardableTextureCHROMIUM, header) == 0, - "offset of UnlockDiscardableTextureCHROMIUM header should be 0"); -static_assert( - offsetof(UnlockDiscardableTextureCHROMIUM, texture_id) == 4, - "offset of UnlockDiscardableTextureCHROMIUM texture_id should be 4"); - -struct LockDiscardableTextureCHROMIUM { - typedef LockDiscardableTextureCHROMIUM ValueType; - static const CommandId kCmdId = kLockDiscardableTextureCHROMIUM; - static const cmd::ArgFlags kArgFlags = cmd::kFixed; - static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); - - static uint32_t ComputeSize() { - return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT - } - - void SetHeader() { header.SetCmd<ValueType>(); } - - void Init(GLuint _texture_id) { - SetHeader(); - texture_id = _texture_id; - } - - void* Set(void* cmd, GLuint _texture_id) { - static_cast<ValueType*>(cmd)->Init(_texture_id); - return NextCmdAddress<ValueType>(cmd); - } - - gpu::CommandHeader header; - uint32_t texture_id; -}; - -static_assert(sizeof(LockDiscardableTextureCHROMIUM) == 8, - "size of LockDiscardableTextureCHROMIUM should be 8"); -static_assert(offsetof(LockDiscardableTextureCHROMIUM, header) == 0, - "offset of LockDiscardableTextureCHROMIUM header should be 0"); -static_assert( - offsetof(LockDiscardableTextureCHROMIUM, texture_id) == 4, - "offset of LockDiscardableTextureCHROMIUM texture_id should be 4"); - struct BeginRasterCHROMIUM { typedef BeginRasterCHROMIUM ValueType; static const CommandId kCmdId = kBeginRasterCHROMIUM;
diff --git a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h index 59cbf6a..84bd76f 100644 --- a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
@@ -207,45 +207,6 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } -TEST_F(RasterFormatTest, InitializeDiscardableTextureCHROMIUM) { - cmds::InitializeDiscardableTextureCHROMIUM& cmd = - *GetBufferAs<cmds::InitializeDiscardableTextureCHROMIUM>(); - void* next_cmd = - cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12), - static_cast<uint32_t>(13)); - EXPECT_EQ( - static_cast<uint32_t>(cmds::InitializeDiscardableTextureCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLuint>(11), cmd.texture_id); - EXPECT_EQ(static_cast<uint32_t>(12), cmd.shm_id); - EXPECT_EQ(static_cast<uint32_t>(13), cmd.shm_offset); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - -TEST_F(RasterFormatTest, UnlockDiscardableTextureCHROMIUM) { - cmds::UnlockDiscardableTextureCHROMIUM& cmd = - *GetBufferAs<cmds::UnlockDiscardableTextureCHROMIUM>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11)); - EXPECT_EQ( - static_cast<uint32_t>(cmds::UnlockDiscardableTextureCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLuint>(11), cmd.texture_id); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - -TEST_F(RasterFormatTest, LockDiscardableTextureCHROMIUM) { - cmds::LockDiscardableTextureCHROMIUM& cmd = - *GetBufferAs<cmds::LockDiscardableTextureCHROMIUM>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11)); - EXPECT_EQ(static_cast<uint32_t>(cmds::LockDiscardableTextureCHROMIUM::kCmdId), - cmd.header.command); - EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLuint>(11), cmd.texture_id); - CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); -} - TEST_F(RasterFormatTest, BeginRasterCHROMIUM) { cmds::BeginRasterCHROMIUM& cmd = *GetBufferAs<cmds::BeginRasterCHROMIUM>(); void* next_cmd =
diff --git a/gpu/command_buffer/common/raster_cmd_ids_autogen.h b/gpu/command_buffer/common/raster_cmd_ids_autogen.h index ea5a391..e64146a2 100644 --- a/gpu/command_buffer/common/raster_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/raster_cmd_ids_autogen.h
@@ -26,24 +26,21 @@ OP(InsertFenceSyncCHROMIUM) /* 267 */ \ OP(WaitSyncTokenCHROMIUM) /* 268 */ \ OP(UnpremultiplyAndDitherCopyCHROMIUM) /* 269 */ \ - OP(InitializeDiscardableTextureCHROMIUM) /* 270 */ \ - OP(UnlockDiscardableTextureCHROMIUM) /* 271 */ \ - OP(LockDiscardableTextureCHROMIUM) /* 272 */ \ - OP(BeginRasterCHROMIUM) /* 273 */ \ - OP(RasterCHROMIUM) /* 274 */ \ - OP(EndRasterCHROMIUM) /* 275 */ \ - OP(CreateTransferCacheEntryINTERNAL) /* 276 */ \ - OP(DeleteTransferCacheEntryINTERNAL) /* 277 */ \ - OP(UnlockTransferCacheEntryINTERNAL) /* 278 */ \ - OP(CreateTexture) /* 279 */ \ - OP(SetColorSpaceMetadata) /* 280 */ \ - OP(ProduceTextureDirectImmediate) /* 281 */ \ - OP(CreateAndConsumeTextureINTERNALImmediate) /* 282 */ \ - OP(TexParameteri) /* 283 */ \ - OP(BindTexImage2DCHROMIUM) /* 284 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 285 */ \ - OP(TexStorage2D) /* 286 */ \ - OP(CopySubTexture) /* 287 */ + OP(BeginRasterCHROMIUM) /* 270 */ \ + OP(RasterCHROMIUM) /* 271 */ \ + OP(EndRasterCHROMIUM) /* 272 */ \ + OP(CreateTransferCacheEntryINTERNAL) /* 273 */ \ + OP(DeleteTransferCacheEntryINTERNAL) /* 274 */ \ + OP(UnlockTransferCacheEntryINTERNAL) /* 275 */ \ + OP(CreateTexture) /* 276 */ \ + OP(SetColorSpaceMetadata) /* 277 */ \ + OP(ProduceTextureDirectImmediate) /* 278 */ \ + OP(CreateAndConsumeTextureINTERNALImmediate) /* 279 */ \ + OP(TexParameteri) /* 280 */ \ + OP(BindTexImage2DCHROMIUM) /* 281 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 282 */ \ + OP(TexStorage2D) /* 283 */ \ + OP(CopySubTexture) /* 284 */ enum CommandId { kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/raster_cmd_buffer_functions.txt b/gpu/command_buffer/raster_cmd_buffer_functions.txt index 05437553..f616108 100644 --- a/gpu/command_buffer/raster_cmd_buffer_functions.txt +++ b/gpu/command_buffer/raster_cmd_buffer_functions.txt
@@ -32,11 +32,6 @@ // Extension KHR_robustness GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); -// Extension CHROMIUM_discardable_textures -GL_APICALL void GL_APIENTRY glInitializeDiscardableTextureCHROMIUM (GLuint texture_id); -GL_APICALL void GL_APIENTRY glUnlockDiscardableTextureCHROMIUM (GLuint texture_id); -GL_APICALL bool GL_APIENTRY glLockDiscardableTextureCHROMIUM (GLuint texture_id); - // Extension CHROMIUM_raster_transport GL_APICALL void GL_APIENTRY glBeginRasterCHROMIUM (GLuint texture_id, GLuint sk_color, GLuint msaa_sample_count, GLboolean can_use_lcd_text, GLint color_type, GLuint color_space_transfer_cache_id); GL_APICALL void GL_APIENTRY glRasterCHROMIUM (GLuint raster_shm_id, GLuint raster_shm_offset, GLsizeiptr raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, GLsizeiptr font_shm_size);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 8097ccf3..a10c7d2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -20183,6 +20183,12 @@ } ~TransferCacheDeserializeHelperImpl() override = default; + void CreateLocalEntry( + uint32_t id, + std::unique_ptr<cc::ServiceTransferCacheEntry> entry) override { + transfer_cache_->CreateLocalEntry(id, std::move(entry)); + } + private: cc::ServiceTransferCacheEntry* GetEntryInternal( cc::TransferCacheEntryType entry_type,
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc index 0dab7fc..25e2fd6 100644 --- a/gpu/command_buffer/service/raster_decoder.cc +++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -699,6 +699,7 @@ sk_sp<GrContext> gr_context_; sk_sp<SkSurface> sk_surface_; std::unique_ptr<SkCanvas> raster_canvas_; + uint32_t raster_color_space_id_; base::WeakPtrFactory<DecoderContext> weak_ptr_factory_; @@ -1766,27 +1767,6 @@ return error::kNoError; } -error::Error RasterDecoderImpl::HandleInitializeDiscardableTextureCHROMIUM( - uint32_t immediate_data_size, - const volatile void* cmd_data) { - NOTIMPLEMENTED(); - return error::kNoError; -} - -error::Error RasterDecoderImpl::HandleUnlockDiscardableTextureCHROMIUM( - uint32_t immediate_data_size, - const volatile void* cmd_data) { - NOTIMPLEMENTED(); - return error::kNoError; -} - -error::Error RasterDecoderImpl::HandleLockDiscardableTextureCHROMIUM( - uint32_t immediate_data_size, - const volatile void* cmd_data) { - NOTIMPLEMENTED(); - return error::kNoError; -} - error::Error RasterDecoderImpl::HandleInsertFenceSyncCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) { @@ -2691,6 +2671,12 @@ } ~TransferCacheDeserializeHelperImpl() override = default; + void CreateLocalEntry( + uint32_t id, + std::unique_ptr<cc::ServiceTransferCacheEntry> entry) override { + transfer_cache_->CreateLocalEntry(id, std::move(entry)); + } + private: cc::ServiceTransferCacheEntry* GetEntryInternal( cc::TransferCacheEntryType entry_type, @@ -2841,6 +2827,7 @@ raster_canvas_ = SkCreateColorSpaceXformCanvas( sk_surface_->getCanvas(), color_space_entry->color_space().ToSkColorSpace()); + raster_color_space_id_ = color_space_transfer_cache_id; // All or nothing clearing, as no way to validate the client's input on what // is the "used" part of the texture. @@ -2910,6 +2897,7 @@ TransferCacheDeserializeHelperImpl impl(transfer_cache_.get()); options.transfer_cache = &impl; options.strike_client = font_manager_.strike_client(); + options.raster_color_space_id = raster_color_space_id_; int op_idx = 0; size_t paint_buffer_size = raster_shm_size;
diff --git a/gpu/command_buffer/service/service_transfer_cache.cc b/gpu/command_buffer/service/service_transfer_cache.cc index 4a20a60..faea324d 100644 --- a/gpu/command_buffer/service/service_transfer_cache.cc +++ b/gpu/command_buffer/service/service_transfer_cache.cc
@@ -19,7 +19,7 @@ } // namespace ServiceTransferCache::CacheEntryInternal::CacheEntryInternal( - ServiceDiscardableHandle handle, + base::Optional<ServiceDiscardableHandle> handle, std::unique_ptr<cc::ServiceTransferCacheEntry> entry) : handle(handle), entry(std::move(entry)) {} @@ -63,6 +63,21 @@ return true; } +void ServiceTransferCache::CreateLocalEntry( + uint32_t entry_id, + std::unique_ptr<cc::ServiceTransferCacheEntry> entry) { + if (!entry) + return; + + DeleteEntry(entry->Type(), entry_id); + + total_size_ += entry->CachedSize(); + + auto key = std::make_pair(entry->Type(), entry_id); + entries_.Put(key, CacheEntryInternal(base::nullopt, std::move(entry))); + EnforceLimits(); +} + bool ServiceTransferCache::UnlockEntry(cc::TransferCacheEntryType entry_type, uint32_t entry_id) { auto key = std::make_pair(entry_type, entry_id); @@ -70,7 +85,9 @@ if (found == entries_.end()) return false; - found->second.handle.Unlock(); + if (!found->second.handle) + return false; + found->second.handle->Unlock(); return true; } @@ -81,7 +98,8 @@ if (found == entries_.end()) return false; - found->second.handle.ForceDelete(); + if (found->second.handle) + found->second.handle->ForceDelete(); total_size_ -= found->second.entry->CachedSize(); entries_.Erase(found); return true; @@ -102,7 +120,7 @@ if (total_size_ <= cache_size_limit_) { return; } - if (!it->second.handle.Delete()) { + if (it->second.handle && !it->second.handle->Delete()) { ++it; continue; }
diff --git a/gpu/command_buffer/service/service_transfer_cache.h b/gpu/command_buffer/service/service_transfer_cache.h index 4cacac1..883d0eb 100644 --- a/gpu/command_buffer/service/service_transfer_cache.h +++ b/gpu/command_buffer/service/service_transfer_cache.h
@@ -34,6 +34,8 @@ ServiceDiscardableHandle handle, GrContext* context, base::span<uint8_t> data); + void CreateLocalEntry(uint32_t entry_id, + std::unique_ptr<cc::ServiceTransferCacheEntry> entry); bool UnlockEntry(cc::TransferCacheEntryType entry_type, uint32_t entry_id); bool DeleteEntry(cc::TransferCacheEntryType entry_type, uint32_t entry_id); cc::ServiceTransferCacheEntry* GetEntry(cc::TransferCacheEntryType entry_type, @@ -49,12 +51,12 @@ void EnforceLimits(); struct CacheEntryInternal { - CacheEntryInternal(ServiceDiscardableHandle handle, + CacheEntryInternal(base::Optional<ServiceDiscardableHandle> handle, std::unique_ptr<cc::ServiceTransferCacheEntry> entry); CacheEntryInternal(CacheEntryInternal&& other); CacheEntryInternal& operator=(CacheEntryInternal&& other); ~CacheEntryInternal(); - ServiceDiscardableHandle handle; + base::Optional<ServiceDiscardableHandle> handle; std::unique_ptr<cc::ServiceTransferCacheEntry> entry; }; using EntryCache =
diff --git a/gpu/config/gpu_blacklist_unittest.cc b/gpu/config/gpu_blacklist_unittest.cc index 17f2bf80c..e3c14679 100644 --- a/gpu/config/gpu_blacklist_unittest.cc +++ b/gpu/config/gpu_blacklist_unittest.cc
@@ -46,6 +46,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc index a34cc7fc..720d8794 100644 --- a/gpu/config/gpu_control_list.cc +++ b/gpu/config/gpu_control_list.cc
@@ -320,7 +320,7 @@ if (os_version.IsSpecified() && !os_version.Contains(target_os_version)) return false; } - if (vendor_id != 0) { + if (vendor_id != 0 || gpu_series_list_size > 0) { std::vector<GPUInfo::GPUDevice> candidates; switch (multi_gpu_category) { case kMultiGpuCategoryPrimary: @@ -346,26 +346,41 @@ candidates.push_back(gpu_info.gpu); } - GPUInfo::GPUDevice gpu; - gpu.vendor_id = vendor_id; bool found = false; - if (device_id_size == 0) { - for (size_t ii = 0; ii < candidates.size(); ++ii) { - if (gpu.vendor_id == candidates[ii].vendor_id) { - found = true; - break; + if (gpu_series_list_size > 0) { + for (size_t ii = 0; !found && ii < candidates.size(); ++ii) { + GpuSeriesType candidate_series = GetGpuSeriesType( + candidates[ii].vendor_id, candidates[ii].device_id); + if (candidate_series == GpuSeriesType::kUnknown) + continue; + for (size_t jj = 0; jj < gpu_series_list_size; ++jj) { + if (candidate_series == gpu_series_list[jj]) { + found = true; + break; + } } } } else { - for (size_t ii = 0; ii < device_id_size; ++ii) { - gpu.device_id = device_ids[ii]; - for (size_t jj = 0; jj < candidates.size(); ++jj) { - if (gpu.vendor_id == candidates[jj].vendor_id && - gpu.device_id == candidates[jj].device_id) { + GPUInfo::GPUDevice gpu; + gpu.vendor_id = vendor_id; + if (device_id_size == 0) { + for (size_t ii = 0; ii < candidates.size(); ++ii) { + if (gpu.vendor_id == candidates[ii].vendor_id) { found = true; break; } } + } else { + for (size_t ii = 0; ii < device_id_size; ++ii) { + gpu.device_id = device_ids[ii]; + for (size_t jj = 0; jj < candidates.size(); ++jj) { + if (gpu.vendor_id == candidates[jj].vendor_id && + gpu.device_id == candidates[jj].device_id) { + found = true; + break; + } + } + } } } if (!found) @@ -687,4 +702,58 @@ return true; } +// static +GpuControlList::GpuSeriesType GpuControlList::GetGpuSeriesType( + uint32_t vendor_id, + uint32_t device_id) { + if (vendor_id == 0x8086) { // Intel + // https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units + // We only identify Intel 6th gen or newer. + uint32_t masked_device_id = device_id & 0xFF00; + switch (masked_device_id) { + case 0x0100: + switch (device_id & 0xFFF0) { + case 0x0100: + case 0x0110: + case 0x0120: + return GpuSeriesType::kIntelSandyBridge; + case 0x0150: + if (device_id == 0x0155 || device_id == 0x0157) + return GpuSeriesType::kIntelValleyView; + if (device_id == 0x0152 || device_id == 0x015A) + return GpuSeriesType::kIntelIvyBridge; + break; + case 0x0160: + return GpuSeriesType::kIntelIvyBridge; + default: + break; + } + break; + case 0x0F00: + return GpuSeriesType::kIntelValleyView; + case 0x0400: + case 0x0A00: + case 0x0D00: + return GpuSeriesType::kIntelHaswell; + case 0x2200: + return GpuSeriesType::kIntelCherryView; + case 0x1600: + return GpuSeriesType::kIntelBroadwell; + case 0x5A00: + return GpuSeriesType::kIntelApolloLake; + case 0x1900: + return GpuSeriesType::kIntelSkyLake; + case 0x3100: + return GpuSeriesType::kIntelGeminiLake; + case 0x5900: + return GpuSeriesType::kIntelKabyLake; + case 0x3E00: + return GpuSeriesType::kIntelCoffeeLake; + default: + break; + } + } + return GpuSeriesType::kUnknown; +} + } // namespace gpu
diff --git a/gpu/config/gpu_control_list.h b/gpu/config/gpu_control_list.h index 416386d7..608b51b 100644 --- a/gpu/config/gpu_control_list.h +++ b/gpu/config/gpu_control_list.h
@@ -84,6 +84,27 @@ kVersionStyleUnknown }; + enum class GpuSeriesType { + // Intel 6th gen + kIntelSandyBridge, + // Intel 7th gen + kIntelValleyView, // BayTrail + kIntelIvyBridge, + kIntelHaswell, + // Intel 8th gen + kIntelCherryView, // Braswell + kIntelBroadwell, + // Intel 9th gen + kIntelApolloLake, + kIntelSkyLake, + kIntelGeminiLake, + kIntelKabyLake, + kIntelCoffeeLake, + // Please also update |gpu_series_map| in process_json.py. + + kUnknown, + }; + struct GPU_EXPORT Version { NumericOp op; VersionStyle style; @@ -173,6 +194,8 @@ const DriverInfo* driver_info; const GLStrings* gl_strings; const MachineModelInfo* machine_model_info; + size_t gpu_series_list_size; + const GpuSeriesType* gpu_series_list; const More* more; bool Contains(OsType os_type, @@ -292,6 +315,8 @@ // Gets the current OS type. static OsType GetOsType(); + static GpuSeriesType GetGpuSeriesType(uint32_t vendor_id, uint32_t device_id); + size_t entry_count_; const Entry* entries_; // This records all the entries that are appliable to the current user
diff --git a/gpu/config/gpu_control_list_entry_unittest.cc b/gpu/config/gpu_control_list_entry_unittest.cc index a1c9971..312adfbd4 100644 --- a/gpu/config/gpu_control_list_entry_unittest.cc +++ b/gpu/config/gpu_control_list_entry_unittest.cc
@@ -665,4 +665,185 @@ EXPECT_TRUE(entry.Contains(kOsLinux, "7.0", gpu_info)); } +TEST_F(GpuControlListEntryTest, GpuSeries) { + const Entry& entry = GetEntry(kGpuControlListEntryTest_GpuSeries); + GPUInfo gpu_info; + gpu_info.gpu.vendor_id = 0x8086; + // Intel KabyLake + gpu_info.gpu.device_id = 0x5916; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + // Intel SandyBridge + gpu_info.gpu.device_id = 0x0116; + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + // Intel SkyLake + gpu_info.gpu.device_id = 0x1916; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + // Non-Intel GPU + gpu_info.gpu.vendor_id = 0x10de; + gpu_info.gpu.device_id = 0x0df8; + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); +} + +TEST_F(GpuControlListEntryTest, GpuSeriesActive) { + const Entry& entry = GetEntry(kGpuControlListEntryTest_GpuSeriesActive); + + GPUInfo::GPUDevice intel_gpu; + intel_gpu.vendor_id = 0x8086; + intel_gpu.device_id = 0x5916; + GPUInfo::GPUDevice nvidia_gpu; + nvidia_gpu.vendor_id = 0x10de; + nvidia_gpu.device_id = 0x0df8; + + { // Single GPU + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is primary and active + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + gpu_info.gpu.active = true; + gpu_info.secondary_gpus.push_back(nvidia_gpu); + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is secondary and active + GPUInfo gpu_info; + gpu_info.gpu = nvidia_gpu; + gpu_info.secondary_gpus.push_back(intel_gpu); + gpu_info.secondary_gpus[0].active = true; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, NVidia is primary and active + GPUInfo gpu_info; + gpu_info.gpu = nvidia_gpu; + gpu_info.gpu.active = true; + gpu_info.secondary_gpus.push_back(intel_gpu); + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, NVidia is secondary and active + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + gpu_info.secondary_gpus.push_back(nvidia_gpu); + gpu_info.secondary_gpus[0].active = true; + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + } +} + +TEST_F(GpuControlListEntryTest, GpuSeriesAny) { + const Entry& entry = GetEntry(kGpuControlListEntryTest_GpuSeriesAny); + + GPUInfo::GPUDevice intel_gpu; + intel_gpu.vendor_id = 0x8086; + intel_gpu.device_id = 0x5916; + GPUInfo::GPUDevice nvidia_gpu; + nvidia_gpu.vendor_id = 0x10de; + nvidia_gpu.device_id = 0x0df8; + + { // Single GPU Intel + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Single GPU NVidia + GPUInfo gpu_info; + gpu_info.gpu = nvidia_gpu; + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is primary + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + gpu_info.secondary_gpus.push_back(nvidia_gpu); + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is secondary + GPUInfo gpu_info; + gpu_info.gpu = nvidia_gpu; + gpu_info.secondary_gpus.push_back(intel_gpu); + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } +} + +TEST_F(GpuControlListEntryTest, GpuSeriesPrimary) { + const Entry& entry = GetEntry(kGpuControlListEntryTest_GpuSeriesPrimary); + + GPUInfo::GPUDevice intel_gpu; + intel_gpu.vendor_id = 0x8086; + intel_gpu.device_id = 0x5916; + GPUInfo::GPUDevice nvidia_gpu; + nvidia_gpu.vendor_id = 0x10de; + nvidia_gpu.device_id = 0x0df8; + + { // Single GPU + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is primary + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + gpu_info.secondary_gpus.push_back(nvidia_gpu); + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is secondary + GPUInfo gpu_info; + gpu_info.gpu = nvidia_gpu; + gpu_info.secondary_gpus.push_back(intel_gpu); + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + } +} + +TEST_F(GpuControlListEntryTest, GpuSeriesSecondary) { + const Entry& entry = GetEntry(kGpuControlListEntryTest_GpuSeriesSecondary); + + GPUInfo::GPUDevice intel_gpu; + intel_gpu.vendor_id = 0x8086; + intel_gpu.device_id = 0x5916; + GPUInfo::GPUDevice nvidia_gpu; + nvidia_gpu.vendor_id = 0x10de; + nvidia_gpu.device_id = 0x0df8; + + { // Single GPU + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is primary + GPUInfo gpu_info; + gpu_info.gpu = intel_gpu; + gpu_info.secondary_gpus.push_back(nvidia_gpu); + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + } + + { // Dual GPU, Intel is secondary + GPUInfo gpu_info; + gpu_info.gpu = nvidia_gpu; + gpu_info.secondary_gpus.push_back(intel_gpu); + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); + } +} + +TEST_F(GpuControlListEntryTest, GpuSeriesInException) { + const Entry& entry = GetEntry(kGpuControlListEntryTest_GpuSeriesInException); + + GPUInfo gpu_info; + // Intel KabyLake + gpu_info.gpu.vendor_id = 0x8086; + gpu_info.gpu.device_id = 0x5916; + EXPECT_FALSE(entry.Contains(kOsWin, "10.0", gpu_info)); + // Intel SandyBridge + gpu_info.gpu.vendor_id = 0x8086; + gpu_info.gpu.device_id = 0x0116; + EXPECT_TRUE(entry.Contains(kOsWin, "10.0", gpu_info)); +} + } // namespace gpu
diff --git a/gpu/config/gpu_control_list_format.txt b/gpu/config/gpu_control_list_format.txt index 449263d..689aa6c 100644 --- a/gpu/config/gpu_control_list_format.txt +++ b/gpu/config/gpu_control_list_format.txt
@@ -67,6 +67,10 @@ // 28. "test_group" is an non-negative integer. If not specified, it defaults // to 0, which is Chrome's blacklist. Any entries with a non-zero test_group // ID will be applied if Chrome runs with --gpu-blacklist-test-group=ID. +// 29. "gpu_series" is a list of gpu series names. Currently supported series +// include: "intel_ivybridge", "intel_sandybridge", "intel_haswell", +// "intel_broadwell", "intel_skylake", "intel_kabylake", "intel_coffeelake", +// "intel_cherryview". // // VERSION includes "op", "style", "value", and "value2". "op" can be any of // the following values: "=", "<", "<=", ">", ">=", "any", "between". "style"
diff --git a/gpu/config/gpu_control_list_testing.json b/gpu/config/gpu_control_list_testing.json index 827ca7a4..81629662 100644 --- a/gpu/config/gpu_control_list_testing.json +++ b/gpu/config/gpu_control_list_testing.json
@@ -733,6 +733,75 @@ "features": [ "test_feature_1" ] + }, + { + "id": 61, + "description": "GpuControlListEntryTest.GpuSeries", + "gpu_series": [ + "intel_skylake", + "intel_kabylake" + ], + "features": [ + "test_feature_0" + ] + }, + { + "id": 62, + "description": "GpuControlListEntryTest.GpuSeriesActive", + "gpu_series": [ + "intel_kabylake" + ], + "multi_gpu_category": "active", + "features": [ + "test_feature_0" + ] + }, + { + "id": 63, + "description": "GpuControlListEntryTest.GpuSeriesAny", + "gpu_series": [ + "intel_kabylake" + ], + "multi_gpu_category": "any", + "features": [ + "test_feature_0" + ] + }, + { + "id": 64, + "description": "GpuControlListEntryTest.GpuSeriesPrimary", + "gpu_series": [ + "intel_kabylake" + ], + "multi_gpu_category": "primary", + "features": [ + "test_feature_0" + ] + }, + { + "id": 65, + "description": "GpuControlListEntryTest.GpuSeriesSecondary", + "gpu_series": [ + "intel_kabylake" + ], + "multi_gpu_category": "secondary", + "features": [ + "test_feature_0" + ] + }, + { + "id": 66, + "description": "GpuControlListEntryTest.GpuSeriesInException", + "exceptions": [ + { + "gpu_series": [ + "intel_kabylake" + ] + } + ], + "features": [ + "test_feature_0" + ] } ] }
diff --git a/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h b/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h index 60382f3..f41be06 100644 --- a/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h +++ b/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h
@@ -267,8 +267,8 @@ }; const GpuControlList::MachineModelInfo kMachineModelInfoForEntry27 = { - arraysize(kMachineModelNameForEntry27), // machine model name size - kMachineModelNameForEntry27, // machine model names + base::size(kMachineModelNameForEntry27), // machine model name size + kMachineModelNameForEntry27, // machine model names {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // machine model version }; @@ -282,7 +282,7 @@ }; const GpuControlList::MachineModelInfo kMachineModelInfoForEntry28Exception0 = { - arraysize( + base::size( kMachineModelNameForEntry28Exception0), // machine model name size kMachineModelNameForEntry28Exception0, // machine model names {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, @@ -298,8 +298,8 @@ }; const GpuControlList::MachineModelInfo kMachineModelInfoForEntry29 = { - arraysize(kMachineModelNameForEntry29), // machine model name size - kMachineModelNameForEntry29, // machine model names + base::size(kMachineModelNameForEntry29), // machine model name size + kMachineModelNameForEntry29, // machine model names {GpuControlList::kEQ, GpuControlList::kVersionStyleNumerical, "7.1", nullptr}, // machine model version }; @@ -313,8 +313,8 @@ }; const GpuControlList::MachineModelInfo kMachineModelInfoForEntry30 = { - arraysize(kMachineModelNameForEntry30), // machine model name size - kMachineModelNameForEntry30, // machine model names + base::size(kMachineModelNameForEntry30), // machine model name size + kMachineModelNameForEntry30, // machine model names {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // machine model version }; @@ -596,6 +596,55 @@ 2, // test_group }; +const int kFeatureListForEntry61[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::GpuSeriesType kGpuSeriesForEntry61[2] = { + GpuControlList::GpuSeriesType::kIntelSkyLake, + GpuControlList::GpuSeriesType::kIntelKabyLake, +}; + +const int kFeatureListForEntry62[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::GpuSeriesType kGpuSeriesForEntry62[1] = { + GpuControlList::GpuSeriesType::kIntelKabyLake, +}; + +const int kFeatureListForEntry63[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::GpuSeriesType kGpuSeriesForEntry63[1] = { + GpuControlList::GpuSeriesType::kIntelKabyLake, +}; + +const int kFeatureListForEntry64[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::GpuSeriesType kGpuSeriesForEntry64[1] = { + GpuControlList::GpuSeriesType::kIntelKabyLake, +}; + +const int kFeatureListForEntry65[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::GpuSeriesType kGpuSeriesForEntry65[1] = { + GpuControlList::GpuSeriesType::kIntelKabyLake, +}; + +const int kFeatureListForEntry66[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::GpuSeriesType kGpuSeriesForEntry66Exception0[1] = { + GpuControlList::GpuSeriesType::kIntelKabyLake, +}; + } // namespace gpu #endif // GPU_CONFIG_GPU_CONTROL_LIST_TESTING_ARRAYS_AND_STRUCTS_AUTOGEN_H_
diff --git a/gpu/config/gpu_control_list_testing_autogen.cc b/gpu/config/gpu_control_list_testing_autogen.cc index 72408ae..0fefefe 100644 --- a/gpu/config/gpu_control_list_testing_autogen.cc +++ b/gpu/config/gpu_control_list_testing_autogen.cc
@@ -19,26 +19,28 @@ { 1, // id "GpuControlListEntryTest.DetailedEntry", - arraysize(kFeatureListForEntry1), // features size - kFeatureListForEntry1, // features - arraysize(kDisabledExtensionsForEntry1), // DisabledExtensions size - kDisabledExtensionsForEntry1, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - arraysize(kCrBugsForEntry1), // CrBugs size - kCrBugsForEntry1, // CrBugs + base::size(kFeatureListForEntry1), // features size + kFeatureListForEntry1, // features + base::size(kDisabledExtensionsForEntry1), // DisabledExtensions size + kDisabledExtensionsForEntry1, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + base::size(kCrBugsForEntry1), // CrBugs size + kCrBugsForEntry1, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kEQ, GpuControlList::kVersionStyleNumerical, "10.6.4", nullptr}, // os_version 0x10de, // vendor_id - arraysize(kDeviceIDsForEntry1), // DeviceIDs size + base::size(kDeviceIDsForEntry1), // DeviceIDs size kDeviceIDsForEntry1, // DeviceIDs GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style &kDriverInfoForEntry1, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -47,14 +49,14 @@ { 2, // id "GpuControlListEntryTest.VendorOnAllOsEntry", - arraysize(kFeatureListForEntry2), // features size - kFeatureListForEntry2, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry2), // features size + kFeatureListForEntry2, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -67,6 +69,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -75,14 +79,14 @@ { 3, // id "GpuControlListEntryTest.VendorOnLinuxEntry", - arraysize(kFeatureListForEntry3), // features size - kFeatureListForEntry3, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry3), // features size + kFeatureListForEntry3, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -95,6 +99,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -103,14 +109,14 @@ { 4, // id "GpuControlListEntryTest.AllExceptNVidiaOnLinuxEntry", - arraysize(kFeatureListForEntry4), // features size - kFeatureListForEntry4, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry4), // features size + kFeatureListForEntry4, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -123,22 +129,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry4), // exceptions count - kExceptionsForEntry4, // exceptions + base::size(kExceptionsForEntry4), // exceptions count + kExceptionsForEntry4, // exceptions }, { 5, // id "GpuControlListEntryTest.AllExceptIntelOnLinuxEntry", - arraysize(kFeatureListForEntry5), // features size - kFeatureListForEntry5, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry5), // features size + kFeatureListForEntry5, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -151,22 +159,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry5), // exceptions count - kExceptionsForEntry5, // exceptions + base::size(kExceptionsForEntry5), // exceptions count + kExceptionsForEntry5, // exceptions }, { 6, // id "GpuControlListEntryTest.DateOnWindowsEntry", - arraysize(kFeatureListForEntry6), // features size - kFeatureListForEntry6, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry6), // features size + kFeatureListForEntry6, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsWin, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -179,6 +189,8 @@ &kDriverInfoForEntry6, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -187,26 +199,28 @@ { 7, // id "GpuControlListEntryTest.MultipleDevicesEntry", - arraysize(kFeatureListForEntry7), // features size - kFeatureListForEntry7, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry7), // features size + kFeatureListForEntry7, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x10de, // vendor_id - arraysize(kDeviceIDsForEntry7), // DeviceIDs size + base::size(kDeviceIDsForEntry7), // DeviceIDs size kDeviceIDsForEntry7, // DeviceIDs GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -215,14 +229,14 @@ { 8, // id "GpuControlListEntryTest.ChromeOSEntry", - arraysize(kFeatureListForEntry8), // features size - kFeatureListForEntry8, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry8), // features size + kFeatureListForEntry8, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsChromeOS, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -235,6 +249,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -243,14 +259,14 @@ { 9, // id "GpuControlListEntryTest.GlVersionGLESEntry", - arraysize(kFeatureListForEntry9), // features size - kFeatureListForEntry9, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry9), // features size + kFeatureListForEntry9, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -263,6 +279,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry9, // more data }, 0, // exceptions count @@ -271,14 +289,14 @@ { 10, // id "GpuControlListEntryTest.GlVersionANGLEEntry", - arraysize(kFeatureListForEntry10), // features size - kFeatureListForEntry10, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry10), // features size + kFeatureListForEntry10, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -291,6 +309,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry10, // more data }, 0, // exceptions count @@ -299,14 +319,14 @@ { 11, // id "GpuControlListEntryTest.GlVersionGLEntry", - arraysize(kFeatureListForEntry11), // features size - kFeatureListForEntry11, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry11), // features size + kFeatureListForEntry11, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -319,6 +339,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry11, // more data }, 0, // exceptions count @@ -327,14 +349,14 @@ { 12, // id "GpuControlListEntryTest.GlVendorEqual", - arraysize(kFeatureListForEntry12), // features size - kFeatureListForEntry12, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry12), // features size + kFeatureListForEntry12, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -347,6 +369,8 @@ nullptr, // driver info &kGLStringsForEntry12, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -355,14 +379,14 @@ { 13, // id "GpuControlListEntryTest.GlVendorWithDot", - arraysize(kFeatureListForEntry13), // features size - kFeatureListForEntry13, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry13), // features size + kFeatureListForEntry13, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -375,6 +399,8 @@ nullptr, // driver info &kGLStringsForEntry13, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -383,14 +409,14 @@ { 14, // id "GpuControlListEntryTest.GlRendererContains", - arraysize(kFeatureListForEntry14), // features size - kFeatureListForEntry14, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry14), // features size + kFeatureListForEntry14, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -403,6 +429,8 @@ nullptr, // driver info &kGLStringsForEntry14, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -411,14 +439,14 @@ { 15, // id "GpuControlListEntryTest.GlRendererCaseInsensitive", - arraysize(kFeatureListForEntry15), // features size - kFeatureListForEntry15, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry15), // features size + kFeatureListForEntry15, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -431,6 +459,8 @@ nullptr, // driver info &kGLStringsForEntry15, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -439,14 +469,14 @@ { 16, // id "GpuControlListEntryTest.GlExtensionsEndWith", - arraysize(kFeatureListForEntry16), // features size - kFeatureListForEntry16, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry16), // features size + kFeatureListForEntry16, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -459,6 +489,8 @@ nullptr, // driver info &kGLStringsForEntry16, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -467,14 +499,14 @@ { 17, // id "GpuControlListEntryTest.OptimusEntry", - arraysize(kFeatureListForEntry17), // features size - kFeatureListForEntry17, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry17), // features size + kFeatureListForEntry17, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -487,6 +519,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -495,14 +529,14 @@ { 18, // id "GpuControlListEntryTest.AMDSwitchableEntry", - arraysize(kFeatureListForEntry18), // features size - kFeatureListForEntry18, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry18), // features size + kFeatureListForEntry18, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -515,6 +549,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -523,14 +559,14 @@ { 19, // id "GpuControlListEntryTest.DriverVendorBeginWith", - arraysize(kFeatureListForEntry19), // features size - kFeatureListForEntry19, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry19), // features size + kFeatureListForEntry19, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -543,6 +579,8 @@ &kDriverInfoForEntry19, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -551,14 +589,14 @@ { 20, // id "GpuControlListEntryTest.LexicalDriverVersionEntry", - arraysize(kFeatureListForEntry20), // features size - kFeatureListForEntry20, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry20), // features size + kFeatureListForEntry20, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -571,6 +609,8 @@ &kDriverInfoForEntry20, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -579,14 +619,14 @@ { 21, // id "GpuControlListEntryTest.NeedsMoreInfoEntry", - arraysize(kFeatureListForEntry21), // features size - kFeatureListForEntry21, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry21), // features size + kFeatureListForEntry21, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -599,6 +639,8 @@ &kDriverInfoForEntry21, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -607,14 +649,14 @@ { 22, // id "GpuControlListEntryTest.NeedsMoreInfoForExceptionsEntry", - arraysize(kFeatureListForEntry22), // features size - kFeatureListForEntry22, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry22), // features size + kFeatureListForEntry22, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -627,22 +669,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry22), // exceptions count - kExceptionsForEntry22, // exceptions + base::size(kExceptionsForEntry22), // exceptions count + kExceptionsForEntry22, // exceptions }, { 23, // id "GpuControlListEntryTest.NeedsMoreInfoForGlVersionEntry", - arraysize(kFeatureListForEntry23), // features size - kFeatureListForEntry23, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry23), // features size + kFeatureListForEntry23, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -655,6 +699,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry23, // more data }, 0, // exceptions count @@ -663,14 +709,14 @@ { 24, // id "GpuControlListEntryTest.FeatureTypeAllEntry", - arraysize(kFeatureListForEntry24), // features size - kFeatureListForEntry24, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry24), // features size + kFeatureListForEntry24, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -683,6 +729,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -691,14 +739,14 @@ { 25, // id "GpuControlListEntryTest.FeatureTypeAllEntryWithExceptions", - arraysize(kFeatureListForEntry25), // features size - kFeatureListForEntry25, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry25), // features size + kFeatureListForEntry25, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -711,6 +759,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -719,26 +769,28 @@ { 26, // id "GpuControlListEntryTest.SingleActiveGPU", - arraysize(kFeatureListForEntry26), // features size - kFeatureListForEntry26, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry26), // features size + kFeatureListForEntry26, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x10de, // vendor_id - arraysize(kDeviceIDsForEntry26), // DeviceIDs size + base::size(kDeviceIDsForEntry26), // DeviceIDs size kDeviceIDsForEntry26, // DeviceIDs GpuControlList::kMultiGpuCategoryActive, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -747,14 +799,14 @@ { 27, // id "GpuControlListEntryTest.MachineModelName", - arraysize(kFeatureListForEntry27), // features size - kFeatureListForEntry27, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry27), // features size + kFeatureListForEntry27, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAndroid, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -767,6 +819,8 @@ nullptr, // driver info nullptr, // GL strings &kMachineModelInfoForEntry27, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -775,14 +829,14 @@ { 28, // id "GpuControlListEntryTest.MachineModelNameException", - arraysize(kFeatureListForEntry28), // features size - kFeatureListForEntry28, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry28), // features size + kFeatureListForEntry28, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -795,22 +849,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry28), // exceptions count - kExceptionsForEntry28, // exceptions + base::size(kExceptionsForEntry28), // exceptions count + kExceptionsForEntry28, // exceptions }, { 29, // id "GpuControlListEntryTest.MachineModelVersion", - arraysize(kFeatureListForEntry29), // features size - kFeatureListForEntry29, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry29), // features size + kFeatureListForEntry29, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -823,6 +879,8 @@ nullptr, // driver info nullptr, // GL strings &kMachineModelInfoForEntry29, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -831,14 +889,14 @@ { 30, // id "GpuControlListEntryTest.MachineModelVersionException", - arraysize(kFeatureListForEntry30), // features size - kFeatureListForEntry30, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry30), // features size + kFeatureListForEntry30, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -851,34 +909,38 @@ nullptr, // driver info nullptr, // GL strings &kMachineModelInfoForEntry30, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry30), // exceptions count - kExceptionsForEntry30, // exceptions + base::size(kExceptionsForEntry30), // exceptions count + kExceptionsForEntry30, // exceptions }, { 31, // id "GpuControlListEntryDualGPUTest.CategoryAny.Intel", - arraysize(kFeatureListForEntry31), // features size - kFeatureListForEntry31, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry31), // features size + kFeatureListForEntry31, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry31), // DeviceIDs size + base::size(kDeviceIDsForEntry31), // DeviceIDs size kDeviceIDsForEntry31, // DeviceIDs GpuControlList::kMultiGpuCategoryAny, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -887,26 +949,28 @@ { 32, // id "GpuControlListEntryDualGPUTest.CategoryAny.NVidia", - arraysize(kFeatureListForEntry32), // features size - kFeatureListForEntry32, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry32), // features size + kFeatureListForEntry32, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x10de, // vendor_id - arraysize(kDeviceIDsForEntry32), // DeviceIDs size + base::size(kDeviceIDsForEntry32), // DeviceIDs size kDeviceIDsForEntry32, // DeviceIDs GpuControlList::kMultiGpuCategoryAny, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -915,26 +979,28 @@ { 33, // id "GpuControlListEntryDualGPUTest.CategorySecondary", - arraysize(kFeatureListForEntry33), // features size - kFeatureListForEntry33, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry33), // features size + kFeatureListForEntry33, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry33), // DeviceIDs size + base::size(kDeviceIDsForEntry33), // DeviceIDs size kDeviceIDsForEntry33, // DeviceIDs GpuControlList::kMultiGpuCategorySecondary, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -943,26 +1009,28 @@ { 34, // id "GpuControlListEntryDualGPUTest.CategoryPrimary", - arraysize(kFeatureListForEntry34), // features size - kFeatureListForEntry34, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry34), // features size + kFeatureListForEntry34, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry34), // DeviceIDs size + base::size(kDeviceIDsForEntry34), // DeviceIDs size kDeviceIDsForEntry34, // DeviceIDs GpuControlList::kMultiGpuCategoryPrimary, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -971,26 +1039,28 @@ { 35, // id "GpuControlListEntryDualGPUTest.CategoryDefault", - arraysize(kFeatureListForEntry35), // features size - kFeatureListForEntry35, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry35), // features size + kFeatureListForEntry35, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry35), // DeviceIDs size + base::size(kDeviceIDsForEntry35), // DeviceIDs size kDeviceIDsForEntry35, // DeviceIDs GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -999,26 +1069,28 @@ { 36, // id "GpuControlListEntryDualGPUTest.ActiveSecondaryGPU", - arraysize(kFeatureListForEntry36), // features size - kFeatureListForEntry36, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry36), // features size + kFeatureListForEntry36, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry36), // DeviceIDs size + base::size(kDeviceIDsForEntry36), // DeviceIDs size kDeviceIDsForEntry36, // DeviceIDs GpuControlList::kMultiGpuCategoryActive, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1027,14 +1099,14 @@ { 37, // id "GpuControlListEntryDualGPUTest.VendorOnlyActiveSecondaryGPU", - arraysize(kFeatureListForEntry37), // features size - kFeatureListForEntry37, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry37), // features size + kFeatureListForEntry37, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1047,6 +1119,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1055,26 +1129,28 @@ { 38, // id "GpuControlListEntryDualGPUTest.ActivePrimaryGPU", - arraysize(kFeatureListForEntry38), // features size - kFeatureListForEntry38, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry38), // features size + kFeatureListForEntry38, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version 0x10de, // vendor_id - arraysize(kDeviceIDsForEntry38), // DeviceIDs size + base::size(kDeviceIDsForEntry38), // DeviceIDs size kDeviceIDsForEntry38, // DeviceIDs GpuControlList::kMultiGpuCategoryActive, // multi_gpu_category GpuControlList::kMultiGpuStyleNone, // multi_gpu_style nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1083,14 +1159,14 @@ { 39, // id "GpuControlListEntryDualGPUTest.VendorOnlyActivePrimaryGPU", - arraysize(kFeatureListForEntry39), // features size - kFeatureListForEntry39, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry39), // features size + kFeatureListForEntry39, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsMacosx, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1103,6 +1179,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1111,14 +1189,14 @@ { 40, // id "GpuControlListEntryTest.PixelShaderVersion", - arraysize(kFeatureListForEntry40), // features size - kFeatureListForEntry40, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry40), // features size + kFeatureListForEntry40, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1131,6 +1209,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry40, // more data }, 0, // exceptions count @@ -1139,14 +1219,14 @@ { 41, // id "GpuControlListEntryTest.OsVersionZeroLT", - arraysize(kFeatureListForEntry41), // features size - kFeatureListForEntry41, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry41), // features size + kFeatureListForEntry41, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAndroid, // os_type {GpuControlList::kLT, GpuControlList::kVersionStyleNumerical, "4.2", @@ -1159,6 +1239,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1167,14 +1249,14 @@ { 42, // id "GpuControlListEntryTest.OsVersionZeroAny", - arraysize(kFeatureListForEntry42), // features size - kFeatureListForEntry42, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry42), // features size + kFeatureListForEntry42, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAndroid, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1187,6 +1269,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1195,14 +1279,14 @@ { 43, // id "GpuControlListEntryTest.OsComparisonAny", - arraysize(kFeatureListForEntry43), // features size - kFeatureListForEntry43, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry43), // features size + kFeatureListForEntry43, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1215,6 +1299,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1223,14 +1309,14 @@ { 44, // id "GpuControlListEntryTest.OsComparisonGE", - arraysize(kFeatureListForEntry44), // features size - kFeatureListForEntry44, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry44), // features size + kFeatureListForEntry44, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsWin, // os_type {GpuControlList::kGE, GpuControlList::kVersionStyleNumerical, "6", @@ -1243,6 +1329,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1251,14 +1339,14 @@ { 45, // id "GpuControlListEntryTest.ExceptionWithoutVendorId", - arraysize(kFeatureListForEntry45), // features size - kFeatureListForEntry45, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry45), // features size + kFeatureListForEntry45, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1271,22 +1359,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry45), // exceptions count - kExceptionsForEntry45, // exceptions + base::size(kExceptionsForEntry45), // exceptions count + kExceptionsForEntry45, // exceptions }, { 46, // id "GpuControlListEntryTest.MultiGpuStyleAMDSwitchableDiscrete", - arraysize(kFeatureListForEntry46), // features size - kFeatureListForEntry46, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry46), // features size + kFeatureListForEntry46, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1300,6 +1390,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1308,14 +1400,14 @@ { 47, // id "GpuControlListEntryTest.MultiGpuStyleAMDSwitchableIntegrated", - arraysize(kFeatureListForEntry47), // features size - kFeatureListForEntry47, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry47), // features size + kFeatureListForEntry47, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1329,6 +1421,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1337,14 +1431,14 @@ { 48, // id "GpuControlListEntryTest.InProcessGPU", - arraysize(kFeatureListForEntry48), // features size - kFeatureListForEntry48, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry48), // features size + kFeatureListForEntry48, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsWin, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1357,6 +1451,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry48, // more data }, 0, // exceptions count @@ -1365,14 +1461,14 @@ { 49, // id "GpuControlListEntryTest.SameGPUTwiceTest", - arraysize(kFeatureListForEntry49), // features size - kFeatureListForEntry49, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry49), // features size + kFeatureListForEntry49, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsWin, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1385,6 +1481,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1393,14 +1491,14 @@ { 50, // id "GpuControlListEntryTest.NVidiaNumberingScheme", - arraysize(kFeatureListForEntry50), // features size - kFeatureListForEntry50, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry50), // features size + kFeatureListForEntry50, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsWin, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1413,6 +1511,8 @@ &kDriverInfoForEntry50, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1421,14 +1521,14 @@ { 51, // id "GpuControlListTest.NeedsMoreInfo", - arraysize(kFeatureListForEntry51), // features size - kFeatureListForEntry51, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry51), // features size + kFeatureListForEntry51, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsWin, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1441,6 +1541,8 @@ &kDriverInfoForEntry51, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1449,14 +1551,14 @@ { 52, // id "GpuControlListTest.NeedsMoreInfoForExceptions", - arraysize(kFeatureListForEntry52), // features size - kFeatureListForEntry52, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry52), // features size + kFeatureListForEntry52, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1469,22 +1571,24 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, - arraysize(kExceptionsForEntry52), // exceptions count - kExceptionsForEntry52, // exceptions + base::size(kExceptionsForEntry52), // exceptions count + kExceptionsForEntry52, // exceptions }, { 53, // id "GpuControlListTest.IgnorableEntries.0", - arraysize(kFeatureListForEntry53), // features size - kFeatureListForEntry53, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry53), // features size + kFeatureListForEntry53, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1497,6 +1601,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1505,14 +1611,14 @@ { 54, // id "GpuControlListTest.IgnorableEntries.1", - arraysize(kFeatureListForEntry54), // features size - kFeatureListForEntry54, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry54), // features size + kFeatureListForEntry54, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1525,6 +1631,8 @@ &kDriverInfoForEntry54, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1533,10 +1641,10 @@ { 55, // id "GpuControlListTest.DisabledExtensionTest.0", - 0, // feature size - nullptr, // features - arraysize(kDisabledExtensionsForEntry55), // DisabledExtensions size - kDisabledExtensionsForEntry55, // DisabledExtensions + 0, // feature size + nullptr, // features + base::size(kDisabledExtensionsForEntry55), // DisabledExtensions size + kDisabledExtensionsForEntry55, // DisabledExtensions 0, // DisabledWebGLExtensions size nullptr, // DisabledWebGLExtensions 0, // CrBugs size @@ -1553,6 +1661,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1561,10 +1671,10 @@ { 56, // id "GpuControlListTest.DisabledExtensionTest.1", - 0, // feature size - nullptr, // features - arraysize(kDisabledExtensionsForEntry56), // DisabledExtensions size - kDisabledExtensionsForEntry56, // DisabledExtensions + 0, // feature size + nullptr, // features + base::size(kDisabledExtensionsForEntry56), // DisabledExtensions size + kDisabledExtensionsForEntry56, // DisabledExtensions 0, // DisabledWebGLExtensions size nullptr, // DisabledWebGLExtensions 0, // CrBugs size @@ -1581,6 +1691,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1589,14 +1701,14 @@ { 57, // id "GpuControlListEntryTest.DirectRendering", - arraysize(kFeatureListForEntry57), // features size - kFeatureListForEntry57, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry57), // features size + kFeatureListForEntry57, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1609,6 +1721,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry57, // more data }, 0, // exceptions count @@ -1617,14 +1731,14 @@ { 58, // id "GpuControlListTest.LinuxKernelVersion", - arraysize(kFeatureListForEntry58), // features size - kFeatureListForEntry58, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry58), // features size + kFeatureListForEntry58, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsLinux, // os_type {GpuControlList::kLT, GpuControlList::kVersionStyleNumerical, @@ -1637,6 +1751,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, 0, // exceptions count @@ -1645,14 +1761,14 @@ { 59, // id "GpuControlListTest.TestGroup.0", - arraysize(kFeatureListForEntry59), // features size - kFeatureListForEntry59, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry59), // features size + kFeatureListForEntry59, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1665,6 +1781,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry59, // more data }, 0, // exceptions count @@ -1673,14 +1791,14 @@ { 60, // id "GpuControlListTest.TestGroup.1", - arraysize(kFeatureListForEntry60), // features size - kFeatureListForEntry60, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // DisabledWebGLExtensions size - nullptr, // DisabledWebGLExtensions - 0, // CrBugs size - nullptr, // CrBugs + base::size(kFeatureListForEntry60), // features size + kFeatureListForEntry60, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -1693,11 +1811,193 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series &kMoreForEntry60, // more data }, 0, // exceptions count nullptr, // exceptions }, + { + 61, // id + "GpuControlListEntryTest.GpuSeries", + base::size(kFeatureListForEntry61), // features size + kFeatureListForEntry61, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + base::size(kGpuSeriesForEntry61), // gpu_series size + kGpuSeriesForEntry61, // gpu_series + nullptr, // more conditions + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 62, // id + "GpuControlListEntryTest.GpuSeriesActive", + base::size(kFeatureListForEntry62), // features size + kFeatureListForEntry62, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryActive, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + base::size(kGpuSeriesForEntry62), // gpu_series size + kGpuSeriesForEntry62, // gpu_series + nullptr, // more conditions + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 63, // id + "GpuControlListEntryTest.GpuSeriesAny", + base::size(kFeatureListForEntry63), // features size + kFeatureListForEntry63, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryAny, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + base::size(kGpuSeriesForEntry63), // gpu_series size + kGpuSeriesForEntry63, // gpu_series + nullptr, // more conditions + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 64, // id + "GpuControlListEntryTest.GpuSeriesPrimary", + base::size(kFeatureListForEntry64), // features size + kFeatureListForEntry64, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryPrimary, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + base::size(kGpuSeriesForEntry64), // gpu_series size + kGpuSeriesForEntry64, // gpu_series + nullptr, // more conditions + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 65, // id + "GpuControlListEntryTest.GpuSeriesSecondary", + base::size(kFeatureListForEntry65), // features size + kFeatureListForEntry65, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategorySecondary, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + base::size(kGpuSeriesForEntry65), // gpu_series size + kGpuSeriesForEntry65, // gpu_series + nullptr, // more conditions + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 66, // id + "GpuControlListEntryTest.GpuSeriesInException", + base::size(kFeatureListForEntry66), // features size + kFeatureListForEntry66, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series + nullptr, // more conditions + }, + base::size(kExceptionsForEntry66), // exceptions count + kExceptionsForEntry66, // exceptions + }, }; -const size_t kGpuControlListTestingEntryCount = 60; +const size_t kGpuControlListTestingEntryCount = 66; } // namespace gpu
diff --git a/gpu/config/gpu_control_list_testing_entry_enums_autogen.h b/gpu/config/gpu_control_list_testing_entry_enums_autogen.h index a6af543b..3af233e 100644 --- a/gpu/config/gpu_control_list_testing_entry_enums_autogen.h +++ b/gpu/config/gpu_control_list_testing_entry_enums_autogen.h
@@ -73,6 +73,12 @@ kGpuControlListTest_LinuxKernelVersion = 57, kGpuControlListTest_TestGroup_0 = 58, kGpuControlListTest_TestGroup_1 = 59, + kGpuControlListEntryTest_GpuSeries = 60, + kGpuControlListEntryTest_GpuSeriesActive = 61, + kGpuControlListEntryTest_GpuSeriesAny = 62, + kGpuControlListEntryTest_GpuSeriesPrimary = 63, + kGpuControlListEntryTest_GpuSeriesSecondary = 64, + kGpuControlListEntryTest_GpuSeriesInException = 65, }; } // namespace gpu
diff --git a/gpu/config/gpu_control_list_testing_exceptions_autogen.h b/gpu/config/gpu_control_list_testing_exceptions_autogen.h index b1590ae..76c9089 100644 --- a/gpu/config/gpu_control_list_testing_exceptions_autogen.h +++ b/gpu/config/gpu_control_list_testing_exceptions_autogen.h
@@ -25,6 +25,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, }; @@ -42,6 +44,8 @@ nullptr, // driver info nullptr, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, }; @@ -59,6 +63,8 @@ nullptr, // driver info &kGLStringsForEntry22Exception0, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, }; @@ -76,6 +82,8 @@ nullptr, // driver info nullptr, // GL strings &kMachineModelInfoForEntry28Exception0, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, }; @@ -93,6 +101,8 @@ nullptr, // driver info nullptr, // GL strings &kMachineModelInfoForEntry30Exception0, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, }; @@ -101,30 +111,34 @@ { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version - 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry45Exception0), // DeviceIDs size - kDeviceIDsForEntry45Exception0, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - &kDriverInfoForEntry45Exception0, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions + nullptr, nullptr}, // os_version + 0x8086, // vendor_id + base::size(kDeviceIDsForEntry45Exception0), // DeviceIDs size + kDeviceIDsForEntry45Exception0, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + &kDriverInfoForEntry45Exception0, // driver info + nullptr, // GL strings + nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series + nullptr, // more conditions }, { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version - 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry45Exception1), // DeviceIDs size - kDeviceIDsForEntry45Exception1, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - &kDriverInfoForEntry45Exception1, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions + nullptr, nullptr}, // os_version + 0x8086, // vendor_id + base::size(kDeviceIDsForEntry45Exception1), // DeviceIDs size + kDeviceIDsForEntry45Exception1, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + &kDriverInfoForEntry45Exception1, // driver info + nullptr, // GL strings + nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series + nullptr, // more conditions }, }; @@ -141,10 +155,31 @@ nullptr, // driver info &kGLStringsForEntry52Exception0, // GL strings nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series nullptr, // more conditions }, }; +const GpuControlList::Conditions kExceptionsForEntry66[1] = { + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + nullptr, // driver info + nullptr, // GL strings + nullptr, // machine model info + base::size(kGpuSeriesForEntry66Exception0), // gpu_series size + kGpuSeriesForEntry66Exception0, // gpu_series + nullptr, // more conditions + }, +}; + } // namespace gpu #endif // GPU_CONFIG_GPU_CONTROL_LIST_TESTING_EXCEPTIONS_AUTOGEN_H_
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 1d3404c..a77c984b 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -1935,12 +1935,8 @@ "value": "10.13.2" } }, - "vendor_id": "0x8086", - "device_id" : [ - "0x1902", "0x1906", "0x190A", "0x190B", "0x190E", "0x1912", "0x1913", "0x1915", - "0x1916", "0x1917", "0x191A", "0x191B", "0x191D", "0x191E", "0x1921", "0x1923", - "0x1926", "0x1927", "0x192A", "0x192B", "0x192D", "0x1932", "0x193A", "0x193B", - "0x193D" + "gpu_series" : [ + "intel_skylake" ], "features" : [ "emulate_isnan_on_float" @@ -2367,17 +2363,11 @@ "os": { "type": "win" }, - "vendor_id": "0x8086", - "device_id": ["0x1602", "0x1606", "0x160a", "0x160b", "0x160d", - "0x160e", "0x1612", "0x1616", "0x161a", "0x161b", - "0x161d", "0x161e", "0x1622", "0x1626", "0x162a", - "0x162b", "0x162d", "0x162e", "0x22b0", "0x22b1", - "0x22b2", "0x22b3", "0x1902", "0x1906", "0x190a", - "0x190b", "0x190e", "0x1912", "0x1913", "0x1915", - "0x1916", "0x1917", "0x191a", "0x191b", "0x191d", - "0x191e", "0x1921", "0x1923", "0x1926", "0x1927", - "0x192a", "0x192b", "0x192d", "0x1932", "0x193a", - "0x193b", "0x193d"], + "gpu_series": [ + "intel_broadwell", + "intel_skylake", + "intel_cherryview" + ], "features": [ "disable_accelerated_vpx_decode" ] @@ -2608,10 +2598,11 @@ "os": { "type": "macosx" }, - "vendor_id": "0x8086", - "device_id": ["0x1927", "0x1926", "0x191e", "0x1916", "0x1912", "0x1912", - "0x191b", "0x193b", "0x591e", "0x5926", "0x5927", "0x5912", - "0x5916", "0x591b", "0x3e92"], + "gpu_series": [ + "intel_skylake", + "intel_kabylake", + "intel_coffeelake" + ], "multi_gpu_category": "any", "features": [ "flush_on_framebuffer_change"
diff --git a/gpu/config/process_json.py b/gpu/config/process_json.py index 8465760..de09c6b 100755 --- a/gpu/config/process_json.py +++ b/gpu/config/process_json.py
@@ -139,7 +139,7 @@ data_helper_file.write(',\n') data_helper_file.write('};\n\n') # use the list - data_file.write('arraysize(%s), // %s size\n' % (var_name, entry_kind)) + data_file.write('base::size(%s), // %s size\n' % (var_name, entry_kind)) data_file.write('%s, // %s\n' % (var_name, entry_kind)) else: data_file.write('0, // %s size\n' % entry_kind) @@ -233,7 +233,7 @@ data_helper_file.write(',\n') data_helper_file.write('};\n\n') # reference the list - data_file.write('arraysize(%s), // %s size\n' % (var_name, name_tag)) + data_file.write('base::size(%s), // %s size\n' % (var_name, name_tag)) data_file.write('%s, // %s\n' % (var_name, name_tag)) else: data_file.write('0, // %s size\n' % name_tag) @@ -281,7 +281,7 @@ data_helper_file.write( 'const GpuControlList::MachineModelInfo %s = {\n' % var_name) if machine_model_name: - data_helper_file.write('arraysize(%s), // machine model name size\n' % + data_helper_file.write('base::size(%s), // machine model name size\n' % model_name_var_name) data_helper_file.write('%s, // machine model names\n' % model_name_var_name) @@ -349,6 +349,7 @@ device_id = None multi_gpu_category = '' multi_gpu_style = '' + gpu_series_list = None driver_vendor = '' driver_version = None driver_date = None @@ -406,6 +407,8 @@ multi_gpu_category = entry[key] elif key == 'multi_gpu_style': multi_gpu_style = entry[key] + elif key == 'gpu_series': + gpu_series_list = entry[key] elif key == 'driver_vendor': driver_vendor = entry[key] elif key == 'driver_version': @@ -474,6 +477,8 @@ write_machine_model_info(entry_id, is_exception, exception_id, machine_model_name, machine_model_version, data_file, data_helper_file) + write_gpu_series_list(entry_id, is_exception, exception_id, gpu_series_list, + data_file, data_helper_file) # group a bunch of less used conditions if (gl_version != None or pixel_shader_version != None or in_process_gpu or gl_reset_notification_strategy != None or (not direct_rendering) or @@ -486,6 +491,40 @@ data_file.write('nullptr, // more conditions\n') +def write_gpu_series_list(entry_id, is_exception, exception_id, gpu_series_list, + data_file, data_helper_file): + if gpu_series_list: + var_name = 'kGpuSeriesForEntry' + str(entry_id) + if is_exception: + var_name += 'Exception' + str(exception_id) + data_helper_file.write('const GpuControlList::GpuSeriesType %s[%d] = {\n' % + (var_name, len(gpu_series_list))) + gpu_series_map = { + 'intel_sandybridge': 'kIntelSandyBridge', + 'intel_valleyview': 'kIntelValleyView', + 'intel_ivybridge': 'kIntelIvyBridge', + 'intel_haswell': 'kIntelHaswell', + 'intel_cherryview': 'kIntelCherryView', + 'intel_broadwell': 'kIntelBroadwell', + 'intel_apollolake': 'kIntelApolloLake', + 'intel_skylake': 'kIntelSkyLake', + 'intel_geminilake': 'kIntelGeminiLake', + 'intel_kabylake': 'kIntelKabyLake', + 'intel_coffeelake': 'kIntelCoffeeLake', + } + for series in gpu_series_list: + assert gpu_series_map.has_key(series) + data_helper_file.write('GpuControlList::GpuSeriesType::%s,\n' % + gpu_series_map[series]) + data_helper_file.write('};\n\n') + + data_file.write('base::size(%s), // gpu_series size\n' % var_name) + data_file.write('%s, // gpu_series\n' % var_name) + else: + data_file.write('0, // gpu_series size\n') + data_file.write('nullptr, // gpu_series\n') + + def write_entry_more_data(entry_id, is_exception, exception_id, gl_type, gl_version, pixel_shader_version, in_process_gpu, gl_reset_notification_strategy, direct_rendering, @@ -522,7 +561,7 @@ if 'features' in entry: features = entry['features'] feature_set = get_feature_set(features, total_feature_set) - data_file.write('arraysize(kFeatureListForEntry%d), // features size\n' % + data_file.write('base::size(kFeatureListForEntry%d), // features size\n' % entry_id) data_file.write('kFeatureListForEntry%d, // features\n' % entry_id) write_features(entry_id, feature_set, feature_name_prefix, data_helper_file) @@ -566,7 +605,7 @@ data_exception_file, data_helper_file, None) data_exception_file.write('},\n') data_exception_file.write('};\n\n') - data_file.write('arraysize(%s), // exceptions count\n' % exception_var) + data_file.write('base::size(%s), // exceptions count\n' % exception_var) data_file.write('%s, // exceptions\n' % exception_var) else: data_file.write('0, // exceptions count\n')
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json index b608b38..c24085a6 100644 --- a/gpu/config/software_rendering_list.json +++ b/gpu/config/software_rendering_list.json
@@ -920,10 +920,9 @@ "value": "3.19.1" } }, - "vendor_id": "0x8086", - "device_id": ["0x0402", "0x0406", "0x040a", "0x040b", "0x040e", - "0x0a02", "0x0a06", "0x0a0a", "0x0a0b", "0x0a0e", - "0x0d02", "0x0d06", "0x0d0a", "0x0d0b", "0x0d0e"], + "gpu_series": [ + "intel_haswell" + ], "features": [ "all" ]
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.cc b/gpu/ipc/service/direct_composition_child_surface_win.cc index 97dd4e4..1a2ceaf 100644 --- a/gpu/ipc/service/direct_composition_child_surface_win.cc +++ b/gpu/ipc/service/direct_composition_child_surface_win.cc
@@ -71,22 +71,32 @@ pbuffer_attribs.push_back(EGL_NONE); default_surface_ = eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); - CHECK(!!default_surface_); + if (!default_surface_) { + DLOG(ERROR) << "eglCreatePbufferSurface failed with error " + << ui::GetLastEGLErrorString(); + // It is likely that restoring the context will fail, so call Restore here + // to avoid the assert during ScopedReleaseCurrent destruction. + ignore_result(release_current.Restore()); + return false; + } - return release_current.Restore(); -} + if (!release_current.Restore()) { + DLOG(ERROR) << "Failed to restore context with error " + << ui::GetLastEGLErrorString(); + return false; + } -void DirectCompositionChildSurfaceWin::ReleaseCurrentSurface() { - ReleaseDrawTexture(true); - dcomp_surface_.Reset(); - swap_chain_.Reset(); + return true; } bool DirectCompositionChildSurfaceWin::InitializeSurface() { TRACE_EVENT1("gpu", "DirectCompositionChildSurfaceWin::InitializeSurface()", "enable_dc_layers_", enable_dc_layers_); - DCHECK(!dcomp_surface_); - DCHECK(!swap_chain_); + if (!ReleaseDrawTexture(true /* will_discard */)) + return false; + dcomp_surface_.Reset(); + swap_chain_.Reset(); + DXGI_FORMAT output_format = is_hdr_ ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_B8G8R8A8_UNORM; if (enable_dc_layers_) { @@ -96,16 +106,22 @@ size_.width(), size_.height(), output_format, DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.GetAddressOf()); has_been_rendered_to_ = false; - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateSurface failed with error " << std::hex << hr; + return false; + } } else { DXGI_ALPHA_MODE alpha_mode = has_alpha_ ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device; d3d11_device_.CopyTo(dxgi_device.GetAddressOf()); + DCHECK(dxgi_device); Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter; dxgi_device->GetAdapter(dxgi_adapter.GetAddressOf()); + DCHECK(dxgi_adapter); Microsoft::WRL::ComPtr<IDXGIFactory2> dxgi_factory; dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); + DCHECK(dxgi_factory); DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Width = size_.width(); @@ -123,47 +139,63 @@ d3d11_device_.Get(), &desc, nullptr, swap_chain_.GetAddressOf()); has_been_rendered_to_ = false; first_swap_ = true; - return SUCCEEDED(hr); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateSwapChainForComposition failed with error " + << std::hex << hr; + return false; + } } return true; } -void DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) { +bool DirectCompositionChildSurfaceWin::ReleaseDrawTexture(bool will_discard) { DCHECK(!gl::GLContext::GetCurrent()); if (real_surface_) { eglDestroySurface(GetDisplay(), real_surface_); real_surface_ = nullptr; } + + if (dcomp_surface_.Get() == g_current_surface) + g_current_surface = nullptr; + if (draw_texture_) { draw_texture_.Reset(); if (dcomp_surface_) { HRESULT hr = dcomp_surface_->EndDraw(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "EndDraw failed with error " << std::hex << hr; + return false; + } dcomp_surface_serial_++; } else if (!will_discard) { DXGI_PRESENT_PARAMETERS params = {}; RECT dirty_rect = swap_rect_.ToRECT(); params.DirtyRectsCount = 1; params.pDirtyRects = &dirty_rect; - swap_chain_->Present1(vsync_enabled_ && !first_swap_ ? 1 : 0, 0, ¶ms); + HRESULT hr = swap_chain_->Present1(vsync_enabled_ && !first_swap_ ? 1 : 0, + 0, ¶ms); + if (FAILED(hr)) { + DLOG(ERROR) << "Present1 failed with error " << std::hex << hr; + return false; + } if (first_swap_) { // Wait for the GPU to finish executing its commands before // committing the DirectComposition tree, or else the swapchain // may flicker black when it's first presented. + first_swap_ = false; Microsoft::WRL::ComPtr<IDXGIDevice2> dxgi_device2; - HRESULT hr = d3d11_device_.CopyTo(dxgi_device2.GetAddressOf()); - DCHECK(SUCCEEDED(hr)); + d3d11_device_.CopyTo(dxgi_device2.GetAddressOf()); + DCHECK(dxgi_device2); base::WaitableEvent event( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - dxgi_device2->EnqueueSetEvent(event.handle()); + hr = dxgi_device2->EnqueueSetEvent(event.handle()); + DCHECK(SUCCEEDED(hr)); event.Wait(); - first_swap_ = false; } } } - if (dcomp_surface_.Get() == g_current_surface) - g_current_surface = nullptr; + return true; } void DirectCompositionChildSurfaceWin::Destroy() { @@ -183,7 +215,8 @@ } if (dcomp_surface_ && (dcomp_surface_.Get() == g_current_surface)) { HRESULT hr = dcomp_surface_->EndDraw(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) + DLOG(ERROR) << "EndDraw failed with error " << std::hex << hr; g_current_surface = nullptr; } draw_texture_.Reset(); @@ -207,7 +240,8 @@ // PresentationCallback is handled by DirectCompositionSurfaceWin. The child // surface doesn't need provide presentation feedback. DCHECK(!callback); - ReleaseDrawTexture(false); + if (!ReleaseDrawTexture(false /* will_discard */)) + return gfx::SwapResult::SWAP_FAILED; return gfx::SwapResult::SWAP_ACK; } @@ -223,12 +257,18 @@ if (g_current_surface != dcomp_surface_.Get()) { if (g_current_surface) { HRESULT hr = g_current_surface->SuspendDraw(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "SuspendDraw failed with error " << std::hex << hr; + return false; + } g_current_surface = nullptr; } if (draw_texture_) { HRESULT hr = dcomp_surface_->ResumeDraw(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "ResumeDraw failed with error " << std::hex << hr; + return false; + } g_current_surface = dcomp_surface_.Get(); } } @@ -257,7 +297,6 @@ if ((enable_dc_layers_ && !dcomp_surface_) || (!enable_dc_layers_ && !swap_chain_)) { - ReleaseCurrentSurface(); if (!InitializeSurface()) { DLOG(ERROR) << "InitializeSurface failed"; // It is likely that restoring the context will fail, so call Restore here @@ -273,22 +312,25 @@ return false; } - CHECK(!g_current_surface); + DCHECK(!g_current_surface); - RECT rect = rectangle.ToRECT(); + swap_rect_ = rectangle; + draw_offset_ = gfx::Vector2d(); + if (dcomp_surface_) { POINT update_offset; + const RECT rect = rectangle.ToRECT(); HRESULT hr = dcomp_surface_->BeginDraw( &rect, IID_PPV_ARGS(draw_texture_.GetAddressOf()), &update_offset); - draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "BeginDraw failed with error " << std::hex << hr; + return false; + } + draw_offset_ = gfx::Point(update_offset) - rectangle.origin(); } else { - HRESULT hr = - swap_chain_->GetBuffer(0, IID_PPV_ARGS(draw_texture_.GetAddressOf())); - swap_rect_ = rectangle; - draw_offset_ = gfx::Vector2d(); - CHECK(SUCCEEDED(hr)); + swap_chain_->GetBuffer(0, IID_PPV_ARGS(draw_texture_.GetAddressOf())); } + DCHECK(draw_texture_); has_been_rendered_to_ = true; g_current_surface = dcomp_surface_.Get(); @@ -307,9 +349,18 @@ real_surface_ = eglCreatePbufferFromClientBuffer( GetDisplay(), EGL_D3D_TEXTURE_ANGLE, buffer, GetConfig(), &pbuffer_attribs[0]); + if (!real_surface_) { + DLOG(ERROR) << "eglCreatePbufferFromClientBuffer failed with error " + << ui::GetLastEGLErrorString(); + // It is likely that restoring the context will fail, so call Restore here + // to avoid the assert during ScopedReleaseCurrent destruction. + ignore_result(release_current.Restore()); + return false; + } if (!release_current.Restore()) { - DLOG(ERROR) << "Failed to restore context"; + DLOG(ERROR) << "Failed to restore context with error " + << ui::GetLastEGLErrorString(); return false; }
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.h b/gpu/ipc/service/direct_composition_child_surface_win.h index b4ec2fb..c9b6ee1 100644 --- a/gpu/ipc/service/direct_composition_child_surface_win.h +++ b/gpu/ipc/service/direct_composition_child_surface_win.h
@@ -53,12 +53,13 @@ ~DirectCompositionChildSurfaceWin() override; private: - void ReleaseCurrentSurface(); + // Releases previous surface or swap chain, and initializes new surface or + // swap chain. bool InitializeSurface(); // Release the texture that's currently being drawn to. If will_discard is // true then the surface should be discarded without swapping any contents - // to it. - void ReleaseDrawTexture(bool will_discard); + // to it. Returns false if this fails. + bool ReleaseDrawTexture(bool will_discard); // This is a placeholder surface used when not rendering to the // DirectComposition surface.
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index 5f412ead..4d7d9d3 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -84,6 +84,26 @@ DISALLOW_COPY_AND_ASSIGN(PresentationHistory); }; +class ScopedReleaseKeyedMutex { + public: + ScopedReleaseKeyedMutex(Microsoft::WRL::ComPtr<IDXGIKeyedMutex> keyed_mutex, + UINT64 key) + : keyed_mutex_(keyed_mutex), key_(key) { + DCHECK(keyed_mutex); + } + + ~ScopedReleaseKeyedMutex() { + HRESULT hr = keyed_mutex_->ReleaseSync(key_); + DCHECK(SUCCEEDED(hr)); + } + + private: + Microsoft::WRL::ComPtr<IDXGIKeyedMutex> keyed_mutex_; + UINT64 key_ = 0; + + DISALLOW_COPY_AND_ASSIGN(ScopedReleaseKeyedMutex); +}; + gfx::Size g_overlay_monitor_size; bool g_supports_scaled_overlays = true; @@ -107,31 +127,37 @@ Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE(); if (!d3d11_device) { - DLOG(ERROR) << "Failing to create overlay swapchain because couldn't " - "retrieve D3D11 device from ANGLE."; + DLOG(ERROR) << "Not using overlays because failed to retrieve D3D11 device " + "from ANGLE"; return false; } + // This can fail if the D3D device is "Microsoft Basic Display Adapter". Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device; if (FAILED(d3d11_device.CopyTo(video_device.GetAddressOf()))) { - DLOG(ERROR) << "Failing to create overlay swapchain because couldn't " - "retrieve video device from D3D11 device."; + DLOG(ERROR) << "Not using overlays because failed to retrieve video device " + "from D3D11 device"; return false; } + DCHECK(video_device); Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device; d3d11_device.CopyTo(dxgi_device.GetAddressOf()); + DCHECK(dxgi_device); Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter; dxgi_device->GetAdapter(dxgi_adapter.GetAddressOf()); + DCHECK(dxgi_adapter); unsigned int i = 0; while (true) { Microsoft::WRL::ComPtr<IDXGIOutput> output; if (FAILED(dxgi_adapter->EnumOutputs(i++, output.GetAddressOf()))) break; + DCHECK(output); Microsoft::WRL::ComPtr<IDXGIOutput3> output3; if (FAILED(output.CopyTo(output3.GetAddressOf()))) continue; + DCHECK(output3); UINT flags = 0; if (FAILED(output3->CheckOverlaySupport(DXGI_FORMAT_YUY2, @@ -174,7 +200,7 @@ bool Initialize(HWND window); bool CommitAndClearPendingOverlays(); bool ScheduleDCLayer(const ui::DCRendererLayerParams& params); - void InitializeVideoProcessor(const gfx::Size& input_size, + bool InitializeVideoProcessor(const gfx::Size& input_size, const gfx::Size& output_size); const Microsoft::WRL::ComPtr<ID3D11VideoProcessor>& video_processor() const { @@ -217,7 +243,8 @@ // These functions return true if the visual tree was changed. bool InitVisual(size_t i); bool UpdateVisualForVideo(VisualInfo* visual_info, - const ui::DCRendererLayerParams& params); + const ui::DCRendererLayerParams& params, + bool* present_failed); bool UpdateVisualForBackbuffer(VisualInfo* visual_info, const ui::DCRendererLayerParams& params); bool UpdateVisualClip(VisualInfo* visual_info, @@ -255,11 +282,12 @@ class DCLayerTree::SwapChainPresenter { public: SwapChainPresenter(DCLayerTree* surface, - Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device); - + Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device, + Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, + Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context); ~SwapChainPresenter(); - void PresentToSwapChain(const ui::DCRendererLayerParams& overlay, + bool PresentToSwapChain(const ui::DCRendererLayerParams& overlay, const gfx::Size& video_input_size, const gfx::Size& swap_chain_size); @@ -276,7 +304,7 @@ // Returns true if the video processor changed. bool InitializeVideoProcessor(const gfx::Size& in_size, const gfx::Size& out_size); - void ReallocateSwapChain(bool yuy2); + bool ReallocateSwapChain(bool yuy2); bool ShouldBeYUY2(); DCLayerTree* surface_; @@ -312,37 +340,42 @@ }; bool DCLayerTree::Initialize(HWND window) { - HRESULT hr = d3d11_device_.CopyTo(video_device_.GetAddressOf()); - if (FAILED(hr)) + // This can fail if the D3D device is "Microsoft Basic Display Adapter". + if (FAILED(d3d11_device_.CopyTo(video_device_.GetAddressOf()))) { + DLOG(ERROR) << "Failed to retrieve video device from D3D11 device"; return false; + } + DCHECK(video_device_); Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; d3d11_device_->GetImmediateContext(context.GetAddressOf()); - hr = context.CopyTo(video_context_.GetAddressOf()); - if (FAILED(hr)) - return false; + DCHECK(context); + context.CopyTo(video_context_.GetAddressOf()); + DCHECK(video_context_); Microsoft::WRL::ComPtr<IDCompositionDesktopDevice> desktop_device; dcomp_device_.CopyTo(desktop_device.GetAddressOf()); + DCHECK(desktop_device); - hr = desktop_device->CreateTargetForHwnd(window, TRUE, - dcomp_target_.GetAddressOf()); - if (FAILED(hr)) + HRESULT hr = desktop_device->CreateTargetForHwnd( + window, TRUE, dcomp_target_.GetAddressOf()); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateTargetForHwnd failed with error " << std::hex << hr; return false; + } - hr = dcomp_device_->CreateVisual(root_visual_.GetAddressOf()); - if (FAILED(hr)) - return false; - + dcomp_device_->CreateVisual(root_visual_.GetAddressOf()); + DCHECK(root_visual_); dcomp_target_->SetRoot(root_visual_.Get()); + return true; } -void DCLayerTree::InitializeVideoProcessor(const gfx::Size& input_size, +bool DCLayerTree::InitializeVideoProcessor(const gfx::Size& input_size, const gfx::Size& output_size) { - if (SizeContains(video_input_size_, input_size) && + if (video_processor_ && SizeContains(video_input_size_, input_size) && SizeContains(video_output_size_, output_size)) - return; + return true; video_input_size_ = input_size; video_output_size_ = output_size; @@ -361,15 +394,23 @@ desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL; HRESULT hr = video_device_->CreateVideoProcessorEnumerator( &desc, video_processor_enumerator_.GetAddressOf()); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateVideoProcessorEnumerator failed with error " + << std::hex << hr; + return false; + } hr = video_device_->CreateVideoProcessor(video_processor_enumerator_.Get(), 0, video_processor_.GetAddressOf()); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateVideoProcessor failed with error " << std::hex << hr; + return false; + } // Auto stream processing (the default) can hurt power consumption. video_context_->VideoProcessorSetStreamAutoProcessingMode( video_processor_.Get(), 0, FALSE); + return true; } Microsoft::WRL::ComPtr<IDXGISwapChain1> @@ -381,19 +422,18 @@ DCLayerTree::SwapChainPresenter::SwapChainPresenter( DCLayerTree* surface, - Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device) - : surface_(surface), d3d11_device_(d3d11_device) { - HRESULT hr = d3d11_device_.CopyTo(video_device_.GetAddressOf()); - CHECK(SUCCEEDED(hr)); - Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; - d3d11_device_->GetImmediateContext(context.GetAddressOf()); - hr = context.CopyTo(video_context_.GetAddressOf()); - CHECK(SUCCEEDED(hr)); + Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device, + Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, + Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context) + : surface_(surface), + d3d11_device_(d3d11_device), + video_device_(video_device), + video_context_(video_context) { HMODULE dcomp = ::GetModuleHandleA("dcomp.dll"); CHECK(dcomp); create_surface_handle_function_ = reinterpret_cast<PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE>( - GetProcAddress(dcomp, "DCompositionCreateSurfaceHandle")); + ::GetProcAddress(dcomp, "DCompositionCreateSurfaceHandle")); CHECK(create_surface_handle_function_); } @@ -427,7 +467,7 @@ uv_image_size.width() != texture_size.width() / 2 || y_image_memory->format() != gfx::BufferFormat::R_8 || uv_image_memory->format() != gfx::BufferFormat::RG_88) { - DVLOG(ERROR) << "Invalid NV12 GLImageMemory properties."; + DLOG(ERROR) << "Invalid NV12 GLImageMemory properties."; return false; } @@ -451,17 +491,25 @@ Microsoft::WRL::ComPtr<ID3D11Texture2D> texture; HRESULT hr = d3d11_device_->CreateTexture2D( &desc, nullptr, staging_texture_.GetAddressOf()); - CHECK(SUCCEEDED(hr)) << "Creating D3D11 video upload texture failed: " - << std::hex << hr; + if (FAILED(hr)) { + DLOG(ERROR) << "Creating D3D11 video upload texture failed: " << std::hex + << hr; + return false; + } + DCHECK(staging_texture_); staging_texture_size_ = texture_size; } Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; d3d11_device_->GetImmediateContext(context.GetAddressOf()); + DCHECK(context); D3D11_MAPPED_SUBRESOURCE mapped_resource; HRESULT hr = context->Map(staging_texture_.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource); - CHECK(SUCCEEDED(hr)) << "Mapping D3D11 video upload texture failed: " - << std::hex << hr; + if (FAILED(hr)) { + DLOG(ERROR) << "Mapping D3D11 video upload texture failed: " << std::hex + << hr; + return false; + } size_t dest_stride = mapped_resource.RowPitch; for (int y = 0; y < texture_size.height(); y++) { @@ -485,7 +533,7 @@ return true; } -void DCLayerTree::SwapChainPresenter::PresentToSwapChain( +bool DCLayerTree::SwapChainPresenter::PresentToSwapChain( const ui::DCRendererLayerParams& params, const gfx::Size& video_input_size, const gfx::Size& swap_chain_size) { @@ -501,10 +549,11 @@ if (!image_dxgi && (!y_image_memory || !uv_image_memory)) { DLOG(ERROR) << "Video GLImages are missing"; last_gl_images_.clear(); - return; + return false; } - InitializeVideoProcessor(video_input_size, swap_chain_size); + if (!InitializeVideoProcessor(video_input_size, swap_chain_size)) + return false; bool yuy2_swapchain = ShouldBeYUY2(); bool first_present = false; @@ -513,13 +562,12 @@ !failed_to_create_yuy2_swapchain_)) { first_present = true; swap_chain_size_ = swap_chain_size; - swap_chain_.Reset(); ReallocateSwapChain(yuy2_swapchain); } else if (last_gl_images_ == params.image) { // The swap chain is presenting the same images as last swap, which means // that the images were never returned to the video decoder and should // have the same contents as last time. It shouldn't need to be redrawn. - return; + return true; } last_gl_images_ = params.image; @@ -530,8 +578,10 @@ if (image_dxgi) { input_texture = image_dxgi->texture(); input_level = (UINT)image_dxgi->level(); - if (!input_texture) - return; + if (!input_texture) { + DLOG(ERROR) << "Video image has no texture"; + return false; + } // Keyed mutex may not exist. keyed_mutex = image_dxgi->keyed_mutex(); staging_texture_.Reset(); @@ -539,7 +589,7 @@ DCHECK(y_image_memory); DCHECK(uv_image_memory); if (!UploadVideoImages(y_image_memory, uv_image_memory)) - return; + return false; DCHECK(staging_texture_); input_texture = staging_texture_; input_level = 0; @@ -554,7 +604,11 @@ HRESULT hr = video_device_->CreateVideoProcessorOutputView( texture.Get(), video_processor_enumerator_.Get(), &out_desc, out_view_.GetAddressOf()); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateVideoProcessorOutputView failed with error " + << std::hex << hr; + return false; + } } // TODO(jbauman): Use correct colorspace. @@ -564,6 +618,7 @@ } Microsoft::WRL::ComPtr<ID3D11VideoContext1> context1; if (SUCCEEDED(video_context_.CopyTo(context1.GetAddressOf()))) { + DCHECK(context1); context1->VideoProcessorSetStreamColorSpace1( video_processor_.Get(), 0, gfx::ColorSpaceWin::GetDXGIColorSpace(src_color_space)); @@ -585,6 +640,7 @@ Microsoft::WRL::ComPtr<IDXGISwapChain3> swap_chain3; if (SUCCEEDED(swap_chain_.CopyTo(swap_chain3.GetAddressOf()))) { + DCHECK(swap_chain3); DXGI_COLOR_SPACE_TYPE color_space = gfx::ColorSpaceWin::GetDXGIColorSpace(output_color_space); if (is_yuy2_swapchain_) { @@ -632,6 +688,7 @@ } { + base::Optional<ScopedReleaseKeyedMutex> release_keyed_mutex; if (keyed_mutex) { // The producer may still be using this texture for a short period of // time, so wait long enough to hopefully avoid glitches. For example, @@ -642,9 +699,11 @@ HRESULT hr = keyed_mutex->AcquireSync(0, kMaxSyncTimeMs); if (FAILED(hr)) { DLOG(ERROR) << "Error acquiring keyed mutex: " << std::hex << hr; - return; + return false; } + release_keyed_mutex.emplace(keyed_mutex, 0); } + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; in_desc.Texture2D.ArraySlice = input_level; @@ -652,7 +711,11 @@ HRESULT hr = video_device_->CreateVideoProcessorInputView( input_texture.Get(), video_processor_enumerator_.Get(), &in_desc, in_view.GetAddressOf()); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateVideoProcessorInputView failed with error " + << std::hex << hr; + return false; + } D3D11_VIDEO_PROCESSOR_STREAM stream = {}; stream.Enable = true; @@ -672,15 +735,18 @@ hr = video_context_->VideoProcessorBlt(video_processor_.Get(), out_view_.Get(), 0, 1, &stream); - CHECK(SUCCEEDED(hr)); - if (keyed_mutex) { - HRESULT hr = keyed_mutex->ReleaseSync(0); - DCHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "VideoProcessorBlt failed with error " << std::hex << hr; + return false; } } if (first_present) { - swap_chain_->Present(0, 0); + HRESULT hr = swap_chain_->Present(0, 0); + if (FAILED(hr)) { + DLOG(ERROR) << "Present failed with error " << std::hex << hr; + return false; + } // DirectComposition can display black for a swapchain between the first // and second time it's presented to - maybe the first Present can get @@ -689,29 +755,34 @@ // first Present() after this needs to have SyncInterval > 0, or else the // workaround doesn't help. Microsoft::WRL::ComPtr<ID3D11Texture2D> dest_texture; - HRESULT hr = - swap_chain_->GetBuffer(0, IID_PPV_ARGS(dest_texture.GetAddressOf())); - DCHECK(SUCCEEDED(hr)); + swap_chain_->GetBuffer(0, IID_PPV_ARGS(dest_texture.GetAddressOf())); + DCHECK(dest_texture); Microsoft::WRL::ComPtr<ID3D11Texture2D> src_texture; hr = swap_chain_->GetBuffer(1, IID_PPV_ARGS(src_texture.GetAddressOf())); - DCHECK(SUCCEEDED(hr)); + DCHECK(src_texture); Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; d3d11_device_->GetImmediateContext(context.GetAddressOf()); + DCHECK(context); context->CopyResource(dest_texture.Get(), src_texture.Get()); // Additionally wait for the GPU to finish executing its commands, or // there still may be a black flicker when presenting expensive content // (e.g. 4k video). Microsoft::WRL::ComPtr<IDXGIDevice2> dxgi_device2; - hr = d3d11_device_.CopyTo(dxgi_device2.GetAddressOf()); - DCHECK(SUCCEEDED(hr)); + d3d11_device_.CopyTo(dxgi_device2.GetAddressOf()); + DCHECK(dxgi_device2); base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - dxgi_device2->EnqueueSetEvent(event.handle()); + hr = dxgi_device2->EnqueueSetEvent(event.handle()); + DCHECK(SUCCEEDED(hr)); event.Wait(); } - swap_chain_->Present(1, 0); + HRESULT hr = swap_chain_->Present(1, 0); + if (FAILED(hr)) { + DLOG(ERROR) << "Present failed with error " << std::hex << hr; + return false; + } UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", is_yuy2_swapchain_); @@ -719,6 +790,7 @@ Microsoft::WRL::ComPtr<IDXGISwapChainMedia> swap_chain_media; if (SUCCEEDED(swap_chain_.CopyTo(swap_chain_media.GetAddressOf()))) { + DCHECK(swap_chain_media); DXGI_FRAME_STATISTICS_MEDIA stats = {}; if (SUCCEEDED(swap_chain_media->GetFrameStatisticsMedia(&stats))) { base::UmaHistogramSparse("GPU.DirectComposition.CompositionMode", @@ -726,6 +798,7 @@ presentation_history_.AddSample(stats.CompositionMode); } } + return true; } bool DCLayerTree::SwapChainPresenter::InitializeVideoProcessor( @@ -733,10 +806,12 @@ const gfx::Size& out_size) { if (video_processor_ && SizeContains(processor_input_size_, in_size) && SizeContains(processor_output_size_, out_size)) - return false; + return true; processor_input_size_ = in_size; processor_output_size_ = out_size; - surface_->InitializeVideoProcessor(in_size, out_size); + + if (!surface_->InitializeVideoProcessor(in_size, out_size)) + return false; video_processor_enumerator_ = surface_->video_processor_enumerator(); video_processor_ = surface_->video_processor(); @@ -746,19 +821,21 @@ return true; } -void DCLayerTree::SwapChainPresenter::ReallocateSwapChain(bool yuy2) { +bool DCLayerTree::SwapChainPresenter::ReallocateSwapChain(bool yuy2) { TRACE_EVENT0("gpu", "DCLayerTree::SwapChainPresenter::ReallocateSwapChain"); - DCHECK(!swap_chain_); + swap_chain_.Reset(); + out_view_.Reset(); Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device; d3d11_device_.CopyTo(dxgi_device.GetAddressOf()); + DCHECK(dxgi_device); Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter; dxgi_device->GetAdapter(dxgi_adapter.GetAddressOf()); - Microsoft::WRL::ComPtr<IDXGIFactory2> dxgi_factory; - dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); - + DCHECK(dxgi_adapter); Microsoft::WRL::ComPtr<IDXGIFactoryMedia> media_factory; - dxgi_factory.CopyTo(media_factory.GetAddressOf()); + dxgi_adapter->GetParent(IID_PPV_ARGS(media_factory.GetAddressOf())); + DCHECK(media_factory); + DXGI_SWAP_CHAIN_DESC1 desc = {}; DCHECK(!swap_chain_size_.IsEmpty()); desc.Width = swap_chain_size_.width(); @@ -777,6 +854,11 @@ HANDLE handle; HRESULT hr = create_surface_handle_function_(COMPOSITIONOBJECT_ALL_ACCESS, nullptr, &handle); + if (FAILED(hr)) { + DLOG(ERROR) << "DCompositionCreateSurfaceHandle failed with error " + << std::hex << hr; + return false; + } swap_chain_handle_.Set(handle); if (is_yuy2_swapchain_ != yuy2) { @@ -796,21 +878,25 @@ swap_chain_.GetAddressOf()); is_yuy2_swapchain_ = SUCCEEDED(hr); failed_to_create_yuy2_swapchain_ = !is_yuy2_swapchain_; + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to create YUY2 swap chain with error " << std::hex + << hr << ". Falling back to BGRA"; + } } if (!is_yuy2_swapchain_) { - if (yuy2) { - DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr - << ". Falling back to BGRA"; - } desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.Flags = 0; hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( d3d11_device_.Get(), swap_chain_handle_.Get(), &desc, nullptr, swap_chain_.GetAddressOf()); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to create BGRA swap chain with error " << std::hex + << hr; + return false; + } } - out_view_.Reset(); + return true; } bool DCLayerTree::InitVisual(size_t i) { @@ -821,19 +907,21 @@ DCHECK(!visual_info->clip_visual); Microsoft::WRL::ComPtr<IDCompositionVisual2> visual; dcomp_device_->CreateVisual(visual_info->clip_visual.GetAddressOf()); + DCHECK(visual_info->clip_visual); dcomp_device_->CreateVisual(visual.GetAddressOf()); + DCHECK(visual); visual_info->content_visual = visual; visual_info->clip_visual->AddVisual(visual.Get(), FALSE, nullptr); - IDCompositionVisual2* last_visual = (i > 0) ? visual_info_[i - 1].clip_visual.Get() : nullptr; root_visual_->AddVisual(visual_info->clip_visual.Get(), TRUE, last_visual); return true; } -bool DCLayerTree::UpdateVisualForVideo( - VisualInfo* visual_info, - const ui::DCRendererLayerParams& params) { +bool DCLayerTree::UpdateVisualForVideo(VisualInfo* visual_info, + const ui::DCRendererLayerParams& params, + bool* present_failed) { + *present_failed = false; bool changed = false; // This visual's content was a DC surface, but now it'll be a swap chain. if (visual_info->surface) { @@ -855,21 +943,24 @@ if (swap_chain_size.IsEmpty()) { // This visual's content was a swap chain, but now it'll be empty. if (visual_info->swap_chain) { - changed = true; visual_info->swap_chain.Reset(); visual_info->swap_chain_presenter.reset(); dc_visual->SetContent(nullptr); + changed = true; } return changed; } if (!visual_info->swap_chain_presenter) { - visual_info->swap_chain_presenter = - std::make_unique<SwapChainPresenter>(this, d3d11_device_); + visual_info->swap_chain_presenter = std::make_unique<SwapChainPresenter>( + this, d3d11_device_, video_device_, video_context_); } - visual_info->swap_chain_presenter->PresentToSwapChain( - params, video_input_size, swap_chain_size); + if (!visual_info->swap_chain_presenter->PresentToSwapChain( + params, video_input_size, swap_chain_size)) { + *present_failed = true; + return changed; + } // This visual's content was a different swap chain. if (visual_info->swap_chain != @@ -906,6 +997,7 @@ dc_visual->SetOffsetY(bounds_rect.y()); Microsoft::WRL::ComPtr<IDCompositionMatrixTransform> dcomp_transform; dcomp_device_->CreateMatrixTransform(dcomp_transform.GetAddressOf()); + DCHECK(dcomp_transform); D2D_MATRIX_3X2_F d2d_matrix = {{{final_transform.matrix().get(0, 0), final_transform.matrix().get(0, 1), final_transform.matrix().get(1, 0), @@ -1025,6 +1117,7 @@ if (params.is_clipped) { Microsoft::WRL::ComPtr<IDCompositionRectangleClip> clip; dcomp_device_->CreateRectangleClip(clip.GetAddressOf()); + DCHECK(clip); gfx::Rect offset_clip = params.clip_rect; clip->SetLeft(offset_clip.x()); clip->SetRight(offset_clip.right()); @@ -1079,19 +1172,23 @@ VisualInfo* visual_info = &visual_info_[i]; changed |= InitVisual(i); - if (params.image.size() >= 1 && params.image[0]) { - changed |= UpdateVisualForVideo(visual_info, params); - } else if (params.image.empty()) { + if (params.image.empty()) { changed |= UpdateVisualForBackbuffer(visual_info, params); } else { - CHECK(false); + bool present_failed = false; + changed |= UpdateVisualForVideo(visual_info, params, &present_failed); + if (present_failed) + return false; } changed |= UpdateVisualClip(visual_info, params); } if (changed) { HRESULT hr = dcomp_device_->Commit(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "Commit failed with error " << std::hex << hr; + return false; + } } pending_overlays_.clear(); @@ -1241,8 +1338,8 @@ default_surface_ = eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); if (!default_surface_) { - LOG(ERROR) << "eglCreatePbufferSurface failed with error " - << ui::GetLastEGLErrorString(); + DLOG(ERROR) << "eglCreatePbufferSurface failed with error " + << ui::GetLastEGLErrorString(); return false; } @@ -1304,11 +1401,27 @@ gl::GLSurfacePresentationHelper::ScopedSwapBuffers scoped_swap_buffers( presentation_helper_.get(), callback); ui::ScopedReleaseCurrent release_current; - root_surface_->SwapBuffers(PresentationCallback()); - layer_tree_->CommitAndClearPendingOverlays(); + child_window_.ClearInvalidContents(); + + bool failed = false; + + if (root_surface_->SwapBuffers(PresentationCallback()) == + gfx::SwapResult::SWAP_FAILED) + failed = true; + + if (!layer_tree_->CommitAndClearPendingOverlays()) + failed = true; + if (!release_current.Restore()) + failed = true; + + if (failed) { scoped_swap_buffers.set_result(gfx::SwapResult::SWAP_FAILED); + base::UmaHistogramSparse("GPU.DirectComposition.SwapBuffersLastError", + ::GetLastError()); + } + return scoped_swap_buffers.result(); }
diff --git a/headless/lib/browser/protocol/target_handler.cc b/headless/lib/browser/protocol/target_handler.cc index f4e5537..f6e5f9a 100644 --- a/headless/lib/browser/protocol/target_handler.cc +++ b/headless/lib/browser/protocol/target_handler.cc
@@ -82,16 +82,32 @@ return Response::OK(); } -Response TargetHandler::DisposeBrowserContext(const std::string& context_id, - bool* out_success) { +Response TargetHandler::DisposeBrowserContext(const std::string& context_id) { HeadlessBrowserContext* context = browser()->GetBrowserContextForId(context_id); - *out_success = false; - if (context && context != browser()->GetDefaultBrowserContext() && - context->GetAllWebContents().empty()) { - *out_success = true; - context->Close(); + if (!context) + return Response::InvalidParams("browserContextId"); + + std::vector<HeadlessWebContents*> web_contents = context->GetAllWebContents(); + while (!web_contents.empty()) { + for (auto* wc : web_contents) + wc->Close(); + // Since HeadlessWebContents::Close spawns a nested run loop to await + // closing, new web_contents could be opened. We need to re-query pages and + // close them too. + web_contents = context->GetAllWebContents(); + } + context->Close(); + return Response::OK(); +} + +Response TargetHandler::GetBrowserContexts( + std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) { + *browser_context_ids = std::make_unique<protocol::Array<protocol::String>>(); + for (auto* context : browser()->GetAllBrowserContexts()) { + if (context != browser()->GetDefaultBrowserContext()) + (*browser_context_ids)->addItem(context->Id()); } return Response::OK(); }
diff --git a/headless/lib/browser/protocol/target_handler.h b/headless/lib/browser/protocol/target_handler.h index 0f5a182..fa57d8b 100644 --- a/headless/lib/browser/protocol/target_handler.h +++ b/headless/lib/browser/protocol/target_handler.h
@@ -28,8 +28,10 @@ Response CloseTarget(const std::string& target_id, bool* out_success) override; Response CreateBrowserContext(std::string* out_context_id) override; - Response DisposeBrowserContext(const std::string& context_id, - bool* out_success) override; + Response DisposeBrowserContext(const std::string& context_id) override; + Response GetBrowserContexts( + std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids) + override; private: DISALLOW_COPY_AND_ASSIGN(TargetHandler);
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc index 6a3beb52..32a3321 100644 --- a/headless/lib/headless_devtools_client_browsertest.cc +++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -513,7 +513,17 @@ void OnDisposeBrowserContextResult( std::unique_ptr<target::DisposeBrowserContextResult> result) { - EXPECT_TRUE(result->GetSuccess()); + devtools_client_->GetTarget()->GetExperimental()->GetBrowserContexts( + target::GetBrowserContextsParams::Builder().Build(), + base::BindOnce(&TargetDomainCreateAndDeleteBrowserContextTest:: + OnGetBrowserContexts, + base::Unretained(this))); + } + + void OnGetBrowserContexts( + std::unique_ptr<target::GetBrowserContextsResult> result) { + const std::vector<std::string>* contexts = result->GetBrowserContextIds(); + EXPECT_EQ(0u, contexts->size()); FinishAsynchronousTest(); } @@ -523,16 +533,27 @@ HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainCreateAndDeleteBrowserContextTest); -class TargetDomainDisposeContextFailsIfInUse - : public HeadlessAsyncDevTooledBrowserTest { +class TargetDomainDisposeContextSucceedsIfInUse + : public target::Observer, + public HeadlessAsyncDevTooledBrowserTest { void RunDevTooledTest() override { EXPECT_TRUE(embedded_test_server()->Start()); - EXPECT_EQ(1u, GetAllWebContents(browser()).size()); + + devtools_client_->GetTarget()->AddObserver(this); + devtools_client_->GetTarget()->SetDiscoverTargets( + target::SetDiscoverTargetsParams::Builder().SetDiscover(true).Build(), + base::BindOnce(&TargetDomainDisposeContextSucceedsIfInUse:: + OnDiscoverTargetsEnabled, + base::Unretained(this))); + } + + void OnDiscoverTargetsEnabled( + std::unique_ptr<target::SetDiscoverTargetsResult> result) { devtools_client_->GetTarget()->GetExperimental()->CreateBrowserContext( target::CreateBrowserContextParams::Builder().Build(), base::BindOnce( - &TargetDomainDisposeContextFailsIfInUse::OnContextCreated, + &TargetDomainDisposeContextSucceedsIfInUse::OnContextCreated, base::Unretained(this))); } @@ -546,7 +567,7 @@ .SetBrowserContextId(context_id_) .Build(), base::BindOnce( - &TargetDomainDisposeContextFailsIfInUse::OnCreateTargetResult, + &TargetDomainDisposeContextSucceedsIfInUse::OnCreateTargetResult, base::Unretained(this))); } @@ -554,54 +575,38 @@ std::unique_ptr<target::CreateTargetResult> result) { page_id_ = result->GetTargetId(); + destroyed_targets_.clear(); devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( target::DisposeBrowserContextParams::Builder() .SetBrowserContextId(context_id_) .Build(), - base::BindOnce(&TargetDomainDisposeContextFailsIfInUse:: + base::BindOnce(&TargetDomainDisposeContextSucceedsIfInUse:: OnDisposeBrowserContextResult, base::Unretained(this))); } + void OnTargetDestroyed(const target::TargetDestroyedParams& params) override { + destroyed_targets_.push_back(params.GetTargetId()); + } + void OnDisposeBrowserContextResult( std::unique_ptr<target::DisposeBrowserContextResult> result) { - EXPECT_FALSE(result->GetSuccess()); - - // Close the page and try again. - devtools_client_->GetTarget()->GetExperimental()->CloseTarget( - target::CloseTargetParams::Builder().SetTargetId(page_id_).Build(), - base::BindOnce( - &TargetDomainDisposeContextFailsIfInUse::OnCloseTargetResult, - base::Unretained(this))); - } - - void OnCloseTargetResult(std::unique_ptr<target::CloseTargetResult> result) { - EXPECT_TRUE(result->GetSuccess()); - - devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( - target::DisposeBrowserContextParams::Builder() - .SetBrowserContextId(context_id_) - .Build(), - base::BindOnce(&TargetDomainDisposeContextFailsIfInUse:: - OnDisposeBrowserContextResult2, - base::Unretained(this))); - } - - void OnDisposeBrowserContextResult2( - std::unique_ptr<target::DisposeBrowserContextResult> result) { - EXPECT_TRUE(result->GetSuccess()); + EXPECT_EQ(destroyed_targets_.size(), 1u); + EXPECT_EQ(destroyed_targets_[0], page_id_); + devtools_client_->GetTarget()->RemoveObserver(this); FinishAsynchronousTest(); } private: + std::vector<std::string> destroyed_targets_; std::string context_id_; std::string page_id_; }; -HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainDisposeContextFailsIfInUse); +HEADLESS_ASYNC_DEVTOOLED_TEST_F(TargetDomainDisposeContextSucceedsIfInUse); class TargetDomainCreateTwoContexts : public HeadlessAsyncDevTooledBrowserTest, - public target::ExperimentalObserver, + public target::Observer, public page::Observer { public: void RunDevTooledTest() override { @@ -612,7 +617,15 @@ devtools_client_->GetPage()->Enable(run_loop.QuitClosure()); run_loop.Run(); - devtools_client_->GetTarget()->GetExperimental()->AddObserver(this); + devtools_client_->GetTarget()->AddObserver(this); + devtools_client_->GetTarget()->SetDiscoverTargets( + target::SetDiscoverTargetsParams::Builder().SetDiscover(true).Build(), + base::BindOnce(&TargetDomainCreateTwoContexts::OnDiscoverTargetsEnabled, + base::Unretained(this))); + } + + void OnDiscoverTargetsEnabled( + std::unique_ptr<target::SetDiscoverTargetsResult> result) { devtools_client_->GetTarget()->GetExperimental()->CreateBrowserContext( target::CreateBrowserContextParams::Builder().Build(), base::BindOnce(&TargetDomainCreateTwoContexts::OnContextOneCreated, @@ -640,6 +653,21 @@ if (context_id_one_.empty() || context_id_two_.empty()) return; + devtools_client_->GetTarget()->GetExperimental()->GetBrowserContexts( + target::GetBrowserContextsParams::Builder().Build(), + base::BindOnce(&TargetDomainCreateTwoContexts::OnGetBrowserContexts, + base::Unretained(this))); + } + + void OnGetBrowserContexts( + std::unique_ptr<target::GetBrowserContextsResult> result) { + const std::vector<std::string>* contexts = result->GetBrowserContextIds(); + EXPECT_EQ(2u, contexts->size()); + EXPECT_TRUE(std::find(contexts->begin(), contexts->end(), + context_id_one_) != contexts->end()); + EXPECT_TRUE(std::find(contexts->begin(), contexts->end(), + context_id_two_) != contexts->end()); + devtools_client_->GetTarget()->GetExperimental()->CreateTarget( target::CreateTargetParams::Builder() .SetUrl("about://blank") @@ -809,52 +837,34 @@ EXPECT_EQ("", value_value->GetString()) << "Page 2 should not share cookies from page one"; - devtools_client_->GetTarget()->GetExperimental()->CloseTarget( - target::CloseTargetParams::Builder() - .SetTargetId(page_id_one_) + devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( + target::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_one_) .Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseTarget, + base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, base::Unretained(this))); - devtools_client_->GetTarget()->GetExperimental()->CloseTarget( - target::CloseTargetParams::Builder() - .SetTargetId(page_id_two_) + devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( + target::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_two_) .Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseTarget, + base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, base::Unretained(this))); - - devtools_client_->GetTarget()->GetExperimental()->RemoveObserver(this); } } } - void OnCloseTarget(std::unique_ptr<target::CloseTargetResult> result) { - page_close_count_++; - - if (page_close_count_ < 2) - return; - - devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( - target::DisposeBrowserContextParams::Builder() - .SetBrowserContextId(context_id_one_) - .Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, - base::Unretained(this))); - - devtools_client_->GetTarget()->GetExperimental()->DisposeBrowserContext( - target::DisposeBrowserContextParams::Builder() - .SetBrowserContextId(context_id_two_) - .Build(), - base::BindOnce(&TargetDomainCreateTwoContexts::OnCloseContext, - base::Unretained(this))); + void OnTargetDestroyed(const target::TargetDestroyedParams& params) override { + ++page_close_count_; } void OnCloseContext( std::unique_ptr<target::DisposeBrowserContextResult> result) { - EXPECT_TRUE(result->GetSuccess()); if (++context_closed_count_ < 2) return; + EXPECT_EQ(page_close_count_, 2); + devtools_client_->GetTarget()->RemoveObserver(this); FinishAsynchronousTest(); }
diff --git a/headless/protocol_config.json b/headless/protocol_config.json index 8f2f5bf2..f441c0c 100644 --- a/headless/protocol_config.json +++ b/headless/protocol_config.json
@@ -12,7 +12,7 @@ "options": [ { "domain": "Target", - "include": ["createTarget", "closeTarget", "createBrowserContext", "disposeBrowserContext"], + "include": ["createTarget", "closeTarget", "getBrowserContexts", "createBrowserContext", "disposeBrowserContext"], "include_events": [] }, {
diff --git a/infra/config/branch/cq.cfg b/infra/config/branch/cq.cfg index cd46c68..f052ca9 100644 --- a/infra/config/branch/cq.cfg +++ b/infra/config/branch/cq.cfg
@@ -129,7 +129,7 @@ } builders { name: "win10_chromium_x64_rel_ng" - equivalent_to { bucket: "luci.chromium.try" percentage: 10 } + equivalent_to { bucket: "luci.chromium.try" percentage: 100 } } builders { name: "win7_chromium_rel_loc_exp"
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index 926238d..6f9af9e 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -556,6 +556,12 @@ } builders { + name: "android-kitkat-arm-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { name: "Deterministic Android" mixins: "android-ci" recipe { @@ -772,6 +778,15 @@ } builders { + name: "linux-xenial-rel" + mixins: "goma-many-jobs-for-ci" + dimensions: "os:Ubuntu-16.04" + recipe { + properties: "mastername:chromium.linux" + } + } + + builders { name: "Linux Builder (dbg)" mixins: "linux-ci" dimensions: "cores:32" @@ -1257,6 +1272,21 @@ builders { mixins: "android-angle-try" name: "android_angle_deqp_rel_ng" } builders { mixins: "android-try" + name: "android-kitkat-arm-rel" + dimensions: "os:Ubuntu-14.04" + } + builders { + mixins: "android-try" + name: "linux_android_rel_ng" + auto_builder_dimension: NO + dimensions: "builder:android-kitkat-arm-rel" + dimensions: "os:Ubuntu-14.04" + recipe { + properties: "buildername:android-kitkat-arm-rel" + } + } + builders { + mixins: "android-try" name: "android_arm64_dbg_recipe" dimensions: "os:Ubuntu-14.04" } @@ -1319,7 +1349,6 @@ builders { mixins: "linux-try" name: "linux-gcc-rel" } builders { mixins: "linux-try" name: "linux-jumbo-rel" } builders { mixins: "linux-try" name: "linux-ozone-rel" } - builders { mixins: "linux-try" name: "linux_android_rel_ng" } builders { mixins: "linux-try" name: "linux_arm" } builders { mixins: "linux-try" name: "linux_chromium_analysis" } builders { mixins: "linux-try" name: "linux_chromium_archive_rel_ng" }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index dd2d0b0..dcef344 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -368,7 +368,6 @@ short_name: "dev" } builders: { - name: "buildbot/chromium.mac/ios-simulator" name: "buildbucket/luci.chromium.ci/ios-simulator" category: "chromium.mac|ios" short_name: "sim" @@ -404,6 +403,11 @@ category: "chromium.linux|release" short_name: "gcc" } + builders { + name: "buildbucket/luci.chromium.ci/linux-xenial-rel" + category: "chromium.linux|release" + short_name: "xen" + } builders: { name: "buildbucket/luci.chromium.ci/Linux Builder (dbg)(32)" category: "chromium.linux|debug|builder" @@ -836,11 +840,6 @@ short_name: "dev" } builders: { - name: "buildbot/chromium.mac/ios-simulator" - category: "ios" - short_name: "sim" - } - builders: { name: "buildbot/chromium.mac/ios-simulator-full-configs" category: "ios" short_name: "ful" @@ -871,21 +870,26 @@ short_name: "bld" } builders: { + name: "buildbucket/luci.chromium.ci/Linux Tests" + category: "release" + short_name: "tst" + } + builders: { name: "buildbucket/luci.chromium.ci/linux-gcc-rel" category: "release" short_name: "gcc" } + builders { + name: "buildbucket/luci.chromium.ci/linux-xenial-rel" + category: "release" + short_name: "xen" + } builders: { name: "buildbucket/luci.chromium.ci/linux-jumbo-rel" category: "jumbo" short_name: "jumbo" } builders: { - name: "buildbucket/luci.chromium.ci/Linux Tests" - category: "release" - short_name: "tst" - } - builders: { name: "buildbucket/luci.chromium.ci/Linux Builder (dbg)(32)" category: "debug|builder" short_name: "32" @@ -1553,17 +1557,6 @@ category: "chromium.memory|asan|tester|sandbox" short_name: "ci" } - - builders: { - name: "buildbot/chromium.mac/ios-simulator" - category: "chromium.mac|ios-simulator" - short_name: "bb" - } - builders: { - name: "buildbucket/luci.chromium.ci/ios-simulator" - category: "chromium.mac|ios-simulator" - short_name: "ci" - } builders: { name: "buildbot/chromium.fyi/Headless Linux (dbg)" category: "chromium.fyi|linux|debug" @@ -1574,6 +1567,17 @@ category: "chromium.fyi|linux|debug" short_name: "ci" } + + builders: { + name: "buildbucket/luci.chromium.ci/android-kitkat-arm-rel" + category: "android|arm|rel" + short_name: "ci" + } + builders: { + name: "buildbot/chromium.android/KitKat Phone Tester (rel)" + category: "android|arm|rel" + short_name: "bb" + } builders: { name: "buildbucket/luci.chromium.ci/Android arm Builder (dbg)" category: "android|builder|arm|debug|32" @@ -1847,6 +1851,7 @@ } builders: { name: "buildbot/chromium.android/KitKat Phone Tester (rel)" + name: "buildbucket/luci.chromium.ci/android-kitkat-arm-rel" category: "on_cq" short_name: "K" } @@ -2461,10 +2466,6 @@ category: "linux" } builders: { - name: "buildbot/chromium.fyi/Linux Xenial" - category: "linux" - } - builders: { name: "buildbot/chromium.fyi/Mojo Android" category: "mojo" } @@ -3846,6 +3847,7 @@ } builders: { name: "buildbot/tryserver.chromium.android/linux_android_rel_ng" + name: "buildbucket/luci.chromium.try/android-kitkat-arm-rel" } } @@ -4384,6 +4386,9 @@ builder_view_only: true builders: { + name: "buildbucket/luci.chromium.try/android-kitkat-arm-rel" + } + builders: { name: "buildbucket/luci.chromium.try/android_arm64_dbg_recipe" } builders: { @@ -4456,9 +4461,6 @@ name: "buildbucket/luci.chromium.try/linux-ozone-rel" } builders: { - name: "buildbucket/luci.chromium.try/linux_android_rel_ng" - } - builders: { name: "buildbucket/luci.chromium.try/linux_angle_compile_dbg_ng" } builders: {
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 204064d..20f11b2 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -67,6 +67,7 @@ triggers: "Android FYI Release (NVIDIA Shield TV)" triggers: "Android x64 Builder (dbg)" triggers: "Android x86 Builder (dbg)" + triggers: "android-kitkat-arm-rel" triggers: "Deterministic Android" triggers: "Deterministic Android (dbg)" triggers: "Optional Android Release (Nexus 5X)" @@ -100,6 +101,7 @@ triggers: "linux-gcc-rel" triggers: "linux-jumbo-rel" triggers: "linux-ozone-rel" + triggers: "linux-xenial-rel" triggers: "Linux ASan LSan Builder" triggers: "Linux Builder" triggers: "Linux Builder (dbg)" @@ -356,6 +358,16 @@ } job { + id: "android-kitkat-arm-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-kitkat-arm-rel" + } +} + +job { id: "Deterministic Android" acl_sets: "default" buildbucket: { @@ -869,6 +881,26 @@ } job { + id: "linux-ozone-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "linux-ozone-rel" + } +} + +job { + id: "linux-xenial-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "linux-xenial-rel" + } +} + +job { id: "Linux ASan LSan Builder" acl_sets: "default" buildbucket: { @@ -994,16 +1026,6 @@ } } -job { - id: "linux-ozone-rel" - acl_sets: "default" - buildbucket: { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.ci" - builder: "linux-ozone-rel" - } -} - ################################################################################ # Mac Builders. Sorted alphabetically. ################################################################################
diff --git a/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.h b/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.h index ebb08a1f..d4ab5f9 100644 --- a/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.h +++ b/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.h
@@ -6,13 +6,9 @@ #define IOS_CHROME_BROWSER_ITUNES_LINKS_ITUNES_LINKS_HANDLER_TAB_HELPER_H_ #include "base/macros.h" -#include "ios/web/public/web_state/web_state_observer.h" +#import "ios/web/public/web_state/web_state_policy_decider.h" #include "ios/web/public/web_state/web_state_user_data.h" -namespace web { -class WebStatePolicyDecider; -} - // Enum for the IOS.StoreKit.ITunesURLsHandlingResult UMA histogram to report // the results of the StoreKit handling. // These values are persisted to logs. Entries should not be renumbered and @@ -31,28 +27,26 @@ kCount }; -// TabHelper which handles navigation to iTunes links. -// If a navigation to web page for a product in iTunes App Store happens while -// in non off the record browsing mode, this helper will use StoreKitTabHelper -// to present the information of that product. The goal of this class is to -// workaround a bug where appstore website serves the wrong content for -// itunes.apple.com pages, see http://crbug.com/623016. +// A Tab helper for iTunes Apps URLs handling. +// If a navigation to web page for a supported product in iTunes App Store +// happens while in non off the record browsing mode, this helper will use +// StoreKitTabHelper to present the information of that product. The goal of +// this class is to workaround a bug where appstore website serves the wrong +// content for itunes.apple.com pages, see http://crbug.com/623016. class ITunesLinksHandlerTabHelper - : public web::WebStateObserver, + : public web::WebStatePolicyDecider, public web::WebStateUserData<ITunesLinksHandlerTabHelper> { public: ~ITunesLinksHandlerTabHelper() override; explicit ITunesLinksHandlerTabHelper(web::WebState* web_state); + // web::WebStatePolicyDecider implementation + bool ShouldAllowRequest(NSURLRequest* request, + ui::PageTransition transition, + bool from_main_frame) override; private: - // web::WebStateObserver implementation - void DidFinishNavigation(web::WebState* web_state, - web::NavigationContext* navigation_context) override; - void WebStateDestroyed(web::WebState* web_state) override; - - // PolicyDecider instance that will be initialized with the - // ITunesLinkHandlerTabHelper object, and destroyed with it. - std::unique_ptr<web::WebStatePolicyDecider> policy_decider_; + // Opens the StoreKit for the given iTunes app |url|. + void HandleITunesUrl(const GURL& url); DISALLOW_COPY_AND_ASSIGN(ITunesLinksHandlerTabHelper); };
diff --git a/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.mm b/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.mm index 2d343ffe2..d3bb5642 100644 --- a/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.mm +++ b/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper.mm
@@ -18,7 +18,6 @@ #include "ios/web/public/browser_state.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" -#import "ios/web/public/web_state/navigation_context.h" #import "ios/web/public/web_state/web_state_policy_decider.h" #include "net/base/filename_util.h" #import "net/base/mac/url_conversions.h" @@ -78,67 +77,29 @@ return params_dictionary; } -// This class handles requests & responses that involve iTunes product links. -class ITunesLinksHandlerWebStatePolicyDecider - : public web::WebStatePolicyDecider { - public: - explicit ITunesLinksHandlerWebStatePolicyDecider(web::WebState* web_state) - : web::WebStatePolicyDecider(web_state) {} - - // web::WebStatePolicyDecider implementation - bool ShouldAllowResponse(NSURLResponse* response, - bool for_main_frame) override { - // Don't allow rendering responses from URLs that can be handled by - // iTunesLinksHandler unless it's on iframe or the browsing mode is off the - // record. - return web_state()->GetBrowserState()->IsOffTheRecord() || - !for_main_frame || !CanHandleUrl(net::GURLWithNSURL(response.URL)); - } - - bool ShouldAllowRequest(NSURLRequest* request, - ui::PageTransition transition, - bool from_main_frame) override { - // Only consider blocking the request if it's not of the record mode. - if (web_state()->GetBrowserState()->IsOffTheRecord()) - return true; - web::NavigationItem* pending_item = - web_state()->GetNavigationManager()->GetPendingItem(); - - if (!pending_item) - return true; - // If the pending item URL is http iTunes URL that can be handled, but the - // request URL is not http URL, then there was a redirect to an external - // application and request should be blocked to be able to show the store - // kit later. - GURL pending_item_url = pending_item->GetURL(); - GURL request_url = net::GURLWithNSURL(request.URL); - return !CanHandleUrl(pending_item_url) || request_url.SchemeIsHTTPOrHTTPS(); - } - - // Returns true, if iTunesLinksHandler can handle the given |url|. - static bool CanHandleUrl(const GURL& url) { - if (!IsITunesProductUrl(url)) - return false; - // Valid iTunes URL structure: - // DOMAIN/OPTIONAL_REGION_CODE/MEDIA_TYPE/MEDIA_NAME/ID?PARAMETERS - // Check the URL media type, to determine if it is supported. - base::FilePath path; - if (!net::FileURLToFilePath(url, &path)) - return false; - std::vector<base::FilePath::StringType> path_components; - path.GetComponents(&path_components); - // GetComponents considers "/" as the first component. - if (path_components.size() < kITunesUrlPathMinComponentsCount) - return false; - size_t media_type_index = kITunesUrlMediaTypeComponentDefaultIndex; - DCHECK(media_type_index > 0); - // If there is no reigon code in the URL then media type has to appear - // earlier in the URL. - if (path_components[kITunesUrlRegionComponentDefaultIndex].size() != 2) - media_type_index--; - return path_components[media_type_index] == kITunesAppPathIdentifier; - } -}; +// Returns true, if ITunesLinksHandlerTabHelper can handle the given |url|. +bool CanHandleUrl(const GURL& url) { + if (!IsITunesProductUrl(url)) + return false; + // Valid iTunes URL structure: + // DOMAIN/OPTIONAL_REGION_CODE/MEDIA_TYPE/MEDIA_NAME/ID?PARAMETERS + // Check the URL media type, to determine if it is supported. + base::FilePath path; + if (!net::FileURLToFilePath(url, &path)) + return false; + std::vector<base::FilePath::StringType> path_components; + path.GetComponents(&path_components); + // GetComponents considers "/" as the first component. + if (path_components.size() < kITunesUrlPathMinComponentsCount) + return false; + size_t media_type_index = kITunesUrlMediaTypeComponentDefaultIndex; + DCHECK(media_type_index > 0); + // If there is no reigon code in the URL then media type has to appear + // earlier in the URL. + if (path_components[kITunesUrlRegionComponentDefaultIndex].size() != 2) + media_type_index--; + return path_components[media_type_index] == kITunesAppPathIdentifier; +} } // namespace @@ -146,39 +107,37 @@ ITunesLinksHandlerTabHelper::ITunesLinksHandlerTabHelper( web::WebState* web_state) - : policy_decider_(std::make_unique<ITunesLinksHandlerWebStatePolicyDecider>( - web_state)) { - web_state->AddObserver(this); + : web::WebStatePolicyDecider(web_state) {} + +bool ITunesLinksHandlerTabHelper::ShouldAllowRequest( + NSURLRequest* request, + ui::PageTransition transition, + bool from_main_frame) { + // Don't Handle URLS in Off The record mode as this will open StoreKit with + // Users' iTunes account. Also don't Handle requests from iframe because they + // may be spam, and they will be handled by other policy deciders. + if (web_state()->GetBrowserState()->IsOffTheRecord() || !from_main_frame) + return true; + + GURL request_url = net::GURLWithNSURL(request.URL); + if (!CanHandleUrl(request_url)) + return true; + + HandleITunesUrl(request_url); + return false; } -// WebStateObserver -void ITunesLinksHandlerTabHelper::DidFinishNavigation( - web::WebState* web_state, - web::NavigationContext* navigation_context) { - // Don't handle iTunse URL in off the record mode. - if (web_state->GetBrowserState()->IsOffTheRecord()) - return; - - GURL url = navigation_context->GetUrl(); - // Whenever a navigation to iTunes product url is finished, launch StoreKit. - if (ITunesLinksHandlerWebStatePolicyDecider::CanHandleUrl(url)) { - ITunesUrlsStoreKitHandlingResult handling_result = - ITunesUrlsStoreKitHandlingResult::kSingleAppUrlHandled; - // If the url is iTunes product url, then this navigation should not be - // committed, as the policy decider's ShouldAllowResponse will return false. - DCHECK(!navigation_context->HasCommitted()); - StoreKitTabHelper* tab_helper = StoreKitTabHelper::FromWebState(web_state); - if (tab_helper) { - base::RecordAction( - base::UserMetricsAction("ITunesLinksHandler_StoreKitLaunched")); - tab_helper->OpenAppStore(ExtractITunesProductParameters(url)); - } else { - handling_result = ITunesUrlsStoreKitHandlingResult::kUrlHandlingFailed; - } - RecordStoreKitHandlingResult(handling_result); +// private +void ITunesLinksHandlerTabHelper::HandleITunesUrl(const GURL& url) { + ITunesUrlsStoreKitHandlingResult handling_result = + ITunesUrlsStoreKitHandlingResult::kSingleAppUrlHandled; + StoreKitTabHelper* tab_helper = StoreKitTabHelper::FromWebState(web_state()); + if (tab_helper) { + base::RecordAction( + base::UserMetricsAction("ITunesLinksHandler_StoreKitLaunched")); + tab_helper->OpenAppStore(ExtractITunesProductParameters(url)); + } else { + handling_result = ITunesUrlsStoreKitHandlingResult::kUrlHandlingFailed; } -} - -void ITunesLinksHandlerTabHelper::WebStateDestroyed(web::WebState* web_state) { - web_state->RemoveObserver(this); + RecordStoreKitHandlingResult(handling_result); }
diff --git a/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper_unittest.mm b/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper_unittest.mm index 0386eb5..b05cd208 100644 --- a/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper_unittest.mm +++ b/ios/chrome/browser/itunes_links/itunes_links_handler_tab_helper_unittest.mm
@@ -6,19 +6,15 @@ #import <Foundation/Foundation.h> -#include "base/observer_list.h" #include "base/test/histogram_tester.h" #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #import "ios/chrome/test/fakes/fake_store_kit_launcher.h" -#import "ios/web/public/test/fakes/fake_navigation_context.h" -#import "ios/web/public/test/fakes/test_navigation_manager.h" #import "ios/web/public/test/fakes/test_web_state.h" #include "ios/web/public/test/test_web_thread_bundle.h" #import "ios/web/public/web_state/web_state_policy_decider.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" -#include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -37,125 +33,113 @@ web_state_.SetBrowserState( chrome_browser_state_->GetOriginalChromeBrowserState()); StoreKitTabHelper::CreateForWebState(&web_state_); - std::unique_ptr<web::TestNavigationManager> test_navigation_manager = - std::make_unique<web::TestNavigationManager>(); - navigation_manager_ = test_navigation_manager.get(); - web_state_.SetNavigationManager(std::move(test_navigation_manager)); ITunesLinksHandlerTabHelper::CreateForWebState(&web_state_); StoreKitTabHelper::FromWebState(&web_state_)->SetLauncher(fake_launcher_); } - // Tries to finish navigation with the given |url_string| and returns true if - // store kit was launched. - bool VerifyStoreKitLaunched(const std::string& url_string) { + // Calls ShouldAllowRequest for a request with the given |url_string| and + // returns true if storekit was launched. + bool VerifyStoreKitLaunched(NSString* url_string, bool main_frame) { fake_launcher_.launchedProductID = nil; fake_launcher_.launchedProductParams = nil; - web::FakeNavigationContext context; - context.SetUrl(GURL(url_string)); - web_state_.OnNavigationFinished(&context); - return fake_launcher_.launchedProductID != nil || - fake_launcher_.launchedProductParams != nil; - } - - // Checks that given the pending item URL & the request URL if - // ITunesHandlerPolicyDecider will allow the request. - bool ShouldAllowRequest(NSString* url_string, - std::string const& pending_item_url) { - std::unique_ptr<web::NavigationItem> pending_item; - if (!pending_item_url.empty()) { - pending_item = web::NavigationItem::Create(); - pending_item->SetURL(GURL(pending_item_url)); - } - navigation_manager_->SetPendingItem(pending_item.get()); - - return web_state_.ShouldAllowRequest( + bool request_allowed = web_state_.ShouldAllowRequest( [NSURLRequest requestWithURL:[NSURL URLWithString:url_string]], - ui::PageTransition::PAGE_TRANSITION_LINK, /*from_main_frame=*/true); - } - - // Checks that given the pending item URL & the request URL if - // ITunesHandlerPolicyDecider will allow the request. - bool ShouldAllowResponse(NSString* url_string, bool main_frame) { - NSURLResponse* response = - [[NSURLResponse alloc] initWithURL:[NSURL URLWithString:url_string] - MIMEType:@"text/html" - expectedContentLength:0 - textEncodingName:nil]; - return web_state_.ShouldAllowResponse(response, main_frame); + ui::PageTransition::PAGE_TRANSITION_LINK, main_frame); + return !request_allowed && (fake_launcher_.launchedProductID != nil || + fake_launcher_.launchedProductParams != nil); } web::TestWebThreadBundle thread_bundle_; - web::TestNavigationManager* navigation_manager_; FakeStoreKitLauncher* fake_launcher_; web::TestWebState web_state_; std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; base::HistogramTester histogram_tester_; }; +// Verifies that iTunes URLs are not handled when in off the record mode. +TEST_F(ITunesLinksHandlerTabHelperTest, NoHandlingInOffTheRecordMode) { + NSString* url = @"http://itunes.apple.com/us/app/app_name/id123"; + EXPECT_TRUE(VerifyStoreKitLaunched(url, /*main_frame=*/true)); + web_state_.SetBrowserState( + chrome_browser_state_->GetOffTheRecordChromeBrowserState()); + EXPECT_FALSE(VerifyStoreKitLaunched(url, /*main_frame=*/true)); +} + +// Verifies that iTunes URLs are not handled when the request is from iframe. +TEST_F(ITunesLinksHandlerTabHelperTest, NoHandlingInIframes) { + EXPECT_TRUE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/us/app/app_name/id123", /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/us/app/app_name/id123", /*main_frame=*/false)); + EXPECT_TRUE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/app/bar/id243?at=12312", /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/app/bar/id243?at=12312", /*main_frame=*/false)); +} + // Verifies that navigating to non iTunes product URLs, or not supported iTunes // product type URLs does not launch storekit. TEST_F(ITunesLinksHandlerTabHelperTest, NonMatchingUrlsDoesntLaunchStoreKit) { - EXPECT_FALSE(VerifyStoreKitLaunched("")); - EXPECT_FALSE(VerifyStoreKitLaunched("foobar")); - EXPECT_FALSE(VerifyStoreKitLaunched("foo://bar")); - EXPECT_FALSE(VerifyStoreKitLaunched("http://foo")); - EXPECT_FALSE(VerifyStoreKitLaunched("http://foo?bar#qux")); - EXPECT_FALSE(VerifyStoreKitLaunched("http://foo.bar/qux")); + EXPECT_FALSE(VerifyStoreKitLaunched(@"", /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched(@"foobar", /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched(@"foo://bar", /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched(@"http://foo", /*main_frame=*/true)); EXPECT_FALSE( - VerifyStoreKitLaunched("http://geo.itunes.apple.com/de/genre/apps/")); - EXPECT_FALSE(VerifyStoreKitLaunched( - "https://itunes.apple.com/us/tv-show/theshow/id1232")); + VerifyStoreKitLaunched(@"http://foo?bar#qux", /*main_frame=*/true)); EXPECT_FALSE( - VerifyStoreKitLaunched("http://itunes.apple.com/podcast/id12345")); + VerifyStoreKitLaunched(@"http://foo.bar/qux", /*main_frame=*/true)); EXPECT_FALSE(VerifyStoreKitLaunched( - "itms-apps://itunes.apple.com/us/app/appname/id123")); + @"http://geo.itunes.apple.com/de/genre/apps/", /*main_frame=*/true)); EXPECT_FALSE(VerifyStoreKitLaunched( - "http://itunes.apple.com/us/movie/testmovie/id12345")); - EXPECT_FALSE( - VerifyStoreKitLaunched("http://itunes.apple.com/app-bundle/id12345")); + @"https://itunes.apple.com/us/tv-show/theshow/id1232", + /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/podcast/id12345", /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched( + @"itms-apps://itunes.apple.com/us/app/appname/id123", + /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/us/movie/testmovie/id12345", + /*main_frame=*/true)); + EXPECT_FALSE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/app-bundle/id12345", /*main_frame=*/true)); histogram_tester_.ExpectTotalCount(kITunesURLsHandlingResultHistogram, 0); } -// Verifies that iTunes URLs are not handled when in off the record mode. -TEST_F(ITunesLinksHandlerTabHelperTest, NoHandlingInOffTheRecordMode) { - std::string url = "http://itunes.apple.com/us/app/app_name/id123"; - EXPECT_TRUE(VerifyStoreKitLaunched(url)); - web_state_.SetBrowserState( - chrome_browser_state_->GetOffTheRecordChromeBrowserState()); - EXPECT_FALSE(VerifyStoreKitLaunched(url)); -} - // Verifies that navigating to URLs for a product hosted on iTunes AppStore // with supported media type launches storekit. TEST_F(ITunesLinksHandlerTabHelperTest, MatchingUrlsLaunchesStoreKit) { - EXPECT_TRUE( - VerifyStoreKitLaunched("http://itunes.apple.com/us/app/app_name/id123")); + EXPECT_TRUE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/us/app/app_name/id123", /*main_frame=*/true)); NSString* product_id = @"id"; NSString* af_tkn = @"at"; NSDictionary* expected_params = @{product_id : @"123"}; EXPECT_NSEQ(expected_params, fake_launcher_.launchedProductParams); - - EXPECT_TRUE(VerifyStoreKitLaunched("http://itunes.apple.com/app/bar/id123?")); + EXPECT_TRUE(VerifyStoreKitLaunched(@"http://itunes.apple.com/app/bar/id123?", + /*main_frame=*/true)); EXPECT_NSEQ(expected_params, fake_launcher_.launchedProductParams); EXPECT_TRUE(VerifyStoreKitLaunched( - "http://foo.itunes.apple.com/app/test/id123?qux&baz#foo")); + @"http://foo.itunes.apple.com/app/test/id123?qux&baz#foo", + /*main_frame=*/true)); expected_params = @{product_id : @"123", @"qux" : @"", @"baz" : @""}; EXPECT_NSEQ(expected_params, fake_launcher_.launchedProductParams); - EXPECT_TRUE( - VerifyStoreKitLaunched("http://itunes.apple.com/app/bar/id243?at=12312")); + EXPECT_TRUE(VerifyStoreKitLaunched( + @"http://itunes.apple.com/app/bar/id243?at=12312", /*main_frame=*/true)); expected_params = @{product_id : @"243", af_tkn : @"12312"}; EXPECT_NSEQ(expected_params, fake_launcher_.launchedProductParams); EXPECT_TRUE(VerifyStoreKitLaunched( - "http://itunes.apple.com/app/bar/idabc?at=213&ct=123")); + @"http://itunes.apple.com/app/bar/idabc?at=213&ct=123", + /*main_frame=*/true)); expected_params = @{product_id : @"abc", af_tkn : @"213", @"ct" : @"123"}; EXPECT_NSEQ(expected_params, fake_launcher_.launchedProductParams); EXPECT_TRUE(VerifyStoreKitLaunched( - "http://itunes.apple.com/de/app/bar/id123?at=2&uo=4#foo")); + @"http://itunes.apple.com/de/app/bar/id123?at=2&uo=4#foo", + /*main_frame=*/true)); expected_params = @{product_id : @"123", af_tkn : @"2", @"uo" : @"4"}; EXPECT_NSEQ(expected_params, fake_launcher_.launchedProductParams); @@ -166,50 +150,3 @@ 6); histogram_tester_.ExpectTotalCount(kITunesURLsHandlingResultHistogram, 6); } - -// Verifies that ITunesLinkHandlerPolicyDecider don't allow redirects to Apple -// appstore when the original request link is supported http iTunes product URL. -TEST_F(ITunesLinksHandlerTabHelperTest, TestPolicyDeciderShouldAllowRequest) { - EXPECT_FALSE(ShouldAllowRequest( - /*url_string=*/@"itms://itunes.apple.com/us/app/name/id12345", - /*pending_item_url=*/"http://itunes.apple.com/us/app/name/id12345")); - EXPECT_TRUE(ShouldAllowRequest( - /*url_string=*/@"itms://itunes.apple.com/us/app/name/id12345", - /*pending_item_url=*/"http://foo.bar")); - EXPECT_TRUE(ShouldAllowRequest( - /*url_string=*/@"http://itunes.apple.com/us/app/name/id12345", - /*pending_item_url=*/"")); - EXPECT_TRUE(ShouldAllowRequest( - /*url_string=*/@"itms-apps://itunes.apple.com/us/podcast/name/id123", - /*pending_item_url=*/"https://itunes.apple.com/us/podcast/name/id123")); - EXPECT_TRUE(ShouldAllowRequest( - /*url_string=*/@"https://itunes.apple.com/app/test/id12345", - /*pending_item_url=*/"https://foo.bar")); -} - -// Verifies that ITunesLinkHandlerPolicyDecider block response from supported -// http iTunes product URL. -TEST_F(ITunesLinksHandlerTabHelperTest, TestPolicyDeciderShouldAllowResponse) { - EXPECT_TRUE(ShouldAllowResponse(/*url_string=*/@"https://itunes.apple.com/", - /*main_frame=*/true)); - EXPECT_FALSE(ShouldAllowResponse( - /*url_string=*/@"http://itunes.apple.com/app/test/id1234", - /*main_frame=*/true)); - // If the response is for subframe, it should be allowed. - EXPECT_TRUE(ShouldAllowResponse( - /*url_string=*/@"http://itunes.apple.com/app/test/id1234", - /*main_frame=*/false)); - - EXPECT_TRUE(ShouldAllowResponse( - /*url_string=*/@"https://itunes.apple.com/us/podcast/name/id123", - /*main_frame=*/true)); - EXPECT_FALSE(ShouldAllowResponse( - /*url_string=*/@"http://itunes.apple.com/de/app/bar/id123?qux", - /*main_frame=*/true)); - - EXPECT_TRUE(ShouldAllowResponse( - /*url_string=*/@"itms-apps://itunes.apple.com/de/app/bar/id123?qux", - /*main_frame=*/true)); - EXPECT_TRUE(ShouldAllowResponse(/*url_string=*/@"http://foo.bar/qux", - /*main_frame=*/true)); -}
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn index 83e09b7..fa52c64 100644 --- a/ios/chrome/browser/ui/bookmarks/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -17,6 +17,9 @@ "bookmark_folder_table_view_cell.mm", "bookmark_folder_view_controller.h", "bookmark_folder_view_controller.mm", + "bookmark_home_consumer.h", + "bookmark_home_mediator.h", + "bookmark_home_mediator.mm", "bookmark_home_shared_state.h", "bookmark_home_shared_state.mm", "bookmark_home_view_controller.h",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h b/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h new file mode 100644 index 0000000..e6803a0 --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h
@@ -0,0 +1,15 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_HOME_CONSUMER_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_HOME_CONSUMER_H_ + +#import "ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h" + +// BookmarkHomeConsumer provides methods that allow mediators to update the UI. +@protocol BookmarkHomeConsumer<ChromeTableViewConsumer> + +@end + +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_HOME_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.h b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.h new file mode 100644 index 0000000..e746582 --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_HOME_MEDIATOR_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_HOME_MEDIATOR_H_ + +#import <Foundation/Foundation.h> + +@protocol BookmarkHomeConsumer; +@class BookmarkHomeSharedState; + +// BookmarkHomeMediator manages model interactions for the +// BookmarkHomeViewController. +@interface BookmarkHomeMediator : NSObject + +@property(nonatomic, weak) id<BookmarkHomeConsumer> consumer; + +- (instancetype)initWithSharedState:(BookmarkHomeSharedState*)sharedState + NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; + +// Starts this mediator. Populates the table view model with current data and +// begins listening for backend model updates. +- (void)startMediating; + +// Stops mediating and disconnects from backend models. +- (void)disconnect; + +@end + +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_HOME_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm new file mode 100644 index 0000000..a3f0dbb2 --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.h" + +#include "base/logging.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_home_shared_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface BookmarkHomeMediator () + +@property(nonatomic, strong) BookmarkHomeSharedState* sharedState; + +@end + +@implementation BookmarkHomeMediator +@synthesize consumer = _consumer; +@synthesize sharedState = _sharedState; + +- (instancetype)initWithSharedState:(BookmarkHomeSharedState*)sharedState { + if ((self = [super init])) { + _sharedState = sharedState; + } + return self; +} + +- (void)startMediating { + DCHECK(self.consumer); + DCHECK(self.sharedState); +} + +- (void)disconnect { + self.consumer = nil; + self.sharedState = nil; +} + +@end
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index 145647f..7188188 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -17,6 +17,8 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_view_controller.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_home_shared_state.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_home_waiting_view.h" #include "ios/chrome/browser/ui/bookmarks/bookmark_model_bridge_observer.h" @@ -79,6 +81,7 @@ BookmarkEditViewControllerDelegate, BookmarkFolderEditorViewControllerDelegate, BookmarkFolderViewControllerDelegate, + BookmarkHomeConsumer, BookmarkHomeSharedStateObserver, BookmarkModelBridgeObserver, BookmarkPromoControllerDelegate, @@ -108,9 +111,15 @@ // The user's browser state model used. @property(nonatomic, assign) ios::ChromeBrowserState* browserState; +// The mediator that provides data for this view controller. +@property(nonatomic, strong) BookmarkHomeMediator* mediator; + // The main view showing all the bookmarks. @property(nonatomic, strong) BookmarkTableView* bookmarksTableView; +// The table view's styler. +@property(nonatomic, strong) ChromeTableViewStyler* tableViewStyler; + // The view controller used to pick a folder in which to move the selected // bookmarks. @property(nonatomic, strong) BookmarkFolderViewController* folderSelector; @@ -169,6 +178,8 @@ @synthesize cachedContentPosition = _cachedContentPosition; @synthesize isReconstructingFromCache = _isReconstructingFromCache; @synthesize sharedState = _sharedState; +@synthesize mediator = _mediator; +@synthesize tableViewStyler = _tableViewStyler; #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -200,6 +211,13 @@ return self; } +- (void)dealloc { + [self.mediator disconnect]; + [self removeKeyboardObservers]; + _sharedState.tableView.dataSource = nil; + _sharedState.tableView.delegate = nil; +} + - (void)setRootNode:(const bookmarks::BookmarkNode*)rootNode { _rootNode = rootNode; } @@ -278,9 +296,35 @@ [self.view addSubview:self.bookmarksTableView]; // Configure the table view. + self.tableViewStyler = [[ChromeTableViewStyler alloc] init]; + self.sharedState.tableView.accessibilityIdentifier = @"bookmarksTableView"; + if (@available(iOS 11.0, *)) { + self.sharedState.tableView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; + } + self.sharedState.tableView.estimatedRowHeight = + [BookmarkHomeSharedState cellHeightPt]; + self.sharedState.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.sharedState.tableView.allowsMultipleSelectionDuringEditing = YES; + + UILongPressGestureRecognizer* longPressRecognizer = + [[UILongPressGestureRecognizer alloc] + initWithTarget:self + action:@selector(handleLongPress:)]; + longPressRecognizer.numberOfTouchesRequired = 1; + longPressRecognizer.delegate = self; + [self.sharedState.tableView addGestureRecognizer:longPressRecognizer]; + + // Create the mediator and hook up the table view. + self.mediator = + [[BookmarkHomeMediator alloc] initWithSharedState:self.sharedState]; + self.mediator.consumer = self; + [self.mediator startMediating]; self.sharedState.tableView.dataSource = self; self.sharedState.tableView.delegate = self; + [self registerForKeyboardNotifications]; + // After the table view has been added. [self setupNavigationBar]; @@ -316,6 +360,22 @@ .contentPosition)]; } +#pragma mark - BookmarkHomeConsumer + +- (void)reconfigureCellsForItems:(NSArray*)items { + for (TableViewItem* item in items) { + NSIndexPath* indexPath = + [self.sharedState.tableViewModel indexPathForItem:item]; + UITableViewCell* cell = + [self.sharedState.tableView cellForRowAtIndexPath:indexPath]; + + // |cell| may be nil if the row is not currently on screen. + if (cell) { + [item configureCell:cell withStyler:self.tableViewStyler]; + } + } +} + #pragma mark - BookmarkPromoControllerDelegate - (void)promoStateChanged:(BOOL)promoEnabled { @@ -1248,12 +1308,114 @@ return alert; } -#pragma mark - UIGestureRecognizerDelegate +#pragma mark - UIGestureRecognizerDelegate and gesture handling - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer { - DCHECK(gestureRecognizer == - self.navigationController.interactivePopGestureRecognizer); - return self.navigationController.viewControllers.count > 1; + if (gestureRecognizer == + self.navigationController.interactivePopGestureRecognizer) { + return self.navigationController.viewControllers.count > 1; + } + return YES; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer + shouldReceiveTouch:(UITouch*)touch { + // Ignore long press in edit mode. + if (self.sharedState.currentlyInEditMode) { + return NO; + } + return YES; +} + +- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer { + if (self.sharedState.currentlyInEditMode || + gestureRecognizer.state != UIGestureRecognizerStateBegan) { + return; + } + CGPoint touchPoint = + [gestureRecognizer locationInView:self.sharedState.tableView]; + NSIndexPath* indexPath = + [self.sharedState.tableView indexPathForRowAtPoint:touchPoint]; + if (indexPath == nil || [self.sharedState.tableViewModel + sectionIdentifierForSection:indexPath.section] != + BookmarkHomeSectionIdentifierBookmarks) { + return; + } + + const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; + // Disable the long press gesture if it is a permanent node (not an URL or + // Folder). + if (!node || ![self isUrlOrFolder:node]) { + return; + } + + [self bookmarkTableView:self.bookmarksTableView showContextMenuForNode:node]; +} + +#pragma mark - Keyboard + +- (void)registerForKeyboardNotifications { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWasShown:) + name:UIKeyboardDidShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWillBeHidden:) + name:UIKeyboardWillHideNotification + object:nil]; +} + +- (void)removeKeyboardObservers { + NSNotificationCenter* notificationCenter = + [NSNotificationCenter defaultCenter]; + [notificationCenter removeObserver:self + name:UIKeyboardDidShowNotification + object:nil]; + [notificationCenter removeObserver:self + name:UIKeyboardWillHideNotification + object:nil]; +} + +// Called when the UIKeyboardDidShowNotification is sent +- (void)keyboardWasShown:(NSNotification*)aNotification { + if (![self isAtTopOfNavigation:self.bookmarksTableView]) { + return; + } + NSDictionary* info = [aNotification userInfo]; + CGFloat keyboardTop = + [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y; + CGFloat tableBottom = CGRectGetMaxY([self.bookmarksTableView + convertRect:self.sharedState.tableView.frame + toView:nil]); + CGFloat shiftY = + tableBottom - keyboardTop + [BookmarkHomeSharedState keyboardSpacingPt]; + + if (shiftY >= 0) { + UIEdgeInsets previousContentInsets = + self.sharedState.tableView.contentInset; + // Shift the content inset to prevent the editing content from being hidden + // by the keyboard. + UIEdgeInsets contentInsets = + UIEdgeInsetsMake(previousContentInsets.top, 0.0, shiftY, 0.0); + self.sharedState.tableView.contentInset = contentInsets; + self.sharedState.tableView.scrollIndicatorInsets = contentInsets; + } +} + +// Called when the UIKeyboardWillHideNotification is sent +- (void)keyboardWillBeHidden:(NSNotification*)aNotification { + if (![self isAtTopOfNavigation:self.bookmarksTableView]) { + return; + } + UIEdgeInsets previousContentInsets = self.sharedState.tableView.contentInset; + // Restore the content inset now that the keyboard has been hidden. + UIEdgeInsets contentInsets = + UIEdgeInsetsMake(previousContentInsets.top, 0, 0, 0); + self.sharedState.tableView.contentInset = contentInsets; + self.sharedState.tableView.scrollIndicatorInsets = contentInsets; } #pragma mark - SigninPresenter @@ -1323,7 +1485,7 @@ UITableViewCell* cell = [self.sharedState.tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; - [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; + [item configureCell:cell withStyler:self.tableViewStyler]; if (item.type == BookmarkHomeItemTypeBookmark) { BookmarkHomeNodeItem* nodeItem =
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm index e06f718..755be44d 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm
@@ -9,6 +9,7 @@ #include "base/strings/sys_string_conversions.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/favicon/core/fallback_url_util.h" +#include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" #include "components/favicon_base/favicon_types.h" @@ -144,39 +145,18 @@ // Create and setup tableview. self.sharedState.tableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain]; - self.sharedState.tableView.accessibilityIdentifier = @"bookmarksTableView"; - if (@available(iOS 11.0, *)) { - self.sharedState.tableView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } - self.sharedState.tableView.estimatedRowHeight = - [BookmarkHomeSharedState cellHeightPt]; - self.sharedState.tableView.separatorStyle = - UITableViewCellSeparatorStyleNone; // Remove extra rows. self.sharedState.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.sharedState.tableView.allowsMultipleSelectionDuringEditing = YES; - UILongPressGestureRecognizer* longPressRecognizer = - [[UILongPressGestureRecognizer alloc] - initWithTarget:self - action:@selector(handleLongPress:)]; - longPressRecognizer.numberOfTouchesRequired = 1; - longPressRecognizer.delegate = self; - [self.sharedState.tableView addGestureRecognizer:longPressRecognizer]; [self addSubview:self.sharedState.tableView]; [self bringSubviewToFront:self.sharedState.tableView]; - [self registerForKeyboardNotifications]; [self showEmptyOrLoadingSpinnerBackgroundIfNeeded]; } return self; } - (void)dealloc { - [self removeKeyboardObservers]; - _sharedState.tableView.dataSource = nil; - _sharedState.tableView.delegate = nil; _faviconTaskTracker.TryCancelAll(); } @@ -430,44 +410,6 @@ [self loadFaviconAtIndexPath:indexPath continueToGoogleServer:NO]; } -#pragma mark - Gesture recognizer - -- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer - shouldReceiveTouch:(UITouch*)touch { - // Ignore long press in edit mode. - if (self.sharedState.currentlyInEditMode) { - return NO; - } - return YES; -} - -#pragma mark - Private - -- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer { - if (self.sharedState.currentlyInEditMode || - gestureRecognizer.state != UIGestureRecognizerStateBegan) { - return; - } - CGPoint touchPoint = - [gestureRecognizer locationInView:self.sharedState.tableView]; - NSIndexPath* indexPath = - [self.sharedState.tableView indexPathForRowAtPoint:touchPoint]; - if (indexPath == nil || [self.sharedState.tableViewModel - sectionIdentifierForSection:indexPath.section] != - BookmarkHomeSectionIdentifierBookmarks) { - return; - } - - const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; - // Disable the long press gesture if it is a permanent node (not an URL or - // Folder). - if (!node || ![self isUrlOrFolder:node]) { - return; - } - - [self.delegate bookmarkTableView:self showContextMenuForNode:node]; -} - // Row selection of the tableView will be cleared after reloadData. This // function is used to restore the row selection. It also updates editNodes in // case some selected nodes are removed. @@ -816,7 +758,9 @@ strongSelf.sharedState.faviconDownloadCount++; IOSChromeLargeIconServiceFactory::GetForBrowserState(self.browserState) ->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - node->url(), minFaviconSizeInPixel, desiredFaviconSizeInPixel, + favicon::FaviconServerFetcherParams::CreateForMobile( + node->url(), minFaviconSizeInPixel, + desiredFaviconSizeInPixel), /*may_page_url_be_private=*/true, kTrafficAnnotation, base::BindBlockArc(faviconLoadedFromServerBlock)); } @@ -839,71 +783,6 @@ node->type() == BookmarkNode::FOLDER; } -#pragma mark - Keyboard - -- (void)registerForKeyboardNotifications { - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(keyboardWasShown:) - name:UIKeyboardDidShowNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(keyboardWillBeHidden:) - name:UIKeyboardWillHideNotification - object:nil]; -} - -- (void)removeKeyboardObservers { - NSNotificationCenter* notificationCenter = - [NSNotificationCenter defaultCenter]; - [notificationCenter removeObserver:self - name:UIKeyboardDidShowNotification - object:nil]; - [notificationCenter removeObserver:self - name:UIKeyboardWillHideNotification - object:nil]; -} - -// Called when the UIKeyboardDidShowNotification is sent -- (void)keyboardWasShown:(NSNotification*)aNotification { - if (![self.delegate isAtTopOfNavigation:self]) { - return; - } - NSDictionary* info = [aNotification userInfo]; - CGFloat keyboardTop = - [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y; - CGFloat tableBottom = CGRectGetMaxY( - [self convertRect:self.sharedState.tableView.frame toView:nil]); - CGFloat shiftY = - tableBottom - keyboardTop + [BookmarkHomeSharedState keyboardSpacingPt]; - - if (shiftY >= 0) { - UIEdgeInsets previousContentInsets = - self.sharedState.tableView.contentInset; - // Shift the content inset to prevent the editing content from being hidden - // by the keyboard. - UIEdgeInsets contentInsets = - UIEdgeInsetsMake(previousContentInsets.top, 0.0, shiftY, 0.0); - self.sharedState.tableView.contentInset = contentInsets; - self.sharedState.tableView.scrollIndicatorInsets = contentInsets; - } -} - -// Called when the UIKeyboardWillHideNotification is sent -- (void)keyboardWillBeHidden:(NSNotification*)aNotification { - if (![self.delegate isAtTopOfNavigation:self]) { - return; - } - UIEdgeInsets previousContentInsets = self.sharedState.tableView.contentInset; - // Restore the content inset now that the keyboard has been hidden. - UIEdgeInsets contentInsets = - UIEdgeInsetsMake(previousContentInsets.top, 0, 0, 0); - self.sharedState.tableView.contentInset = contentInsets; - self.sharedState.tableView.scrollIndicatorInsets = contentInsets; -} - #pragma mark - SyncedSessionsObserver - (void)reloadSessions {
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm index bc9d4c9d..3a5750e 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -93,7 +93,7 @@ CGFloat yOffset = 0; if (IsUIRefreshPhase1Enabled()) { if (IsIPadIdiom()) { - yOffset = -89.0; + yOffset = -104.0; } else { yOffset = -48.0; }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm index 772912f1..f3fb6ea5 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm
@@ -24,8 +24,12 @@ namespace { // Returns whether fullscreen should be disabled for |web_state|'s SSL status. // This will return true if the visible NavigationItem's SSL has a broken -// security style or is showing mixed content. +// security style or is showing mixed content. If the UI refresh is enabled, +// fullscreen does not need to be disabled for certificate issues, as the +// omnibox security indicator is never fully hidden in fullscreen mode. bool ShouldDisableFullscreenForWebStateSSL(web::WebState* web_state) { + if (IsUIRefreshPhase1Enabled()) + return false; if (!web_state) return false; web::NavigationManager* manager = web_state->GetNavigationManager(); @@ -125,12 +129,12 @@ } void FullscreenWebStateObserver::SetIsLoading(bool loading) { - if (IsUIRefreshPhase1Enabled()) - return; - - if (!!loading_disabler_.get() == loading) - return; - loading_disabler_ = - loading ? std::make_unique<ScopedFullscreenDisabler>(controller_) - : nullptr; + if (IsUIRefreshPhase1Enabled()) { + if (loading) + controller_->ResetModel(); + } else { + loading_disabler_ = + loading ? std::make_unique<ScopedFullscreenDisabler>(controller_) + : nullptr; + } }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm index b36b85b..062211df 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm
@@ -110,6 +110,9 @@ // Tests that the model is disabled when the SSL status is broken. TEST_F(FullscreenWebStateObserverTest, DisableForBrokenSSL) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(kUIRefreshPhase1); + std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create(); item->GetSSL().security_style = web::SECURITY_STYLE_AUTHENTICATION_BROKEN; navigation_manager().SetVisibleItem(item.get()); @@ -120,3 +123,21 @@ web_state().OnVisibleSecurityStateChanged(); EXPECT_TRUE(model().enabled()); } + +// Tests that the model remains enabled when the SSL status is broken and the +// UI refresh flag is enabled. +TEST_F(FullscreenWebStateObserverTest, + DisableForBrokenSSLWithUIRefreshEnabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(kUIRefreshPhase1); + + std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create(); + item->GetSSL().security_style = web::SECURITY_STYLE_AUTHENTICATION_BROKEN; + navigation_manager().SetVisibleItem(item.get()); + EXPECT_TRUE(model().enabled()); + web_state().OnVisibleSecurityStateChanged(); + EXPECT_TRUE(model().enabled()); + navigation_manager().SetVisibleItem(nullptr); + web_state().OnVisibleSecurityStateChanged(); + EXPECT_TRUE(model().enabled()); +}
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm index ae5b405..3cecfb57 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
@@ -5,8 +5,10 @@ #import "ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h" #import <CoreGraphics/CoreGraphics.h> +#include <algorithm> #include "base/logging.h" +#include "base/numerics/ranges.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -65,7 +67,8 @@ // Points that the slider overhangs a segment on each side, or 0 if the slider // is narrower than a segment. -const CGFloat kSliderOverhang = MAX((kSliderWidth - kSegmentWidth) / 2.0, 0.0); +const CGFloat kSliderOverhang = + std::max((kSliderWidth - kSegmentWidth) / 2.0, 0.0); // Width of the separator bars between segments. const CGFloat kSeparatorWidth = 1.0; @@ -75,7 +78,7 @@ // Overall height of the control -- the larger of the slider and segment // heights. -const CGFloat kOverallHeight = MAX(kSliderHeight, kSegmentHeight); +const CGFloat kOverallHeight = std::max(kSliderHeight, kSegmentHeight); // Overall width of the control -- the background width plusand twice // the slider overhang. const CGFloat kOverallWidth = kBackgroundWidth + 2 * kSliderOverhang; @@ -191,7 +194,7 @@ - (void)setSliderPosition:(CGFloat)sliderPosition { // Clamp |selectionOffset| to (0.0 - 1.0). - sliderPosition = MIN(MAX(0.0, sliderPosition), 1.0); + sliderPosition = base::ClampToRange<CGFloat>(sliderPosition, 0.0, 1.0); CGPoint center = self.sliderView.center; center.x = self.sliderOrigin + self.sliderRange * sliderPosition; self.sliderView.center = center; @@ -248,7 +251,7 @@ // is moving across two segments. CGFloat offsetDelta = abs(newPosition - self.sliderPosition); NSTimeInterval duration = offsetDelta * kSliderMoveDuration; - [UIView animateWithDuration:MIN(duration, kSliderMoveDuration) + [UIView animateWithDuration:std::min(duration, kSliderMoveDuration) animations:^{ self.sliderPosition = newPosition; }];
diff --git a/ios/chrome/browser/ui/table_view/BUILD.gn b/ios/chrome/browser/ui/table_view/BUILD.gn index 7ab4b348..67ed7b59 100644 --- a/ios/chrome/browser/ui/table_view/BUILD.gn +++ b/ios/chrome/browser/ui/table_view/BUILD.gn
@@ -5,6 +5,7 @@ source_set("table_view") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "chrome_table_view_consumer.h", "chrome_table_view_controller.h", "chrome_table_view_controller.mm", "table_view_model.h",
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h b/ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h new file mode 100644 index 0000000..b95b525 --- /dev/null +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h
@@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TABLE_VIEW_CHROME_TABLE_VIEW_CONSUMER_H_ +#define IOS_CHROME_BROWSER_UI_TABLE_VIEW_CHROME_TABLE_VIEW_CONSUMER_H_ + +#import <Foundation/Foundation.h> + +// ChromeTableViewConsumer declares a basic set of methods that allow table view +// mediators to update their UI. Individual features can extend this protocol to +// add feature-specific methods. +@protocol ChromeTableViewConsumer<NSObject> + +// Reconfigures the cells corresponding to the given |items| by calling +// |configureCell:| on each cell. +- (void)reconfigureCellsForItems:(NSArray*)items; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TABLE_VIEW_CHROME_TABLE_VIEW_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h index 98e16dff..6fa9384e 100644 --- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
@@ -8,6 +8,7 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/material_components/app_bar_presenting.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h" #import "ios/chrome/browser/ui/table_view/table_view_model.h" @class ChromeTableViewStyler; @@ -19,7 +20,8 @@ }; // Chrome-specific TableViewController. -@interface ChromeTableViewController : UITableViewController<AppBarPresenting> +@interface ChromeTableViewController + : UITableViewController<AppBarPresenting, ChromeTableViewConsumer> // The model of this controller. @property(nonatomic, readonly, strong) @@ -45,9 +47,8 @@ // override this method in order to get a clean tableViewModel. - (void)loadModel NS_REQUIRES_SUPER; -// Reconfigures the cells corresponding to the given |items| by calling -// |configureCell:| on each cell. -- (void)reconfigureCellsForItems:(NSArray*)items; +// Methods for reconfiguring and reloading the table view are provided by +// ChromeTableViewConsumer. #pragma mark UIScrollViewDelegate
diff --git a/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm b/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm index ab1af6a..148d83d 100644 --- a/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm +++ b/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm
@@ -97,12 +97,11 @@ GetApplicationContext()->GetNetLog()->net_export_file_writer()), state_observer_manager_(this), weak_ptr_factory_(this) { - file_writer_->Initialize( - web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)); + file_writer_->Initialize(); } NetExportMessageHandler::~NetExportMessageHandler() { - file_writer_->StopNetLog(nullptr, nullptr); + file_writer_->StopNetLog(nullptr); } void NetExportMessageHandler::RegisterMessages() { @@ -156,14 +155,12 @@ file_writer_->StartNetLog( base::FilePath(), capture_mode, max_log_file_size, base::CommandLine::ForCurrentProcess()->GetCommandLineString(), - GetChannelString(), - {GetApplicationContext()->GetSystemURLRequestContext()}); + GetChannelString(), GetApplicationContext()->GetSystemNetworkContext()); } void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) { DCHECK_CURRENTLY_ON(web::WebThread::UI); - file_writer_->StopNetLog( - nullptr, GetApplicationContext()->GetSystemURLRequestContext()); + file_writer_->StopNetLog(nullptr); } void NetExportMessageHandler::OnSendNetLog(const base::ListValue* list) {
diff --git a/ios/chrome/browser/web/error_page_egtest.mm b/ios/chrome/browser/web/error_page_egtest.mm index e191fae8..3ff690f 100644 --- a/ios/chrome/browser/web/error_page_egtest.mm +++ b/ios/chrome/browser/web/error_page_egtest.mm
@@ -93,6 +93,7 @@ // Sucessfully loads the page, goes back, stops the server, goes forward and // reloads. +// TODO(crbug.com/840489): Remove this test. - (void)testGoForwardAfterServerIsDownAndReload { // First page loads sucessfully. [ChromeEarlGrey loadURL:self.testServer->GetURL("/echo")]; @@ -127,6 +128,7 @@ // Sucessfully loads the page, then loads the URL which fails to load, then // sucessfully goes back to the first page. +// TODO(crbug.com/840489): Remove this test. - (void)testGoBackFromErrorPage { // First page loads sucessfully. [ChromeEarlGrey loadURL:self.testServer->GetURL("/echo")]; @@ -146,6 +148,7 @@ } // Loads the URL which redirects to unresponsive server. +// TODO(crbug.com/840489): Remove this test. - (void)testRedirectToFailingURL { // No response leads to ERR_INTERNET_DISCONNECTED error. self.serverRespondsWithContent = NO; @@ -160,6 +163,7 @@ // Loads the page with iframe, and that iframe fails to load. There should be no // error page if the main frame has sucessfully loaded. +// TODO(crbug.com/840489): Remove this test. - (void)testErrorPageInIFrame { [ChromeEarlGrey loadURL:self.testServer->GetURL("/iframe?echo-query")]; [ChromeEarlGrey
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm index 270c8a2..9109f7b 100644 --- a/ios/components/io_thread/ios_io_thread.mm +++ b/ios/components/io_thread/ios_io_thread.mm
@@ -320,7 +320,7 @@ // Add built-in logs ct_verifier->AddLogs(ct_logs); - globals_->ct_policy_enforcer.reset(new net::CTPolicyEnforcer()); + globals_->ct_policy_enforcer.reset(new net::DefaultCTPolicyEnforcer()); globals_->ssl_config_service = new net::SSLConfigServiceDefaults();
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index dfe4f67..cd4d8a1 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -543,6 +543,7 @@ deps = [ ":web", "//base/test:test_support", + "//ios/testing:embedded_test_server_support", "//ios/testing:http_server_bundle_data", "//ios/testing:ios_test_support", "//ios/web:resources_grit", @@ -570,6 +571,7 @@ "public/test/http_server_inttest.mm", "test/run_all_unittests.cc", "url_loader_inttest.mm", + "web_state/error_page_inttest.mm", "web_state/favicon_callbacks_inttest.mm", "web_state/http_auth_inttest.mm", "web_state/navigation_and_load_callbacks_inttest.mm",
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm index 9494ae4..868d33a 100644 --- a/ios/web/shell/shell_url_request_context_getter.mm +++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -103,7 +103,7 @@ storage_->set_cert_transparency_verifier( base::WrapUnique(new net::MultiLogCTVerifier)); storage_->set_ct_policy_enforcer( - base::WrapUnique(new net::CTPolicyEnforcer)); + base::WrapUnique(new net::DefaultCTPolicyEnforcer)); transport_security_persister_ = std::make_unique<net::TransportSecurityPersister>( url_request_context_->transport_security_state(), base_path_,
diff --git a/ios/web/web_state/error_page_inttest.mm b/ios/web/web_state/error_page_inttest.mm new file mode 100644 index 0000000..03510160 --- /dev/null +++ b/ios/web/web_state/error_page_inttest.mm
@@ -0,0 +1,170 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_feature_list.h" +#include "ios/testing/embedded_test_server_handlers.h" +#import "ios/testing/wait_util.h" +#include "ios/web/public/features.h" +#import "ios/web/public/navigation_manager.h" +#include "ios/web/public/reload_type.h" +#import "ios/web/public/test/navigation_test_util.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#import "ios/web/public/test/web_view_content_test_util.h" +#import "ios/web/public/web_client.h" +#import "ios/web/public/web_state/web_state.h" +#include "net/test/embedded_test_server/default_handlers.h" +#include "net/test/embedded_test_server/request_handler_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using testing::WaitUntilConditionOrTimeout; + +namespace web { + +namespace { +// Overrides PrepareErrorPage to render all important arguments. +class TestWebClient : public WebClient { + void PrepareErrorPage(NSError* error, + bool is_post, + bool is_off_the_record, + NSString** error_html) override { + *error_html = + [NSString stringWithFormat:@"domain: %@ code: %ld post: %d otr: %d", + error.domain, static_cast<long>(error.code), + is_post, is_off_the_record]; + } +}; +} // namespace + +// Test fixture for error page testing. Error page simply renders the arguments +// passed to WebClient::PrepareErrorPage, so the test also acts as integration +// test for PrepareErrorPage WebClient method. +class ErrorPageTest : public WebTestWithWebState { + protected: + ErrorPageTest() : WebTestWithWebState(std::make_unique<TestWebClient>()) { + RegisterDefaultHandlers(&server_); + server_.RegisterRequestHandler(base::BindRepeating( + &net::test_server::HandlePrefixedRequest, "/echo-query", + base::BindRepeating(&testing::HandleEchoQueryOrCloseSocket, + base::ConstRef(server_responds_with_content_)))); + server_.RegisterRequestHandler( + base::BindRepeating(&net::test_server::HandlePrefixedRequest, "/iframe", + base::BindRepeating(&testing::HandleIFrame))); + scoped_feature_list_.InitAndEnableFeature(features::kWebErrorPages); + } + + void SetUp() override { + WebTestWithWebState::SetUp(); + ASSERT_TRUE(server_.Start()); + } + + net::EmbeddedTestServer server_; + bool server_responds_with_content_ = false; + + private: + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(ErrorPageTest); +}; + +// Loads the URL which fails to load, then sucessfully reloads the page. +TEST_F(ErrorPageTest, ReloadErrorPage) { + // No response leads to -1005 error code. + server_responds_with_content_ = false; + test::LoadUrl(web_state(), server_.GetURL("/echo-query?foo")); + ASSERT_TRUE(test::WaitForWebViewContainingText( + web_state(), "domain: NSURLErrorDomain code: -1005 post: 0 otr: 1")); + + // Reload the page, which should load without errors. + server_responds_with_content_ = true; + web_state()->GetNavigationManager()->Reload(ReloadType::NORMAL, + /*check_for_repost=*/false); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo")); +} + +// Sucessfully loads the page, stops the server and reloads the page. +TEST_F(ErrorPageTest, ReloadPageAfterServerIsDown) { + // Sucessfully load the page. + server_responds_with_content_ = true; + test::LoadUrl(web_state(), server_.GetURL("/echo-query?foo")); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo")); + + // Reload the page, no response leads to -1005 error code. + server_responds_with_content_ = false; + web_state()->GetNavigationManager()->Reload(ReloadType::NORMAL, + /*check_for_repost=*/false); + ASSERT_TRUE(test::WaitForWebViewContainingText( + web_state(), "domain: NSURLErrorDomain code: -1005 post: 0 otr: 1")); +} + +// Sucessfully loads the page, goes back, stops the server, goes forward and +// reloads. +TEST_F(ErrorPageTest, GoForwardAfterServerIsDownAndReload) { + // First page loads sucessfully. + test::LoadUrl(web_state(), server_.GetURL("/echo")); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo")); + + // Second page loads sucessfully. + server_responds_with_content_ = true; + test::LoadUrl(web_state(), server_.GetURL("/echo-query?foo")); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo")); + + // Go back to the first page. + web_state()->GetNavigationManager()->GoBack(); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo")); + +#if TARGET_IPHONE_SIMULATOR + // Go forward. The response will be retrieved from the page cache and will not + // present the error page. Page cache may not always exist on device (which is + // more memory constrained), so this part of the test is simulator-only. + server_responds_with_content_ = false; + web_state()->GetNavigationManager()->GoForward(); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "foo")); + + // Reload bypasses the cache. + web_state()->GetNavigationManager()->Reload(ReloadType::NORMAL, + /*check_for_repost=*/false); + ASSERT_TRUE(test::WaitForWebViewContainingText( + web_state(), "domain: NSURLErrorDomain code: -1005 post: 0 otr: 1")); +#endif // TARGET_IPHONE_SIMULATOR +} + +// Sucessfully loads the page, then loads the URL which fails to load, then +// sucessfully goes back to the first page. +TEST_F(ErrorPageTest, GoBackFromErrorPage) { + // First page loads sucessfully. + test::LoadUrl(web_state(), server_.GetURL("/echo")); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo")); + + // Second page fails to load. + test::LoadUrl(web_state(), server_.GetURL("/close-socket")); + ASSERT_TRUE(test::WaitForWebViewContainingText( + web_state(), "domain: NSURLErrorDomain code: -1005 post: 0 otr: 1")); + + // Going back should sucessfully load the first page. + web_state()->GetNavigationManager()->GoBack(); + ASSERT_TRUE(test::WaitForWebViewContainingText(web_state(), "Echo")); +} + +// Loads the URL which redirects to unresponsive server. +TEST_F(ErrorPageTest, RedirectToFailingURL) { + // No response leads to -1005 error code. + server_responds_with_content_ = false; + test::LoadUrl(web_state(), server_.GetURL("/server-redirect?echo-query")); + ASSERT_TRUE(test::WaitForWebViewContainingText( + web_state(), "domain: NSURLErrorDomain code: -1005 post: 0 otr: 1")); +} + +// Loads the page with iframe, and that iframe fails to load. There should be no +// error page if the main frame has sucessfully loaded. +TEST_F(ErrorPageTest, ErrorPageInIFrame) { + test::LoadUrl(web_state(), server_.GetURL("/iframe?echo-query")); + EXPECT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForPageLoadTimeout, ^{ + return test::IsWebViewContainingCssSelector(web_state(), + "iframe[src*='echo-query']"); + })); +} + +} // namespace web
diff --git a/ios/web/web_state/navigation_and_load_callbacks_inttest.mm b/ios/web/web_state/navigation_and_load_callbacks_inttest.mm index 715db95f..90520ae 100644 --- a/ios/web/web_state/navigation_and_load_callbacks_inttest.mm +++ b/ios/web/web_state/navigation_and_load_callbacks_inttest.mm
@@ -663,15 +663,9 @@ // Reload web page. NavigationContext* context = nullptr; int32_t nav_id = 0; - if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { - EXPECT_CALL(*decider_, ShouldAllowRequest(_, _, /*from_main_frame=*/true)) - .WillOnce(Return(true)); - EXPECT_CALL(observer_, DidStartLoading(web_state())); - } else { - EXPECT_CALL(observer_, DidStartLoading(web_state())); - EXPECT_CALL(*decider_, ShouldAllowRequest(_, _, /*from_main_frame=*/true)) - .WillOnce(Return(true)); - } + EXPECT_CALL(observer_, DidStartLoading(web_state())); + EXPECT_CALL(*decider_, ShouldAllowRequest(_, _, /*from_main_frame=*/true)) + .WillOnce(Return(true)); EXPECT_CALL(observer_, DidStartNavigation(web_state(), _)) .WillOnce( VerifyReloadStartedContext(web_state(), url, &context, &nav_id));
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index b8026770..ddb6478 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1946,7 +1946,16 @@ // New navigation manager can delegate directly to WKWebView to reload // for non-app-specific URLs. The necessary navigation states will be // updated in WKNavigationDelegate callbacks. - [_webView reload]; + WKNavigation* navigation = [_webView reload]; + [_navigationStates setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; + std::unique_ptr<web::NavigationContextImpl> navigationContext = [self + registerLoadRequestForURL:URL + referrer:self.currentNavItemReferrer + transition:ui::PageTransition::PAGE_TRANSITION_RELOAD + sameDocumentNavigation:NO]; + [_navigationStates setContext:std::move(navigationContext) + forNavigation:navigation]; } else { [self loadCurrentURL]; }
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm index 347023b3..2c365e7 100644 --- a/ios/web_view/internal/web_view_url_request_context_getter.mm +++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -17,6 +17,7 @@ #include "ios/web_view/internal/web_view_network_delegate.h" #include "net/base/cache_type.h" #include "net/cert/cert_verifier.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cert/multi_log_ct_verifier.h" #include "net/dns/host_resolver.h" #include "net/extras/sqlite/sqlite_channel_id_store.h" @@ -103,7 +104,7 @@ storage_->set_cert_transparency_verifier( base::WrapUnique(new net::MultiLogCTVerifier)); storage_->set_ct_policy_enforcer( - base::WrapUnique(new net::CTPolicyEnforcer)); + base::WrapUnique(new net::DefaultCTPolicyEnforcer)); transport_security_persister_ = std::make_unique<net::TransportSecurityPersister>( url_request_context_->transport_security_state(), base_path_,
diff --git a/media/audio/audio_input_controller_unittest.cc b/media/audio/audio_input_controller_unittest.cc index 1b169f1..11787db 100644 --- a/media/audio/audio_input_controller_unittest.cc +++ b/media/audio/audio_input_controller_unittest.cc
@@ -82,14 +82,14 @@ MOCK_METHOD0(Close, void()); }; -class MockUserInputMonitor : public UserInputMonitorBase { +class MockUserInputMonitor : public UserInputMonitor { public: MockUserInputMonitor() = default; uint32_t GetKeyPressCount() const override { return 0; } - MOCK_METHOD0(StartKeyboardMonitoring, void()); - MOCK_METHOD0(StopKeyboardMonitoring, void()); + MOCK_METHOD0(EnableKeyPressMonitoring, void()); + MOCK_METHOD0(DisableKeyPressMonitoring, void()); }; class MockAudioInputStream : public AudioInputStream { @@ -185,13 +185,13 @@ .Times(AtLeast(10)) .WillRepeatedly( CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner())); - EXPECT_CALL(user_input_monitor_, StartKeyboardMonitoring()); + EXPECT_CALL(user_input_monitor_, EnableKeyPressMonitoring()); controller_->Record(); // Record and wait until ten Write() callbacks are received. base::RunLoop().Run(); - EXPECT_CALL(user_input_monitor_, StopKeyboardMonitoring()); + EXPECT_CALL(user_input_monitor_, DisableKeyPressMonitoring()); EXPECT_CALL(sync_writer_, Close()); CloseAudioController(); } @@ -212,10 +212,10 @@ CreateAudioController(); ASSERT_TRUE(controller_.get()); - EXPECT_CALL(user_input_monitor_, StartKeyboardMonitoring()); + EXPECT_CALL(user_input_monitor_, EnableKeyPressMonitoring()); controller_->Record(); - EXPECT_CALL(user_input_monitor_, StopKeyboardMonitoring()); + EXPECT_CALL(user_input_monitor_, DisableKeyPressMonitoring()); EXPECT_CALL(sync_writer_, Close()); CloseAudioController();
diff --git a/media/base/user_input_monitor.cc b/media/base/user_input_monitor.cc index 4528807..5343138 100644 --- a/media/base/user_input_monitor.cc +++ b/media/base/user_input_monitor.cc
@@ -4,6 +4,8 @@ #include "media/base/user_input_monitor.h" +#include <utility> + #include "base/atomicops.h" #include "base/logging.h" #include "base/single_thread_task_runner.h" @@ -11,26 +13,28 @@ namespace media { uint32_t ReadKeyPressMonitorCount( - const base::ReadOnlySharedMemoryMapping& shmem_mapping) { - if (!shmem_mapping.IsValid()) + const base::ReadOnlySharedMemoryMapping& readonly_mapping) { + if (!readonly_mapping.IsValid()) return 0; // No ordering constraints between Load/Store operations, a temporary // inconsistent value is fine. return base::subtle::NoBarrier_Load( - reinterpret_cast<const base::subtle::Atomic32*>(shmem_mapping.memory())); + reinterpret_cast<const base::subtle::Atomic32*>( + readonly_mapping.memory())); } void WriteKeyPressMonitorCount( - const base::WritableSharedMemoryMapping& shmem_mapping, + const base::WritableSharedMemoryMapping& writable_mapping, uint32_t count) { - if (!shmem_mapping.IsValid()) + if (!writable_mapping.IsValid()) return; // No ordering constraints between Load/Store operations, a temporary // inconsistent value is fine. base::subtle::NoBarrier_Store( - reinterpret_cast<base::subtle::Atomic32*>(shmem_mapping.memory()), count); + reinterpret_cast<base::subtle::Atomic32*>(writable_mapping.memory()), + count); } #ifdef DISABLE_USER_INPUT_MONITOR @@ -45,26 +49,48 @@ UserInputMonitor::~UserInputMonitor() = default; -UserInputMonitorBase::UserInputMonitorBase() = default; +UserInputMonitorBase::UserInputMonitorBase() { + DETACH_FROM_SEQUENCE(owning_sequence_); +} UserInputMonitorBase::~UserInputMonitorBase() { DCHECK_EQ(0u, references_); } void UserInputMonitorBase::EnableKeyPressMonitoring() { - base::AutoLock auto_lock(lock_); - ++references_; - if (references_ == 1) { + DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); + if (++references_ == 1) { StartKeyboardMonitoring(); DVLOG(2) << "Started keyboard monitoring."; } } +base::ReadOnlySharedMemoryRegion +UserInputMonitorBase::EnableKeyPressMonitoringWithMapping() { + DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); + if (++references_ == 1) { + base::MappedReadOnlyRegion shmem = + base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)); + if (!shmem.region.IsValid() || !shmem.mapping.IsValid()) { + DVLOG(2) << "Error mapping key press count shmem."; + return base::ReadOnlySharedMemoryRegion(); + } + + key_press_count_region_ = + base::ReadOnlySharedMemoryRegion(std::move(shmem.region)); + WriteKeyPressMonitorCount(shmem.mapping, 0u); + StartKeyboardMonitoring(std::move(shmem.mapping)); + DVLOG(2) << "Started keyboard monitoring."; + } + + return key_press_count_region_.Duplicate(); +} + void UserInputMonitorBase::DisableKeyPressMonitoring() { - base::AutoLock auto_lock(lock_); + DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_); DCHECK_NE(references_, 0u); - --references_; - if (references_ == 0) { + if (--references_ == 0) { + key_press_count_region_ = base::ReadOnlySharedMemoryRegion(); StopKeyboardMonitoring(); DVLOG(2) << "Stopped keyboard monitoring."; }
diff --git a/media/base/user_input_monitor.h b/media/base/user_input_monitor.h index 6559879e..7b774949 100644 --- a/media/base/user_input_monitor.h +++ b/media/base/user_input_monitor.h
@@ -58,27 +58,32 @@ }; // Monitors and notifies about keyboard events. -// Thread safe. class MEDIA_EXPORT UserInputMonitorBase : public UserInputMonitor { public: UserInputMonitorBase(); ~UserInputMonitorBase() override; - // A caller must call EnableKeyPressMonitoring and - // DisableKeyPressMonitoring in pair. + // A caller must call EnableKeyPressMonitoring(WithMapping) and + // DisableKeyPressMonitoring in pair on the same sequence. void EnableKeyPressMonitoring() override; void DisableKeyPressMonitoring() override; + // Initializes a MappedReadOnlyRegion storing key press count. Returns a + // readonly region to the mapping and passes the writable mapping to platform + // specific implementation, to update key press count. If monitoring is + // already enabled, it only returns a handle to readonly region. + base::ReadOnlySharedMemoryRegion EnableKeyPressMonitoringWithMapping(); + private: virtual void StartKeyboardMonitoring() = 0; + virtual void StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) = 0; virtual void StopKeyboardMonitoring() = 0; - // Aquired in EnableKeyPressMonitoring()/DisableKeyPressMonitoring(). Together - // with |references_| updated under lock, it is used to ensure operation - // ordering for start/stop keyboard monitoring, i.e. start is always followed - // by stop and start is only called when keyboard monitoring is stopped. - base::Lock lock_; size_t references_ = 0; + base::ReadOnlySharedMemoryRegion key_press_count_region_; + + SEQUENCE_CHECKER(owning_sequence_); DISALLOW_COPY_AND_ASSIGN(UserInputMonitorBase); };
diff --git a/media/base/user_input_monitor_linux.cc b/media/base/user_input_monitor_linux.cc index 8435739..b52df992 100644 --- a/media/base/user_input_monitor_linux.cc +++ b/media/base/user_input_monitor_linux.cc
@@ -43,6 +43,7 @@ uint32_t GetKeyPressCount() const; void StartMonitor(); + void StartMonitorWithMapping(base::WritableSharedMemoryMapping mapping); void StopMonitor(); private: @@ -54,6 +55,9 @@ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + // Used for sharing key press count value. + std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_; + // // The following members should only be accessed on the IO thread. // @@ -79,6 +83,8 @@ private: // Private UserInputMonitor overrides. void StartKeyboardMonitoring() override; + void StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) override; void StopKeyboardMonitoring() override; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; @@ -192,6 +198,13 @@ OnXEvent(); } +void UserInputMonitorLinuxCore::StartMonitorWithMapping( + base::WritableSharedMemoryMapping mapping) { + StartMonitor(); + key_press_count_mapping_ = + std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping)); +} + void UserInputMonitorLinuxCore::StopMonitor() { DCHECK(io_task_runner_->BelongsToCurrentThread()); @@ -219,6 +232,8 @@ x_control_display_ = NULL; } + key_press_count_mapping_.reset(); + // Stop observing message loop destruction if no event is being monitored. base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this); } @@ -243,6 +258,10 @@ XkbKeycodeToKeysym(x_control_display_, event->u.u.detail, 0, 0); ui::KeyboardCode key_code = ui::KeyboardCodeFromXKeysym(key_sym); counter_.OnKeyboardEvent(type, key_code); + + // Update count value in shared memory. + if (key_press_count_mapping_) + WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount()); } // static @@ -279,6 +298,14 @@ core_->AsWeakPtr())); } +void UserInputMonitorLinux::StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) { + io_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&UserInputMonitorLinuxCore::StartMonitorWithMapping, + core_->AsWeakPtr(), std::move(mapping))); +} + void UserInputMonitorLinux::StopKeyboardMonitoring() { io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StopMonitor,
diff --git a/media/base/user_input_monitor_mac.cc b/media/base/user_input_monitor_mac.cc index f45ec6ce..585cb01 100644 --- a/media/base/user_input_monitor_mac.cc +++ b/media/base/user_input_monitor_mac.cc
@@ -9,10 +9,16 @@ #include <memory> #include "base/macros.h" +#include "base/timer/timer.h" namespace media { namespace { +// Update key press count in shared memory twice as frequent as +// AudioInputController::AudioCallback::OnData() callback for WebRTC. +constexpr base::TimeDelta kUpdateKeyPressCountIntervalMs = + base::TimeDelta::FromMilliseconds(5); + class UserInputMonitorMac : public UserInputMonitorBase { public: UserInputMonitorMac(); @@ -22,8 +28,18 @@ private: void StartKeyboardMonitoring() override; + void StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) override; void StopKeyboardMonitoring() override; + void UpdateKeyPressCountShmem(); + + // Used for sharing key press count value. + std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_; + + // Timer for updating key press count in |key_press_count_mapping_|. + base::RepeatingTimer key_press_count_timer_; + DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac); }; @@ -40,7 +56,26 @@ void UserInputMonitorMac::StartKeyboardMonitoring() {} -void UserInputMonitorMac::StopKeyboardMonitoring() {} +void UserInputMonitorMac::StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) { + key_press_count_mapping_ = + std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping)); + key_press_count_timer_.Start(FROM_HERE, kUpdateKeyPressCountIntervalMs, this, + &UserInputMonitorMac::UpdateKeyPressCountShmem); +} + +void UserInputMonitorMac::StopKeyboardMonitoring() { + if (!key_press_count_mapping_) + return; + + key_press_count_timer_.AbandonAndStop(); + key_press_count_mapping_.reset(); +} + +void UserInputMonitorMac::UpdateKeyPressCountShmem() { + DCHECK(key_press_count_mapping_); + WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount()); +} } // namespace
diff --git a/media/base/user_input_monitor_unittest.cc b/media/base/user_input_monitor_unittest.cc index c974b85..dc4ea40 100644 --- a/media/base/user_input_monitor_unittest.cc +++ b/media/base/user_input_monitor_unittest.cc
@@ -9,6 +9,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_LINUX) @@ -38,7 +39,35 @@ base::RunLoop().RunUntilIdle(); } -TEST(UserInputMonitorTest, KeyPressMonitorReadWriteCount) { +TEST(UserInputMonitorTest, CreatePlatformSpecificWithMapping) { +#if defined(OS_LINUX) + base::MessageLoopForIO message_loop; + base::FileDescriptorWatcher file_descriptor_watcher(&message_loop); +#else + base::MessageLoopForUI message_loop; +#endif // defined(OS_LINUX) + + std::unique_ptr<UserInputMonitor> monitor = UserInputMonitor::Create( + message_loop.task_runner(), message_loop.task_runner()); + + if (!monitor) + return; + + base::ReadOnlySharedMemoryMapping readonly_mapping = + static_cast<UserInputMonitorBase*>(monitor.get()) + ->EnableKeyPressMonitoringWithMapping() + .Map(); + EXPECT_EQ(0u, ReadKeyPressMonitorCount(readonly_mapping)); + monitor->DisableKeyPressMonitoring(); + + monitor.reset(); + base::RunLoop().RunUntilIdle(); + + // Check that read only region remains valid after disable. + EXPECT_EQ(0u, ReadKeyPressMonitorCount(readonly_mapping)); +} + +TEST(UserInputMonitorTest, ReadWriteKeyPressMonitorCount) { std::unique_ptr<base::MappedReadOnlyRegion> shmem = std::make_unique<base::MappedReadOnlyRegion>( base::ReadOnlySharedMemoryRegion::Create(sizeof(uint32_t)));
diff --git a/media/base/user_input_monitor_win.cc b/media/base/user_input_monitor_win.cc index bc9f954..d42f98a2 100644 --- a/media/base/user_input_monitor_win.cc +++ b/media/base/user_input_monitor_win.cc
@@ -57,6 +57,7 @@ uint32_t GetKeyPressCount() const; void StartMonitor(); + void StartMonitorWithMapping(base::WritableSharedMemoryMapping mapping); void StopMonitor(); private: @@ -71,6 +72,9 @@ // Task runner on which |window_| is created. scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; + // Used for sharing key press count value. + std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_; + // These members are only accessed on the UI thread. std::unique_ptr<base::win::MessageWindow> window_; KeyboardEventCounter counter_; @@ -90,6 +94,8 @@ private: // Private UserInputMonitor overrides. void StartKeyboardMonitoring() override; + void StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) override; void StopKeyboardMonitoring() override; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; @@ -143,6 +149,13 @@ base::MessageLoopCurrent::Get()->AddDestructionObserver(this); } +void UserInputMonitorWinCore::StartMonitorWithMapping( + base::WritableSharedMemoryMapping mapping) { + StartMonitor(); + key_press_count_mapping_ = + std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping)); +} + void UserInputMonitorWinCore::StopMonitor() { DCHECK(ui_task_runner_->BelongsToCurrentThread()); @@ -159,6 +172,8 @@ window_ = nullptr; + key_press_count_mapping_.reset(); + // Stop observing message loop destruction if no event is being monitored. base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this); } @@ -196,6 +211,10 @@ ui::KeyboardCode key_code = ui::KeyboardCodeForWindowsKeyCode(input->data.keyboard.VKey); counter_.OnKeyboardEvent(event, key_code); + + // Update count value in shared memory. + if (key_press_count_mapping_) + WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount()); } return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); @@ -241,6 +260,14 @@ core_->AsWeakPtr())); } +void UserInputMonitorWin::StartKeyboardMonitoring( + base::WritableSharedMemoryMapping mapping) { + ui_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&UserInputMonitorWinCore::StartMonitorWithMapping, + core_->AsWeakPtr(), std::move(mapping))); +} + void UserInputMonitorWin::StopKeyboardMonitoring() { ui_task_runner_->PostTask( FROM_HERE, base::BindOnce(&UserInputMonitorWinCore::StopMonitor,
diff --git a/media/base/video_frame_metadata.h b/media/base/video_frame_metadata.h index bcd693e..e4bcbb11 100644 --- a/media/base/video_frame_metadata.h +++ b/media/base/video_frame_metadata.h
@@ -109,7 +109,7 @@ // if ALLOW_OVERLAY is set. However, it allows us to process the overlay // to see if it would have been promoted, if it were backed by a SurfaceView // instead. This lets us figure out when SurfaceViews are appropriate. - SURFACE_TEXTURE, + TEXTURE_OWNER, // Android only: if set, then this frame's resource would like to be // notified about its promotability to an overlay.
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 254366a..8d22210 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -2124,6 +2124,29 @@ client_->TimeChanged(); } +void WebMediaPlayerImpl::FlingingStarted() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(!disable_pipeline_auto_suspend_); + disable_pipeline_auto_suspend_ = true; + + // Capabilities reporting should only be performed for local playbacks. + video_decode_stats_reporter_.reset(); + + // Requests to restart media pipeline. A flinging renderer will be created via + // the |renderer_factory_selector_|. + ScheduleRestart(); +} + +void WebMediaPlayerImpl::FlingingStopped() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(disable_pipeline_auto_suspend_); + disable_pipeline_auto_suspend_ = false; + + CreateVideoDecodeStatsReporter(); + + ScheduleRestart(); +} + void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { DoSeek(base::TimeDelta::FromSecondsD(t), false); @@ -3061,6 +3084,7 @@ void WebMediaPlayerImpl::SwitchToRemoteRenderer( const std::string& remote_device_friendly_name) { DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(!disable_pipeline_auto_suspend_); disable_pipeline_auto_suspend_ = true; // Capabilities reporting should only be performed for local playbacks. @@ -3078,6 +3102,7 @@ void WebMediaPlayerImpl::SwitchToLocalRenderer( MediaObserverClient::ReasonToSwitchToLocal reason) { DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(disable_pipeline_auto_suspend_); disable_pipeline_auto_suspend_ = false; // Capabilities reporting may resume now that playback is local.
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 97fd6bf..87883e7 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -243,10 +243,15 @@ void RequestRemotePlaybackDisabled(bool disabled) override; #if defined(OS_ANDROID) // WMPI_CAST + // TODO(https://crbug.com/839651): Rename Flinging[Started/Stopped] to + // RemotePlayback[Started/Stopped] once the other RemotePlayback methods have + // been removed bool IsRemote() const override; void RequestRemotePlayback() override; void RequestRemotePlaybackControl() override; void RequestRemotePlaybackStop() override; + void FlingingStarted() override; + void FlingingStopped() override; void SetMediaPlayerManager( RendererMediaPlayerManagerInterface* media_player_manager);
diff --git a/media/capture/video/video_capture_system_impl.cc b/media/capture/video/video_capture_system_impl.cc index 98cbe01..2c41b18 100644 --- a/media/capture/video/video_capture_system_impl.cc +++ b/media/capture/video/video_capture_system_impl.cc
@@ -143,10 +143,17 @@ } devices_info_cache_.swap(new_devices_info_cache); - base::ResetAndReturn(&device_enum_request_queue_.front()) - .Run(devices_info_cache_); - + auto request_cb = std::move(device_enum_request_queue_.front()); device_enum_request_queue_.pop_front(); + // If |request_cb| was the last callback in |device_enum_request_queue_|, + // |this| may be out of scope after running it. We need to be careful to + // not touch the state of |this| after running the callback in this case. + if (device_enum_request_queue_.empty()) { + std::move(request_cb).Run(devices_info_cache_); + return; + } + std::move(request_cb).Run(devices_info_cache_); ProcessDeviceInfoRequest(); } + } // namespace media
diff --git a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.cc b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.cc index 953b89d..c251354 100644 --- a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.cc +++ b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.cc
@@ -4,18 +4,20 @@ #include "media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.h" +#include "base/bind_helpers.h" #include "base/logging.h" +#include "media/base/content_decryption_module.h" #include "media/cdm/library_cdm/clear_key_cdm/cdm_proxy_common.h" namespace media { -ClearKeyCdmProxy::ClearKeyCdmProxy() {} +ClearKeyCdmProxy::ClearKeyCdmProxy() : weak_factory_(this) {} ClearKeyCdmProxy::~ClearKeyCdmProxy() {} -// TODO(xhwang): Returns a non-null pointer and add a test covering this path. base::WeakPtr<CdmContext> ClearKeyCdmProxy::GetCdmContext() { - return nullptr; + DVLOG(1) << __func__; + return weak_factory_.GetWeakPtr(); } void ClearKeyCdmProxy::Initialize(Client* client, InitializeCB init_cb) { @@ -31,7 +33,7 @@ const std::vector<uint8_t>& input_data, uint32_t expected_output_data_size, ProcessCB process_cb) { - DVLOG(1) << __func__; + DVLOG(2) << __func__; if (crypto_session_id != kClearKeyCdmProxyCryptoSessionId || !std::equal(input_data.begin(), input_data.end(), @@ -50,7 +52,7 @@ void ClearKeyCdmProxy::CreateMediaCryptoSession( const std::vector<uint8_t>& input_data, CreateMediaCryptoSessionCB create_media_crypto_session_cb) { - DVLOG(1) << __func__; + DVLOG(2) << __func__; if (!std::equal(input_data.begin(), input_data.end(), kClearKeyCdmProxyInputData.begin(), @@ -70,4 +72,16 @@ void ClearKeyCdmProxy::RemoveKey(uint32_t crypto_session_id, const std::vector<uint8_t>& key_id) {} +Decryptor* ClearKeyCdmProxy::GetDecryptor() { + DVLOG(1) << __func__; + + if (!aes_decryptor_) { + aes_decryptor_ = base::MakeRefCounted<AesDecryptor>( + base::DoNothing(), base::DoNothing(), base::DoNothing(), + base::DoNothing()); + } + + return aes_decryptor_.get(); +} + } // namespace media
diff --git a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.h b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.h index 5ec686e..20f3d99 100644 --- a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.h +++ b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm_proxy.h
@@ -7,12 +7,16 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "media/base/cdm_context.h" +#include "media/cdm/aes_decryptor.h" #include "media/cdm/cdm_proxy.h" namespace media { // CdmProxy implementation for Clear Key CDM to test CDM Proxy support. -class ClearKeyCdmProxy : public CdmProxy { +class ClearKeyCdmProxy : public CdmProxy, public CdmContext { public: ClearKeyCdmProxy(); ~ClearKeyCdmProxy() final; @@ -34,7 +38,14 @@ void RemoveKey(uint32_t crypto_session_id, const std::vector<uint8_t>& key_id) final; + // CdmContext implementation. + Decryptor* GetDecryptor() final; + private: + scoped_refptr<AesDecryptor> aes_decryptor_; + + base::WeakPtrFactory<ClearKeyCdmProxy> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(ClearKeyCdmProxy); };
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index 297f994..78a29f54 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc
@@ -95,7 +95,7 @@ DCHECK(factories_); } -void GpuVideoDecoder::Reset(const base::Closure& closure) { +void GpuVideoDecoder::Reset(const base::Closure& closure) { DVLOG(3) << "Reset()"; DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); @@ -121,9 +121,9 @@ const gfx::Size& min_resolution, const gfx::Size& max_resolution) { return (coded_size.width() <= max_resolution.width() && - coded_size.height() <= max_resolution.height() && - coded_size.width() >= min_resolution.width() && - coded_size.height() >= min_resolution.height()); + coded_size.height() <= max_resolution.height() && + coded_size.width() >= min_resolution.width() && + coded_size.height() >= min_resolution.height()); } // Report |success| to UMA and run |cb| with it. This is super-specific to the @@ -135,8 +135,8 @@ bool success) { // TODO(xhwang): Report |success| directly. PipelineStatus status = success ? PIPELINE_OK : DECODER_ERROR_NOT_SUPPORTED; - UMA_HISTOGRAM_ENUMERATION( - "Media.GpuVideoDecoderInitializeStatus", status, PIPELINE_STATUS_MAX + 1); + UMA_HISTOGRAM_ENUMERATION("Media.GpuVideoDecoderInitializeStatus", status, + PIPELINE_STATUS_MAX + 1); if (!success) { media_log->RecordRapporWithSecurityOrigin( @@ -466,10 +466,9 @@ void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer) { - input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), - buffer.timestamp(), - config_.visible_rect(), - config_.natural_size())); + input_buffer_data_.push_front( + BufferData(bitstream_buffer.id(), buffer.timestamp(), + config_.visible_rect(), config_.natural_size())); // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but // that's too small for some pathological B-frame test videos. The cost of // using too-high a value is low (192 bits per extra slot). @@ -484,9 +483,8 @@ base::TimeDelta* timestamp, gfx::Rect* visible_rect, gfx::Size* natural_size) { - for (std::list<BufferData>::const_iterator it = - input_buffer_data_.begin(); it != input_buffer_data_.end(); - ++it) { + for (std::list<BufferData>::const_iterator it = input_buffer_data_.begin(); + it != input_buffer_data_.end(); ++it) { if (it->bitstream_buffer_id != id) continue; *timestamp = it->timestamp; @@ -520,8 +518,8 @@ uint32_t textures_per_buffer, const gfx::Size& size, uint32_t texture_target) { - DVLOG(3) << "ProvidePictureBuffers(" << count << ", " - << size.width() << "x" << size.height() << ")"; + DVLOG(3) << "ProvidePictureBuffers(" << count << ", " << size.width() << "x" + << size.height() << ")"; DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); std::vector<uint32_t> texture_ids; @@ -559,8 +557,10 @@ picture_buffers.push_back(PictureBuffer(next_picture_buffer_id_++, size, ids, mailboxes, texture_target, format)); - bool inserted = assigned_picture_buffers_.insert(std::make_pair( - picture_buffers.back().id(), picture_buffers.back())).second; + bool inserted = assigned_picture_buffers_ + .insert(std::make_pair(picture_buffers.back().id(), + picture_buffers.back())) + .second; DCHECK(inserted); } @@ -664,8 +664,8 @@ frame->set_color_space(picture.color_space()); if (picture.allow_overlay()) frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); - if (picture.surface_texture()) - frame->metadata()->SetBoolean(VideoFrameMetadata::SURFACE_TEXTURE, true); + if (picture.texture_owner()) + frame->metadata()->SetBoolean(VideoFrameMetadata::TEXTURE_OWNER, true); if (picture.wants_promotion_hint()) { frame->metadata()->SetBoolean(VideoFrameMetadata::WANTS_PROMOTION_HINT, true); @@ -686,8 +686,7 @@ DeliverFrame(frame); } -void GpuVideoDecoder::DeliverFrame( - const scoped_refptr<VideoFrame>& frame) { +void GpuVideoDecoder::DeliverFrame(const scoped_refptr<VideoFrame>& frame) { DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); // During a pending vda->Reset(), we don't accumulate frames. Drop it on the
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 8e03ae1..08bb413c 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -190,8 +190,8 @@ "android/promotion_hint_aggregator_impl.h", "android/surface_chooser_helper.cc", "android/surface_chooser_helper.h", - "android/surface_texture_gl_owner.cc", - "android/surface_texture_gl_owner.h", + "android/texture_owner.cc", + "android/texture_owner.h", "android/texture_pool.cc", "android/texture_pool.h", "android/texture_wrapper.cc", @@ -306,6 +306,8 @@ sources += [ "windows/d3d11_cdm_proxy.cc", "windows/d3d11_cdm_proxy.h", + "windows/d3d11_decryptor.cc", + "windows/d3d11_decryptor.h", ] } } @@ -445,8 +447,8 @@ "android/mock_device_info.h", "android/mock_promotion_hint_aggregator.cc", "android/mock_promotion_hint_aggregator.h", - "android/mock_surface_texture_gl_owner.cc", - "android/mock_surface_texture_gl_owner.h", + "android/mock_texture_owner.cc", + "android/mock_texture_owner.h", "android/promotion_hint_aggregator_impl_unittest.cc", "android/surface_chooser_helper_unittest.cc", "android/surface_texture_gl_owner_unittest.cc",
diff --git a/media/gpu/android/android_video_decode_accelerator.cc b/media/gpu/android/android_video_decode_accelerator.cc index 0297f1f..bfd44fe8 100644 --- a/media/gpu/android/android_video_decode_accelerator.cc +++ b/media/gpu/android/android_video_decode_accelerator.cc
@@ -396,7 +396,7 @@ base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceTransition, weak_this_factory_.GetWeakPtr(), nullptr)); - // Handle the sync path, which must use SurfaceTexture anyway. Note that we + // Handle the sync path, which must use TextureOwner anyway. Note that we // check both |during_initialize_| and |deferred_initialization_pending_|, // since we might get here during deferred surface creation. In that case, // Decode will call us (after clearing |defer_surface_creation_|), but @@ -414,7 +414,7 @@ DCHECK(!config_.overlay_info.HasValidSurfaceId()); DCHECK(!config_.overlay_info.HasValidRoutingToken()); // Note that we might still send feedback to |surface_chooser_|, which might - // call us back. However, it will only ever tell us to use SurfaceTexture, + // call us back. However, it will only ever tell us to use TextureOwner, // since we have no overlay factory anyway. OnSurfaceTransition(nullptr); return; @@ -436,7 +436,7 @@ // Notify |surface_chooser_| that we've started. This guarantees that we'll // get a callback. It might not be a synchronous callback, but we're not in // the synchronous case. It will be soon, though. For pre-M, we rely on the - // fact that |surface_chooser_| won't tell us to use a SurfaceTexture while + // fact that |surface_chooser_| won't tell us to use a TextureOwner while // waiting for an overlay to become ready, for example. surface_chooser_helper_.UpdateChooserState(std::move(factory)); } @@ -466,9 +466,9 @@ if (!device_info_->IsSetOutputSurfaceSupported()) return; - // If we're using a SurfaceTexture and are told to switch to one, then just + // If we're using a TextureOwner and are told to switch to one, then just // do nothing. |surface_chooser_| doesn't really know if we've switched to - // SurfaceTexture or not. Note that it can't ask us to switch to the same + // TextureOwner or not. Note that it can't ask us to switch to the same // overlay we're using, since it's unique_ptr. if (!overlay && codec_config_->surface_bundle && !codec_config_->surface_bundle->overlay) { @@ -495,10 +495,10 @@ // incoming bundle properly, since we don't want to accidentally overwrite // |surface_bundle| for a codec that's being released elsewhere. // TODO(liberato): it doesn't make sense anymore for the PictureBufferManager - // to create the surface texture. We can probably make an overlay impl out - // of it, and provide the surface texture to |picture_buffer_manager_|. + // to create the texture owner. We can probably make an overlay impl out + // of it, and provide the texture owner to |picture_buffer_manager_|. if (!picture_buffer_manager_.Initialize(incoming_bundle_)) { - NOTIFY_ERROR(PLATFORM_FAILURE, "Could not allocate surface texture"); + NOTIFY_ERROR(PLATFORM_FAILURE, "Could not allocate texture owner"); incoming_bundle_ = nullptr; return; } @@ -927,7 +927,7 @@ if (want_promotion_hint) { picture.set_wants_promotion_hint(true); // This will prevent it from actually being promoted if it shouldn't be. - picture.set_surface_texture(!allow_overlay); + picture.set_texture_owner(!allow_overlay); } // Notify picture ready before calling UseCodecBufferForPictureBuffer() since @@ -1370,7 +1370,7 @@ // We cannot get here if we're before surface allocation, since we transition // to WAITING_FOR_CODEC (or NO_ERROR, if sync) when we get the surface without // posting. If we do ever lose the surface before starting codec allocation, - // then we could just update the config to use a SurfaceTexture and return + // then we could just update the config to use a TextureOwner and return // without changing state. DCHECK_NE(state_, BEFORE_OVERLAY_INIT); @@ -1393,7 +1393,7 @@ // overlay that was destroyed. if (state_ == WAITING_FOR_CODEC) { // What we should do here is to set |incoming_overlay_| to nullptr, to start - // a transistion to SurfaceTexture. OnCodecConfigured could notice that + // a transistion to TextureOwner. OnCodecConfigured could notice that // there's an incoming overlay, and then immediately transition the codec / // drop and re-allocate the codec using it. However, for CVV, that won't // work, since CVV-based overlays block the main thread waiting for the @@ -1417,16 +1417,16 @@ picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_); // If we aren't transitioning to some other surface, then transition to a - // SurfaceTexture. Remember that, if |incoming_overlay_| is an overlay, + // TextureOwner. Remember that, if |incoming_overlay_| is an overlay, // then it's already ready and can be transitioned to immediately. We were // just waiting for codec buffers to come back, but we just dropped them. // Note that we want |incoming_overlay_| to has_value(), but that value - // should be a nullptr to indicate that we should switch to SurfaceTexture. + // should be a nullptr to indicate that we should switch to TextureOwner. if (!incoming_overlay_) incoming_overlay_ = std::unique_ptr<AndroidOverlay>(); UpdateSurface(); - // Switching to a SurfaceTexture should never need to wait. If it does, + // Switching to a TextureOwner should never need to wait. If it does, // then the codec might still be using the destroyed surface, which is bad. return; } @@ -1513,7 +1513,7 @@ codec_config_->media_crypto = std::move(media_crypto); codec_config_->requires_secure_codec = requires_secure_video_codec; // Request a secure surface in all cases. For L3, it's okay if we fall back - // to SurfaceTexture rather than fail composition. For L1, it's required. + // to TextureOwner rather than fail composition. For L1, it's required. // It's also required if the command line says so. surface_chooser_helper_.SetSecureSurfaceMode( requires_secure_video_codec @@ -1746,7 +1746,7 @@ // wouldn't be necessarily true anymore. // Also note that we might not have switched surfaces yet, which is also bad // for OnSurfaceDestroyed, because of BEFORE_OVERLAY_INIT. Shouldn't - // happen with SurfaceTexture, and OnSurfaceDestroyed checks for it. In + // happen with TextureOwner, and OnSurfaceDestroyed checks for it. In // either case, we definitely should not still have an incoming bundle; it // should have been dropped. DCHECK(!incoming_bundle_);
diff --git a/media/gpu/android/android_video_decode_accelerator.h b/media/gpu/android/android_video_decode_accelerator.h index c8e31ab..842a7bd 100644 --- a/media/gpu/android/android_video_decode_accelerator.h +++ b/media/gpu/android/android_video_decode_accelerator.h
@@ -120,7 +120,7 @@ // |surface_chooser_| with our initial factory from VDA::Config. void StartSurfaceChooser(); - // Start a transition to an overlay, or, if |!overlay|, SurfaceTexture. The + // Start a transition to an overlay, or, if |!overlay|, TextureOwner. The // transition doesn't have to be immediate; we'll favor not dropping frames. void OnSurfaceTransition(std::unique_ptr<AndroidOverlay> overlay); @@ -386,7 +386,7 @@ scoped_refptr<AVDASurfaceBundle> incoming_bundle_; // If we have been given an overlay to use, then this is it. If we've been - // told to move to SurfaceTexture, then this will be value() == nullptr. + // told to move to TextureOwner, then this will be value() == nullptr. base::Optional<std::unique_ptr<AndroidOverlay>> incoming_overlay_; SurfaceChooserHelper surface_chooser_helper_; @@ -406,7 +406,7 @@ // Most recently cached frame information, so that we can dispatch it without // recomputing it on every frame. It changes very rarely. SurfaceChooserHelper::FrameInformation cached_frame_information_ = - SurfaceChooserHelper::FrameInformation::SURFACETEXTURE_INSECURE; + SurfaceChooserHelper::FrameInformation::NON_OVERLAY_INSECURE; // WeakPtrFactory for posting tasks back to |this|. base::WeakPtrFactory<AndroidVideoDecodeAccelerator> weak_this_factory_;
diff --git a/media/gpu/android/android_video_decode_accelerator_unittest.cc b/media/gpu/android/android_video_decode_accelerator_unittest.cc index 08eb9e0e..d35a438b 100644 --- a/media/gpu/android/android_video_decode_accelerator_unittest.cc +++ b/media/gpu/android/android_video_decode_accelerator_unittest.cc
@@ -168,16 +168,16 @@ base::RunLoop().RunUntilIdle(); } - void InitializeAVDAWithSurfaceTexture() { + void InitializeAVDAWithTextureOwner() { ASSERT_TRUE(InitializeAVDA()); base::RunLoop().RunUntilIdle(); - // We do not expect a factory, since we are using SurfaceTexture. + // We do not expect a factory, since we are using TextureOwner. ASSERT_FALSE(chooser_->factory_); // Set the expectations first, since ProvideOverlay might cause callbacks. EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecAsync(nullptr, NotNull())); - chooser_->ProvideSurfaceTexture(); + chooser_->ProvideTextureOwner(); // Provide the codec so that we can check if it's freed properly. EXPECT_CALL(client_, NotifyInitializationComplete(true)); @@ -284,7 +284,7 @@ EXPECT_CALL(client_, NotifyInitializationComplete(false)); ASSERT_TRUE(InitializeAVDA()); - chooser_->ProvideSurfaceTexture(); + chooser_->ProvideTextureOwner(); codec_allocator_->ProvideNullCodecAsync(); // Make sure that codec allocation has happened before destroying the VDA. @@ -310,22 +310,21 @@ InitializeAVDA(force_defer_surface_creation); } -TEST_F(AndroidVideoDecodeAcceleratorTest, - AsyncInitWithSurfaceTextureAndDelete) { - // When configuring with a SurfaceTexture and deferred init, we should be +TEST_F(AndroidVideoDecodeAcceleratorTest, AsyncInitWithTextureOwnerAndDelete) { + // When configuring with a TextureOwner and deferred init, we should be // asked for a codec, and be notified of init success if we provide one. When - // AVDA is destroyed, it should release the codec and surface texture. + // AVDA is destroyed, it should release the codec and texture owner. SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); - InitializeAVDAWithSurfaceTexture(); + InitializeAVDAWithTextureOwner(); // Delete the VDA, and make sure that it tries to free the codec and the right - // surface texture. + // texture owner. EXPECT_CALL( *codec_allocator_, MockReleaseMediaCodec(codec_allocator_->most_recent_codec, codec_allocator_->most_recent_overlay, - codec_allocator_->most_recent_surface_texture)); + codec_allocator_->most_recent_texture_owner)); codec_allocator_->most_recent_codec_destruction_observer->ExpectDestruction(); vda_ = nullptr; base::RunLoop().RunUntilIdle(); @@ -346,21 +345,21 @@ *codec_allocator_, MockReleaseMediaCodec(codec_allocator_->most_recent_codec, codec_allocator_->most_recent_overlay, - codec_allocator_->most_recent_surface_texture)); + codec_allocator_->most_recent_texture_owner)); codec_allocator_->most_recent_codec_destruction_observer->ExpectDestruction(); vda_ = nullptr; base::RunLoop().RunUntilIdle(); } TEST_F(AndroidVideoDecodeAcceleratorTest, - SwitchesToSurfaceTextureWhenSurfaceDestroyed) { + SwitchesToTextureOwnerWhenSurfaceDestroyed) { // Provide a surface, and a codec, then destroy the surface. AVDA should use - // SetSurface to switch to SurfaceTexture. + // SetSurface to switch to TextureOwner. SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); InitializeAVDAWithOverlay(); - // It would be nice if we knew that this was a surface texture. As it is, we + // It would be nice if we knew that this was a texture owner. As it is, we // just destroy the VDA and expect that we're provided with one. Hopefully, // AVDA is actually calling SetSurface properly. EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)) @@ -377,9 +376,9 @@ base::RunLoop().RunUntilIdle(); } -TEST_F(AndroidVideoDecodeAcceleratorTest, SwitchesToSurfaceTextureEventually) { +TEST_F(AndroidVideoDecodeAcceleratorTest, SwitchesToTextureOwnerEventually) { // Provide a surface, and a codec, then request that AVDA switches to a - // surface texture. Verify that it does. + // texture owner. Verify that it does. SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); InitializeAVDAWithOverlay(); @@ -387,12 +386,12 @@ EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)) .WillOnce(Return(true)); - // Note that it's okay if |avda_| switches before ProvideSurfaceTexture + // Note that it's okay if |avda_| switches before ProvideTextureOwner // returns, since it has no queued output anyway. - chooser_->ProvideSurfaceTexture(); + chooser_->ProvideTextureOwner(); LetAVDAUpdateSurface(); - // Verify that we're now using some surface texture. + // Verify that we're now using some texture owner. EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(codec_allocator_->most_recent_codec, nullptr, NotNull())); @@ -404,7 +403,7 @@ TEST_F(AndroidVideoDecodeAcceleratorTest, SetSurfaceFailureDoesntSwitchSurfaces) { // Initialize AVDA with a surface, then request that AVDA switches to a - // surface texture. When it tries to UpdateSurface, pretend to fail. AVDA + // texture owner. When it tries to UpdateSurface, pretend to fail. AVDA // should notify error, and also release the original surface. SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); @@ -417,7 +416,7 @@ .Times(1); codec_allocator_->most_recent_codec_destruction_observer ->VerifyAndClearExpectations(); - chooser_->ProvideSurfaceTexture(); + chooser_->ProvideTextureOwner(); LetAVDAUpdateSurface(); } @@ -427,7 +426,7 @@ // chance to do the first switch. It should simply drop the overlay. SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); - InitializeAVDAWithSurfaceTexture(); + InitializeAVDAWithTextureOwner(); // Don't let AVDA switch immediately, else it could choose to SetSurface when // it first gets the overlay. @@ -445,15 +444,15 @@ // Now it is expected to drop the overlay. observer->ExpectDestruction(); - // While the incoming surface is pending, switch back to SurfaceTexture. - chooser_->ProvideSurfaceTexture(); + // While the incoming surface is pending, switch back to TextureOwner. + chooser_->ProvideTextureOwner(); } TEST_F(AndroidVideoDecodeAcceleratorTest, ChangingOutputSurfaceVoluntarilyWithoutSetSurfaceIsIgnored) { - // If we ask AVDA to change to SurfaceTexture should be ignored on platforms + // If we ask AVDA to change to TextureOwner should be ignored on platforms // that don't support SetSurface (pre-M or blacklisted). It should also - // ignore SurfaceTexture => overlay, but we don't check that. + // ignore TextureOwner => overlay, but we don't check that. // // Also note that there are other probably reasonable things to do (like // signal an error), but we want to be sure that it doesn't try to SetSurface. @@ -469,8 +468,8 @@ InitializeAVDAWithOverlay(); EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)).Times(0); - // This should not switch to SurfaceTexture. - chooser_->ProvideSurfaceTexture(); + // This should not switch to TextureOwner. + chooser_->ProvideTextureOwner(); LetAVDAUpdateSurface(); } @@ -501,15 +500,15 @@ } TEST_F(AndroidVideoDecodeAcceleratorTest, - MultipleSurfaceTextureCallbacksAreIgnored) { + MultipleTextureOwnerCallbacksAreIgnored) { // Ask AVDA to switch to ST when it's already using ST, nothing should happen. SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); - InitializeAVDAWithSurfaceTexture(); + InitializeAVDAWithTextureOwner(); // This should do nothing. EXPECT_CALL(*codec_allocator_->most_recent_codec, SetSurface(_)).Times(0); - chooser_->ProvideSurfaceTexture(); + chooser_->ProvideTextureOwner(); base::RunLoop().RunUntilIdle(); }
diff --git a/media/gpu/android/android_video_surface_chooser.h b/media/gpu/android/android_video_surface_chooser.h index dc738138..7789c45 100644 --- a/media/gpu/android/android_video_surface_chooser.h +++ b/media/gpu/android/android_video_surface_chooser.h
@@ -54,17 +54,16 @@ // Notify the client that the most recently provided overlay should be // discarded. The overlay is still valid, but we recommend against - // using it soon, in favor of a SurfaceTexture. - using UseSurfaceTextureCB = base::RepeatingCallback<void(void)>; + // using it soon, in favor of a TextureOwner. + using UseTextureOwnerCB = base::RepeatingCallback<void(void)>; AndroidVideoSurfaceChooser() {} virtual ~AndroidVideoSurfaceChooser() {} // Sets the client callbacks to be called when a new surface choice is made. // Must be called before UpdateState(); - virtual void SetClientCallbacks( - UseOverlayCB use_overlay_cb, - UseSurfaceTextureCB use_surface_texture_cb) = 0; + virtual void SetClientCallbacks(UseOverlayCB use_overlay_cb, + UseTextureOwnerCB use_texture_owner_cb) = 0; // Updates the current state and makes a new surface choice with the new // state. If |new_factory| is empty, the factory is left as-is. Otherwise,
diff --git a/media/gpu/android/android_video_surface_chooser_impl.cc b/media/gpu/android/android_video_surface_chooser_impl.cc index f1faaa4e2..79152879 100644 --- a/media/gpu/android/android_video_surface_chooser_impl.cc +++ b/media/gpu/android/android_video_surface_chooser_impl.cc
@@ -30,10 +30,10 @@ void AndroidVideoSurfaceChooserImpl::SetClientCallbacks( UseOverlayCB use_overlay_cb, - UseSurfaceTextureCB use_surface_texture_cb) { - DCHECK(use_overlay_cb && use_surface_texture_cb); + UseTextureOwnerCB use_texture_owner_cb) { + DCHECK(use_overlay_cb && use_texture_owner_cb); use_overlay_cb_ = std::move(use_overlay_cb); - use_surface_texture_cb_ = std::move(use_surface_texture_cb); + use_texture_owner_cb_ = std::move(use_texture_owner_cb); } void AndroidVideoSurfaceChooserImpl::UpdateState( @@ -53,13 +53,13 @@ initial_state_received_ = true; // Choose here so that Choose() doesn't have to handle non-dynamic. // Note that we ignore |is_expecting_relayout| here, since it's transient. - // We don't want to pick SurfaceTexture permanently for that. + // We don't want to pick TextureOwner permanently for that. if (overlay_factory_ && (current_state_.is_fullscreen || current_state_.is_secure || current_state_.is_required)) { SwitchToOverlay(false); } else { - SwitchToSurfaceTexture(); + SwitchToTextureOwner(); } } return; @@ -87,9 +87,8 @@ DCHECK(allow_dynamic_); // TODO(liberato): should this depend on resolution? - OverlayState new_overlay_state = current_state_.promote_aggressively - ? kUsingOverlay - : kUsingSurfaceTexture; + OverlayState new_overlay_state = + current_state_.promote_aggressively ? kUsingOverlay : kUsingTextureOwner; // Do we require a power-efficient overlay? bool needs_power_efficient = current_state_.promote_aggressively; @@ -111,7 +110,7 @@ // If the compositor won't promote, then don't. if (!current_state_.is_compositor_promotable) - new_overlay_state = kUsingSurfaceTexture; + new_overlay_state = kUsingTextureOwner; // If we're expecting a relayout, then don't transition to overlay if we're // not already in one. We don't want to transition out, though. This lets us @@ -119,7 +118,7 @@ // TODO(liberato): Detect this more directly. if (current_state_.is_expecting_relayout && client_overlay_state_ != kUsingOverlay) - new_overlay_state = kUsingSurfaceTexture; + new_overlay_state = kUsingTextureOwner; // If we're requesting an overlay, check that we haven't asked too recently // since the last failure. This includes L1. We don't bother to check for @@ -129,7 +128,7 @@ base::TimeDelta time_since_last_failure = tick_clock_->NowTicks() - most_recent_overlay_failure_; if (time_since_last_failure < MinimumDelayAfterFailedOverlay) - new_overlay_state = kUsingSurfaceTexture; + new_overlay_state = kUsingTextureOwner; } // If an overlay is required, then choose one. The only way we won't is if we @@ -142,16 +141,16 @@ // If we have no factory, then we definitely don't want to use overlays. if (!overlay_factory_) - new_overlay_state = kUsingSurfaceTexture; + new_overlay_state = kUsingTextureOwner; // Make sure that we're in |new_overlay_state_|. - if (new_overlay_state == kUsingSurfaceTexture) - SwitchToSurfaceTexture(); + if (new_overlay_state == kUsingTextureOwner) + SwitchToTextureOwner(); else SwitchToOverlay(needs_power_efficient); } -void AndroidVideoSurfaceChooserImpl::SwitchToSurfaceTexture() { +void AndroidVideoSurfaceChooserImpl::SwitchToTextureOwner() { // Invalidate any outstanding deletion callbacks for any overlays that we've // provided to the client already. We assume that it will eventually drop // them in response to the callback. Ready / failed callbacks aren't affected @@ -164,11 +163,11 @@ overlay_ = nullptr; // Notify the client to switch if it's in the wrong state. - if (client_overlay_state_ != kUsingSurfaceTexture) { - DCHECK(use_surface_texture_cb_); + if (client_overlay_state_ != kUsingTextureOwner) { + DCHECK(use_texture_owner_cb_); - client_overlay_state_ = kUsingSurfaceTexture; - use_surface_texture_cb_.Run(); + client_overlay_state_ = kUsingTextureOwner; + use_texture_owner_cb_.Run(); } } @@ -218,7 +217,7 @@ overlay_ = overlay_factory_.Run(std::move(config)); if (!overlay_) - SwitchToSurfaceTexture(); + SwitchToTextureOwner(); } void AndroidVideoSurfaceChooserImpl::OnOverlayReady(AndroidOverlay* overlay) { @@ -243,18 +242,18 @@ overlay_ = nullptr; most_recent_overlay_failure_ = tick_clock_->NowTicks(); - // If the client isn't already using a SurfaceTexture, then switch to it. + // If the client isn't already using a TextureOwner, then switch to it. // Note that this covers the case of kUnknown, when we might not have told the // client anything yet. That's important for Initialize, so that a failed // overlay request still results in some callback to the client to know what // surface to start with. - SwitchToSurfaceTexture(); + SwitchToTextureOwner(); } void AndroidVideoSurfaceChooserImpl::OnOverlayDeleted(AndroidOverlay* overlay) { - client_overlay_state_ = kUsingSurfaceTexture; - // We don't call SwitchToSurfaceTexture since the client dropped the overlay. - // It's already using SurfaceTexture. + client_overlay_state_ = kUsingTextureOwner; + // We don't call SwitchToTextureOwner since the client dropped the overlay. + // It's already using TextureOwner. } void AndroidVideoSurfaceChooserImpl::OnPowerEfficientState( @@ -264,7 +263,7 @@ // callback if it arrives. Getting a new overlay clears any previous cbs. DCHECK(!overlay_); - // We cannot receive it after switching to SurfaceTexture, since that also + // We cannot receive it after switching to TextureOwner, since that also // clears all callbacks. DCHECK(client_overlay_state_ == kUsingOverlay); @@ -285,7 +284,7 @@ // We don't want to delay transitioning to an overlay if the user re-enters // fullscreen. TODO(liberato): Perhaps we should just clear the failure timer // if we detect a transition into fs when we get new state from the client. - SwitchToSurfaceTexture(); + SwitchToTextureOwner(); } } // namespace media
diff --git a/media/gpu/android/android_video_surface_chooser_impl.h b/media/gpu/android/android_video_surface_chooser_impl.h index e3b1a21..f5a5ecd5 100644 --- a/media/gpu/android/android_video_surface_chooser_impl.h +++ b/media/gpu/android/android_video_surface_chooser_impl.h
@@ -30,20 +30,20 @@ // AndroidVideoSurfaceChooser void SetClientCallbacks(UseOverlayCB use_overlay_cb, - UseSurfaceTextureCB use_surface_texture_cb) override; + UseTextureOwnerCB use_texture_owner_cb) override; void UpdateState(base::Optional<AndroidOverlayFactoryCB> new_factory, const State& new_state) override; private: - // Choose whether we should be using a SurfaceTexture or overlay, and issue + // Choose whether we should be using a TextureOwner or overlay, and issue // the right callbacks if we're changing between them. This should only be // called if |allow_dynamic_|. void Choose(); - // Start switching to SurfaceTexture or overlay, as needed. These will call + // Start switching to TextureOwner or overlay, as needed. These will call // the client callbacks if we're changing state, though those callbacks might // happen after this returns. - void SwitchToSurfaceTexture(); + void SwitchToTextureOwner(); // If |overlay_| has an in-flight request, then this will do nothing. If // |power_efficient|, then we will require a power-efficient overlay, and // cancel it if it becomes not power efficient. @@ -57,7 +57,7 @@ // Client callbacks. UseOverlayCB use_overlay_cb_; - UseSurfaceTextureCB use_surface_texture_cb_; + UseTextureOwnerCB use_texture_owner_cb_; // Current overlay that we've constructed but haven't received ready / failed // callbacks yet. Will be nullptr if we haven't constructed one, or if we @@ -72,7 +72,7 @@ enum OverlayState { kUnknown, - kUsingSurfaceTexture, + kUsingTextureOwner, kUsingOverlay, };
diff --git a/media/gpu/android/android_video_surface_chooser_impl_unittest.cc b/media/gpu/android/android_video_surface_chooser_impl_unittest.cc index 76e760d..24310a7 100644 --- a/media/gpu/android/android_video_surface_chooser_impl_unittest.cc +++ b/media/gpu/android/android_video_surface_chooser_impl_unittest.cc
@@ -40,7 +40,7 @@ } // Note that this won't clear |overlay_|, which is helpful. - MOCK_METHOD0(UseSurfaceTexture, void(void)); + MOCK_METHOD0(UseTextureOwner, void(void)); // Let the test have the overlay. std::unique_ptr<AndroidOverlay> ReleaseOverlay() { @@ -128,8 +128,10 @@ chooser_ = std::make_unique<AndroidVideoSurfaceChooserImpl>(allow_dynamic_, &tick_clock_); chooser_->SetClientCallbacks( - base::Bind(&MockClient::UseOverlayImpl, base::Unretained(&client_)), - base::Bind(&MockClient::UseSurfaceTexture, base::Unretained(&client_))); + base::BindRepeating(&MockClient::UseOverlayImpl, + base::Unretained(&client_)), + base::BindRepeating(&MockClient::UseTextureOwner, + base::Unretained(&client_))); chooser_->UpdateState( factory ? base::make_optional(std::move(factory)) : base::nullopt, chooser_state_); @@ -207,28 +209,27 @@ }; TEST_F(AndroidVideoSurfaceChooserImplTest, - InitializeWithoutFactoryUsesSurfaceTexture) { + InitializeWithoutFactoryUsesTextureOwner) { // Calling Initialize() with no factory should result in a callback to use - // surface texture. - EXPECT_CALL(client_, UseSurfaceTexture()); + // texture owner. + EXPECT_CALL(client_, UseTextureOwner()); StartChooser(AndroidOverlayFactoryCB()); } -TEST_F(AndroidVideoSurfaceChooserImplTest, - NullInitialOverlayUsesSurfaceTexture) { +TEST_F(AndroidVideoSurfaceChooserImplTest, NullInitialOverlayUsesTextureOwner) { // If we provide a factory, but it fails to create an overlay, then |client_| - // should be notified to use a surface texture. + // should be notified to use a texture owner. chooser_state_.is_fullscreen = true; EXPECT_CALL(*this, MockOnOverlayCreated()); - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); StartChooser(FactoryFor(nullptr)); } TEST_F(AndroidVideoSurfaceChooserImplTest, - FailedInitialOverlayUsesSurfaceTexture) { + FailedInitialOverlayUsesTextureOwner) { // If we provide a factory, but the overlay that it provides returns 'failed', - // then |client_| should use surface texture. Also check that it won't retry + // then |client_| should use texture owner. Also check that it won't retry // after a failed overlay too soon. chooser_state_.is_fullscreen = true; EXPECT_CALL(*this, MockOnOverlayCreated()); @@ -241,7 +242,7 @@ // doesn't have to be destroyed. We just care that it hasn't been destroyed // before now. destruction_observer_ = nullptr; - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); overlay_callbacks_.OverlayFailed.Run(); testing::Mock::VerifyAndClearExpectations(&client_); testing::Mock::VerifyAndClearExpectations(this); @@ -262,38 +263,38 @@ testing::Mock::VerifyAndClearExpectations(this); } -TEST_F(AndroidVideoSurfaceChooserImplTest, NullLaterOverlayUsesSurfaceTexture) { +TEST_F(AndroidVideoSurfaceChooserImplTest, NullLaterOverlayUsesTextureOwner) { // If an overlay factory is provided after startup that returns a null overlay // from CreateOverlay, |chooser_| should, at most, notify |client_| to use - // SurfaceTexture zero or more times. + // TextureOwner zero or more times. - // Start with SurfaceTexture. + // Start with TextureOwner. chooser_state_.is_fullscreen = true; - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); allow_dynamic_ = true; StartChooser(AndroidOverlayFactoryCB()); testing::Mock::VerifyAndClearExpectations(&client_); // Provide a factory that will return a null overlay. EXPECT_CALL(*this, MockOnOverlayCreated()); - EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber()); + EXPECT_CALL(client_, UseTextureOwner()).Times(AnyNumber()); chooser_->UpdateState(FactoryFor(nullptr), chooser_state_); } TEST_F(AndroidVideoSurfaceChooserImplTest, FailedLaterOverlayDoesNothing) { // If we send an overlay factory that returns an overlay, and that overlay // fails, then the client should not be notified except for zero or more - // callbacks to switch to surface texture. + // callbacks to switch to texture owner. - // Start with SurfaceTexture. + // Start with TextureOwner. chooser_state_.is_fullscreen = true; - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); StartChooser(AndroidOverlayFactoryCB()); testing::Mock::VerifyAndClearExpectations(&client_); // Provide a factory. EXPECT_CALL(*this, MockOnOverlayCreated()); - EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber()); + EXPECT_CALL(client_, UseTextureOwner()).Times(AnyNumber()); chooser_->UpdateState(FactoryFor(std::move(overlay_)), chooser_state_); testing::Mock::VerifyAndClearExpectations(&client_); @@ -307,17 +308,17 @@ SuccessfulLaterOverlayNotifiesClient) { // |client_| is notified if we provide a factory that gets an overlay. - // Start with SurfaceTexture. + // Start with TextureOwner. chooser_state_.is_fullscreen = true; - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); StartChooser(AndroidOverlayFactoryCB()); testing::Mock::VerifyAndClearExpectations(&client_); // Provide a factory. |chooser_| should try to create an overlay. We don't - // care if a call to UseSurfaceTexture is elided or not. Note that AVDA will - // ignore duplicate calls anyway (MultipleSurfaceTextureCallbacksAreIgnored). + // care if a call to UseTextureOwner is elided or not. Note that AVDA will + // ignore duplicate calls anyway (MultipleTextureOwnerCallbacksAreIgnored). EXPECT_CALL(*this, MockOnOverlayCreated()); - EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber()); + EXPECT_CALL(client_, UseTextureOwner()).Times(AnyNumber()); chooser_->UpdateState(FactoryFor(std::move(overlay_)), chooser_state_); testing::Mock::VerifyAndClearExpectations(&client_); testing::Mock::VerifyAndClearExpectations(this); @@ -330,7 +331,7 @@ TEST_F(AndroidVideoSurfaceChooserImplTest, UpdateStateAfterDeleteRetriesOverlay) { // Make sure that SurfaceChooser notices that we delete the overlay, and have - // switched back to SurfaceTexture mode. + // switched back to TextureOwner mode. chooser_state_.is_fullscreen = true; StartChooserAndProvideOverlay(); @@ -341,7 +342,7 @@ // Force chooser to choose again. We expect that it will retry the overlay, // since the delete should have informed it that we've switched back to - // SurfaceTexture without a callback from SurfaceChooser. If it didn't know + // TextureOwner without a callback from SurfaceChooser. If it didn't know // this, then it would think that the client is still using an overlay, and // take no action. @@ -355,7 +356,7 @@ TEST_F(AndroidVideoSurfaceChooserImplTest, PowerEffcientOverlayCancelsIfNotPowerEfficient) { // If we request a power efficient overlay that later becomes not power - // efficient, then the client should switch to SurfaceTexture. + // efficient, then the client should switch to TextureOwner. chooser_state_.promote_aggressively = true; MockAndroidOverlay* overlay = StartChooserAndProvideOverlay(); @@ -366,14 +367,14 @@ ASSERT_TRUE(overlay->config()->power_efficient); // Notify the chooser that it's not power efficient anymore. - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); overlay_callbacks_.PowerEfficientState.Run(false); } TEST_P(AndroidVideoSurfaceChooserImplTest, OverlayIsUsedOrNotBasedOnState) { // Provide a factory, and verify that it is used when the state says that it // should be. If the overlay is used, then we also verify that it does not - // switch to SurfaceTexture first, since pre-M requires it. + // switch to TextureOwner first, since pre-M requires it. const bool should_use_overlay = IsYes(ShouldUseOverlay, 0); const bool should_be_power_efficient = IsYes(ShouldBePowerEfficient, 1); @@ -389,10 +390,10 @@ MockAndroidOverlay* overlay = overlay_.get(); if (should_use_overlay) { - EXPECT_CALL(client_, UseSurfaceTexture()).Times(0); + EXPECT_CALL(client_, UseTextureOwner()).Times(0); EXPECT_CALL(*this, MockOnOverlayCreated()); } else { - EXPECT_CALL(client_, UseSurfaceTexture()); + EXPECT_CALL(client_, UseTextureOwner()); EXPECT_CALL(*this, MockOnOverlayCreated()).Times(0); } @@ -409,8 +410,8 @@ } } -// Unless we're promoting aggressively, we should default to SurfaceTexture. -INSTANTIATE_TEST_CASE_P(NoFullscreenUsesSurfaceTexture, +// Unless we're promoting aggressively, we should default to TextureOwner. +INSTANTIATE_TEST_CASE_P(NoFullscreenUsesTextureOwner, AndroidVideoSurfaceChooserImplTest, Combine(Values(ShouldUseOverlay::No), Values(ShouldBePowerEfficient::Ignored), @@ -463,10 +464,10 @@ // For all dynamic cases, we shouldn't use an overlay if the compositor won't // promote it, unless it's marked as required. This includes secure surfaces, -// so that L3 will fall back to SurfaceTexture. Non-dynamic is excluded, since +// so that L3 will fall back to TextureOwner. Non-dynamic is excluded, since // we don't get (or use) compositor feedback before the first frame. At that // point, we've already chosen the output surface and can't switch it. -INSTANTIATE_TEST_CASE_P(NotCCPromotableNotRequiredUsesSurfaceTexture, +INSTANTIATE_TEST_CASE_P(NotCCPromotableNotRequiredUsesTextureOwner, AndroidVideoSurfaceChooserImplTest, Combine(Values(ShouldUseOverlay::No), Values(ShouldBePowerEfficient::No), @@ -480,7 +481,7 @@ // If we're expecting a relayout, then we should never use an overlay unless // it's required. -INSTANTIATE_TEST_CASE_P(InsecureExpectingRelayoutUsesSurfaceTexture, +INSTANTIATE_TEST_CASE_P(InsecureExpectingRelayoutUsesTextureOwner, AndroidVideoSurfaceChooserImplTest, Combine(Values(ShouldUseOverlay::No), Values(ShouldBePowerEfficient::No),
diff --git a/media/gpu/android/avda_codec_image.cc b/media/gpu/android/avda_codec_image.cc index e1a2b60..66de3d4 100644 --- a/media/gpu/android/avda_codec_image.cc +++ b/media/gpu/android/avda_codec_image.cc
@@ -23,7 +23,7 @@ : shared_state_(shared_state), codec_buffer_index_(kInvalidCodecBufferIndex), media_codec_(codec), - has_surface_texture_(false), + has_texture_owner_(false), texture_(0) {} AVDACodecImage::~AVDACodecImage() {} @@ -43,25 +43,25 @@ void AVDACodecImage::ReleaseTexImage(unsigned target) {} bool AVDACodecImage::CopyTexImage(unsigned target) { - if (!has_surface_texture_ || target != GL_TEXTURE_EXTERNAL_OES) + if (!has_texture_owner_ || target != GL_TEXTURE_EXTERNAL_OES) return false; GLint bound_service_id = 0; glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); // We insist that the currently bound texture is the right one. if (bound_service_id != - static_cast<GLint>(shared_state_->surface_texture_service_id())) { + static_cast<GLint>(shared_state_->texture_owner_service_id())) { return false; } // Make sure that we have the right image in the front buffer. Note that the - // bound_service_id is guaranteed to be equal to the surface texture's client + // bound_service_id is guaranteed to be equal to the texture owner's client // texture id, so we can skip preserving it if the right context is current. UpdateSurfaceInternal(UpdateMode::RENDER_TO_FRONT_BUFFER, kDontRestoreBindings); // By setting image state to UNBOUND instead of COPIED we ensure that - // CopyTexImage() is called each time the surface texture is used for drawing. + // CopyTexImage() is called each time the texture owner is used for drawing. // It would be nice if we could do this via asking for the currently bound // Texture, but the active unit never seems to change. texture_->SetLevelImageState(GL_TEXTURE_EXTERNAL_OES, 0, @@ -83,9 +83,9 @@ const gfx::RectF& crop_rect, bool enable_blend) { // This should only be called when we're rendering to a SurfaceView. - if (has_surface_texture_) { + if (has_texture_owner_) { DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " - "SurfaceTexture backed."; + "TextureOwner backed."; return false; } @@ -103,8 +103,8 @@ uint64_t process_tracing_id, const std::string& dump_name) {} -void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) { - DCHECK(has_surface_texture_); +void AVDACodecImage::UpdateTextureOwner(RestoreBindingsMode mode) { + DCHECK(has_texture_owner_); DCHECK_EQ(codec_buffer_index_, kUpdateOnly); codec_buffer_index_ = kRendered; @@ -137,9 +137,9 @@ } void AVDACodecImage::SetBufferMetadata(int buffer_index, - bool has_surface_texture, + bool has_texture_owner, const gfx::Size& size) { - has_surface_texture_ = has_surface_texture; + has_texture_owner_ = has_texture_owner; codec_buffer_index_ = buffer_index; size_ = size; } @@ -162,7 +162,7 @@ ReleaseOutputBuffer(update_mode); // SurfaceViews are updated implicitly, so no further steps are necessary. - if (!has_surface_texture_) { + if (!has_texture_owner_) { DCHECK(update_mode != UpdateMode::RENDER_TO_BACK_BUFFER); return; } @@ -171,7 +171,7 @@ if (update_mode != UpdateMode::RENDER_TO_FRONT_BUFFER) return; - UpdateSurfaceTexture(attached_bindings_mode); + UpdateTextureOwner(attached_bindings_mode); } void AVDACodecImage::ReleaseOutputBuffer(UpdateMode update_mode) { @@ -191,7 +191,7 @@ DCHECK(update_mode == UpdateMode::RENDER_TO_BACK_BUFFER || update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); - if (!has_surface_texture_) { + if (!has_texture_owner_) { DCHECK(update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER); DCHECK_GE(codec_buffer_index_, 0); media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true); @@ -202,14 +202,14 @@ // If we've already released to the back buffer, there's nothing left to do, // but wait for the previously released buffer if necessary. if (codec_buffer_index_ != kUpdateOnly) { - DCHECK(has_surface_texture_); + DCHECK(has_texture_owner_); DCHECK_GE(codec_buffer_index_, 0); - shared_state_->RenderCodecBufferToSurfaceTexture(media_codec_, - codec_buffer_index_); + shared_state_->RenderCodecBufferToTextureOwner(media_codec_, + codec_buffer_index_); codec_buffer_index_ = kUpdateOnly; } - // Only wait for the SurfaceTexture update if we're rendering to the front. + // Only wait for the TextureOwner update if we're rendering to the front. if (update_mode == UpdateMode::RENDER_TO_FRONT_BUFFER) shared_state_->WaitForFrameAvailable(); } @@ -227,7 +227,7 @@ void AVDACodecImage::GetTextureMatrix(float matrix[16]) { // Our current matrix may be stale. Update it if possible. - if (has_surface_texture_) + if (has_texture_owner_) UpdateSurface(UpdateMode::RENDER_TO_FRONT_BUFFER); shared_state_->GetTransformMatrix(matrix); YInvertMatrix(matrix);
diff --git a/media/gpu/android/avda_codec_image.h b/media/gpu/android/avda_codec_image.h index 78c5978..37071b08 100644 --- a/media/gpu/android/avda_codec_image.h +++ b/media/gpu/android/avda_codec_image.h
@@ -21,7 +21,7 @@ class MediaCodecBridge; -// GLImage that renders MediaCodec buffers to a SurfaceTexture or SurfaceView as +// GLImage that renders MediaCodec buffers to a TextureOwner or SurfaceView as // needed in order to draw them. class AVDACodecImage : public gpu::gles2::GLStreamTextureImage { public: @@ -61,11 +61,11 @@ DISCARD_CODEC_BUFFER, // Renders to back buffer, no UpdateTexImage(); can only be used with a - // valid |surface_texture_|. + // valid |texture_owner_|. RENDER_TO_BACK_BUFFER, // Renders to the back buffer. When used with a SurfaceView, promotion to - // the front buffer is automatic. When using a |surface_texture_|, + // the front buffer is automatic. When using a |texture_owner_|, // UpdateTexImage() is called to promote the back buffer into the front. RENDER_TO_FRONT_BUFFER }; @@ -81,10 +81,10 @@ void set_texture(gpu::gles2::Texture* texture) { texture_ = texture; } // Sets up the properties necessary for the image to render. |buffer_index| is - // supplied to ReleaseOutputBuffer(), |has_surface_texture| controls which + // supplied to ReleaseOutputBuffer(), |has_texture_owner| controls which // rendering path is used, and |size| is used by the compositor. void SetBufferMetadata(int buffer_index, - bool has_surface_texture, + bool has_texture_owner, const gfx::Size& size); bool SetSharedState(scoped_refptr<AVDASharedState> shared_state); @@ -105,18 +105,18 @@ ~AVDACodecImage() override; private: - // Make sure that the surface texture's front buffer is current. This will + // Make sure that the texture owner's front buffer is current. This will // save / restore the current context. It will optionally restore the texture - // bindings in the surface texture's context, based on |mode|. This is + // bindings in the texture owner's context, based on |mode|. This is // intended as a hint if we don't need to change contexts. If we do need to // change contexts, then we'll always preserve the texture bindings in the // both contexts. In other words, the caller is telling us whether it's // okay to change the binding in the current context. enum RestoreBindingsMode { kDontRestoreBindings, kDoRestoreBindings }; - void UpdateSurfaceTexture(RestoreBindingsMode mode); + void UpdateTextureOwner(RestoreBindingsMode mode); // Internal helper for UpdateSurface() that allows callers to specify the - // RestoreBindingsMode when a SurfaceTexture is already attached prior to + // RestoreBindingsMode when a TextureOwner is already attached prior to // calling this method. void UpdateSurfaceInternal(UpdateMode update_mode, RestoreBindingsMode attached_bindings_mode); @@ -148,9 +148,9 @@ // May be null. MediaCodecBridge* media_codec_; - // Indicates if we're rendering to a SurfaceTexture or not. Set during the + // Indicates if we're rendering to a TextureOwner or not. Set during the // call to SetBufferMetadata(). - bool has_surface_texture_; + bool has_texture_owner_; // The texture that we're attached to. gpu::gles2::Texture* texture_;
diff --git a/media/gpu/android/avda_picture_buffer_manager.cc b/media/gpu/android/avda_picture_buffer_manager.cc index feb47dcc..ee4c4ee 100644 --- a/media/gpu/android/avda_picture_buffer_manager.cc +++ b/media/gpu/android/avda_picture_buffer_manager.cc
@@ -49,20 +49,19 @@ bool AVDAPictureBufferManager::Initialize( scoped_refptr<AVDASurfaceBundle> surface_bundle) { shared_state_ = nullptr; - surface_texture_ = nullptr; + texture_owner_ = nullptr; if (!surface_bundle->overlay) { - // Create the surface texture. - surface_texture_ = SurfaceTextureGLOwnerImpl::Create(); - if (!surface_texture_) + // Create the texture owner. + texture_owner_ = SurfaceTextureGLOwner::Create(); + if (!texture_owner_) return false; - surface_bundle->surface_texture_surface = - surface_texture_->CreateJavaSurface(); - surface_bundle->surface_texture = surface_texture_; + surface_bundle->texture_owner_surface = texture_owner_->CreateJavaSurface(); + surface_bundle->texture_owner_ = texture_owner_; } - // Only do this once the surface texture is filled in, since the constructor + // Only do this once the texture owner is filled in, since the constructor // assumes that it will be. shared_state_ = new AVDASharedState(surface_bundle); shared_state_->SetPromotionHintCB(state_provider_->GetPromotionHintCB()); @@ -77,7 +76,7 @@ ReleaseCodecBuffers(buffers); CodecChanged(nullptr); - surface_texture_ = nullptr; + texture_owner_ = nullptr; } void AVDAPictureBufferManager::SetImageForPicture( @@ -98,8 +97,8 @@ GLuint stream_texture_service_id = 0; if (image) { // Override the Texture's service id, so that it will use the one that is - // attached to the SurfaceTexture. - stream_texture_service_id = shared_state_->surface_texture_service_id(); + // attached to the TextureOwner + stream_texture_service_id = shared_state_->texture_owner_service_id(); // Also set the parameters for the level if we're not clearing the image. const gfx::Size size = state_provider_->GetSize(); @@ -110,16 +109,16 @@ static_cast<AVDACodecImage*>(image)->set_texture(texture_ref->texture()); } - // If we're clearing the image, or setting a SurfaceTexture backed image, we - // set the state to UNBOUND. For SurfaceTexture images, this ensures that the + // If we're clearing the image, or setting a TextureOwner backed image, we + // set the state to UNBOUND. For TextureOwner images, this ensures that the // implementation will call CopyTexImage, which is where AVDACodecImage - // updates the SurfaceTexture to the right frame. + // updates the TextureOwner to the right frame. auto image_state = gpu::gles2::Texture::UNBOUND; // For SurfaceView we set the state to BOUND because ScheduleOverlayPlane // requires it. If something tries to sample from this texture it won't work, // but there's no way to sample from a SurfaceView anyway, so it doesn't // matter. - if (image && !surface_texture_) + if (image && !texture_owner_) image_state = gpu::gles2::Texture::BOUND; texture_manager->SetLevelStreamTextureImage(texture_ref, kTextureTarget, 0, image, image_state, @@ -144,7 +143,7 @@ // Note that this is not a race, since we do not re-use a PictureBuffer // until after the CC is done drawing it. pictures_out_for_display_.push_back(picture_buffer.id()); - avda_image->SetBufferMetadata(codec_buf_index, !!surface_texture_, + avda_image->SetBufferMetadata(codec_buf_index, !!texture_owner_, state_provider_->GetSize()); // If the shared state has changed for this image, retarget its texture. @@ -157,7 +156,7 @@ void AVDAPictureBufferManager::AssignOnePictureBuffer( const PictureBuffer& picture_buffer, bool have_context) { - // Attach a GLImage to each texture that will use the surface texture. + // Attach a GLImage to each texture that will use the texture owner. scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image = codec_images_[picture_buffer.id()] = new AVDACodecImage(shared_state_, media_codec_); @@ -222,10 +221,10 @@ AVDACodecImage::UpdateMode::RENDER_TO_FRONT_BUFFER); } - // Back buffer rendering is only available for surface textures. We'll always + // Back buffer rendering is only available for texture owners. We'll always // have at least one front buffer, so the next buffer must be the backbuffer. size_t backbuffer_index = front_index + 1; - if (!surface_texture_ || backbuffer_index >= pictures_out_for_display_.size()) + if (!texture_owner_ || backbuffer_index >= pictures_out_for_display_.size()) return; // See if the back buffer is free. If so, then render the frame adjacent to @@ -252,7 +251,7 @@ bool AVDAPictureBufferManager::ArePicturesOverlayable() { // SurfaceView frames are always overlayable because that's the only way to // display them. - return !surface_texture_; + return !texture_owner_; } bool AVDAPictureBufferManager::HasUnrenderedPictures() const {
diff --git a/media/gpu/android/avda_picture_buffer_manager.h b/media/gpu/android/avda_picture_buffer_manager.h index f2bcc0c..76821f9 100644 --- a/media/gpu/android/avda_picture_buffer_manager.h +++ b/media/gpu/android/avda_picture_buffer_manager.h
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "media/gpu/android/avda_state_provider.h" #include "media/gpu/android/avda_surface_bundle.h" -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include "media/gpu/media_gpu_export.h" namespace gpu { @@ -28,7 +28,7 @@ // AVDAPictureBufferManager is used by AVDA to associate its PictureBuffers with // MediaCodec output buffers. It attaches AVDACodecImages to the PictureBuffer // textures so that when they're used to draw the AVDACodecImage can release the -// MediaCodec buffer to the backing Surface. If the Surface is a SurfaceTexture, +// MediaCodec buffer to the backing Surface. If the Surface is a TextureOwner, // the front buffer can then be used to draw without needing to copy the pixels. // If the Surface is a SurfaceView, the release causes the frame to be displayed // immediately. @@ -46,7 +46,7 @@ // (e.g., SurfaceFlinger). We will ensure that any reference to the bundle // is dropped if the overlay sends OnSurfaceDestroyed. // - // Without an overlay, we will create a SurfaceTexture and add it (and its + // Without an overlay, we will create a TextureOwner and add it (and its // surface) to |surface_bundle|. We will arrange to consume the buffers at // the right time, in addition to releasing the codec buffers for rendering. // @@ -111,9 +111,9 @@ AVDAStateProvider* const state_provider_; - // The SurfaceTexture to render to. Non-null after Initialize() if + // The texture owner to render to. Non-null after Initialize() if // we're not rendering to a SurfaceView. - scoped_refptr<SurfaceTextureGLOwner> surface_texture_; + scoped_refptr<TextureOwner> texture_owner_; MediaCodecBridge* media_codec_;
diff --git a/media/gpu/android/avda_shared_state.cc b/media/gpu/android/avda_shared_state.cc index dbb035370..fa667246 100644 --- a/media/gpu/android/avda_shared_state.cc +++ b/media/gpu/android/avda_shared_state.cc
@@ -33,23 +33,22 @@ AVDASharedState::~AVDASharedState() = default; -void AVDASharedState::RenderCodecBufferToSurfaceTexture( - MediaCodecBridge* codec, - int codec_buffer_index) { - if (surface_texture()->IsExpectingFrameAvailable()) - surface_texture()->WaitForFrameAvailable(); +void AVDASharedState::RenderCodecBufferToTextureOwner(MediaCodecBridge* codec, + int codec_buffer_index) { + if (texture_owner()->IsExpectingFrameAvailable()) + texture_owner()->WaitForFrameAvailable(); codec->ReleaseOutputBuffer(codec_buffer_index, true); - surface_texture()->SetReleaseTimeToNow(); + texture_owner()->SetReleaseTimeToNow(); } void AVDASharedState::WaitForFrameAvailable() { - surface_texture()->WaitForFrameAvailable(); + texture_owner()->WaitForFrameAvailable(); } void AVDASharedState::UpdateTexImage() { - surface_texture()->UpdateTexImage(); + texture_owner()->UpdateTexImage(); // Helpfully, this is already column major. - surface_texture()->GetTransformMatrix(gl_matrix_); + texture_owner()->GetTransformMatrix(gl_matrix_); } void AVDASharedState::GetTransformMatrix(float matrix[16]) const { @@ -57,8 +56,8 @@ } void AVDASharedState::ClearReleaseTime() { - if (surface_texture()) - surface_texture()->IgnorePendingRelease(); + if (texture_owner()) + texture_owner()->IgnorePendingRelease(); } void AVDASharedState::ClearOverlay(AndroidOverlay* overlay_raw) {
diff --git a/media/gpu/android/avda_shared_state.h b/media/gpu/android/avda_shared_state.h index 3110eb0..954f775 100644 --- a/media/gpu/android/avda_shared_state.h +++ b/media/gpu/android/avda_shared_state.h
@@ -29,59 +29,59 @@ public: AVDASharedState(scoped_refptr<AVDASurfaceBundle> surface_bundle); - GLuint surface_texture_service_id() const { - return surface_texture() ? surface_texture()->GetTextureId() : 0; + GLuint texture_owner_service_id() const { + return texture_owner() ? texture_owner()->GetTextureId() : 0; } - SurfaceTextureGLOwner* surface_texture() const { - return surface_bundle_ ? surface_bundle_->surface_texture.get() : nullptr; + TextureOwner* texture_owner() const { + return surface_bundle_ ? surface_bundle_->texture_owner_.get() : nullptr; } AndroidOverlay* overlay() const { return surface_bundle_ ? surface_bundle_->overlay.get() : nullptr; } - // Context and surface that |surface_texture_| is bound to, if - // |surface_texture_| is not null. + // Context and surface that |texture_owner_| is bound to, if + // |texture_owner_| is not null. gl::GLContext* context() const { - return surface_texture() ? surface_texture()->GetContext() : nullptr; + return texture_owner() ? texture_owner()->GetContext() : nullptr; } gl::GLSurface* surface() const { - return surface_texture() ? surface_texture()->GetSurface() : nullptr; + return texture_owner() ? texture_owner()->GetSurface() : nullptr; } // Helper method for coordinating the interactions between // MediaCodec::ReleaseOutputBuffer() and WaitForFrameAvailable() when - // rendering to a SurfaceTexture; this method should never be called when + // rendering to a TextureOwner; this method should never be called when // rendering to a SurfaceView. // - // The release of the codec buffer to the surface texture is asynchronous, by + // The release of the codec buffer to the texture owner is asynchronous, by // using this helper we can attempt to let this process complete in a non - // blocking fashion before the SurfaceTexture is used. + // blocking fashion before the TextureOwner is used. // // Clients should call this method to release the codec buffer for rendering - // and then call WaitForFrameAvailable() before using the SurfaceTexture. In - // the ideal case the SurfaceTexture has already been updated, otherwise the + // and then call WaitForFrameAvailable() before using the TextureOwner. In + // the ideal case the TextureOwner has already been updated, otherwise the // method will wait for a pro-rated amount of time based on elapsed time up // to a short deadline. // // Some devices do not reliably notify frame availability, so we use a very // short deadline of only a few milliseconds to avoid indefinite stalls. - void RenderCodecBufferToSurfaceTexture(MediaCodecBridge* codec, - int codec_buffer_index); + void RenderCodecBufferToTextureOwner(MediaCodecBridge* codec, + int codec_buffer_index); void WaitForFrameAvailable(); - // Helper methods for interacting with |surface_texture_|. See - // gl::SurfaceTexture for method details. + // Helper methods for interacting with |texture_owner_|. See + // gl::TextureOwner for method details. void UpdateTexImage(); // Returns a matrix that needs to be y flipped in order to match the // StreamTextureMatrix contract. See GLStreamTextureImage::YInvertMatrix(). void GetTransformMatrix(float matrix[16]) const; - // Resets the last time for RenderCodecBufferToSurfaceTexture(). Should be + // Resets the last time for RenderCodecBufferToTextureOwner(). Should be // called during codec changes. void ClearReleaseTime(); @@ -96,7 +96,7 @@ private: friend class base::RefCounted<AVDASharedState>; - // Texture matrix of the front buffer of the surface texture. + // Texture matrix of the front buffer of the texture owner. float gl_matrix_[16]; scoped_refptr<AVDASurfaceBundle> surface_bundle_;
diff --git a/media/gpu/android/avda_surface_bundle.cc b/media/gpu/android/avda_surface_bundle.cc index 1c09e8fcd..38c1320 100644 --- a/media/gpu/android/avda_surface_bundle.cc +++ b/media/gpu/android/avda_surface_bundle.cc
@@ -20,28 +20,27 @@ overlay(std::move(overlay)), weak_factory_(this) {} -AVDASurfaceBundle::AVDASurfaceBundle( - scoped_refptr<SurfaceTextureGLOwner> surface_texture_owner) +AVDASurfaceBundle::AVDASurfaceBundle(scoped_refptr<TextureOwner> texture_owner) : RefCountedDeleteOnSequence<AVDASurfaceBundle>( base::SequencedTaskRunnerHandle::Get()), - surface_texture(std::move(surface_texture_owner)), - surface_texture_surface(surface_texture->CreateJavaSurface()), + texture_owner_(std::move(texture_owner)), + texture_owner_surface(texture_owner_->CreateJavaSurface()), weak_factory_(this) {} AVDASurfaceBundle::~AVDASurfaceBundle() { // Explicitly free the surface first, just to be sure that it's deleted before - // the SurfaceTexture is. - surface_texture_surface = gl::ScopedJavaSurface(); + // the TextureOwner is. + texture_owner_surface = gl::ScopedJavaSurface(); // Also release the back buffers. - if (surface_texture) { - auto task_runner = surface_texture->task_runner(); + if (texture_owner_) { + auto task_runner = texture_owner_->task_runner(); if (task_runner->RunsTasksInCurrentSequence()) { - surface_texture->ReleaseBackBuffers(); + texture_owner_->ReleaseBackBuffers(); } else { task_runner->PostTask( - FROM_HERE, base::Bind(&SurfaceTextureGLOwner::ReleaseBackBuffers, - surface_texture)); + FROM_HERE, base::BindRepeating(&TextureOwner::ReleaseBackBuffers, + texture_owner_)); } } } @@ -51,7 +50,7 @@ if (overlay) return overlay->GetJavaSurface(); else - return surface_texture_surface.j_surface(); + return texture_owner_surface.j_surface(); } AVDASurfaceBundle::ScheduleLayoutCB AVDASurfaceBundle::GetScheduleLayoutCB() {
diff --git a/media/gpu/android/avda_surface_bundle.h b/media/gpu/android/avda_surface_bundle.h index e0dc749..7e08b2a 100644 --- a/media/gpu/android/avda_surface_bundle.h +++ b/media/gpu/android/avda_surface_bundle.h
@@ -8,13 +8,13 @@ #include "base/memory/ref_counted_delete_on_sequence.h" #include "media/base/android/android_overlay.h" #include "media/base/surface_manager.h" -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include "media/gpu/media_gpu_export.h" #include "ui/gl/android/scoped_java_surface.h" namespace media { -// AVDASurfaceBundle is a Java surface, and the SurfaceTexture or Overlay that +// AVDASurfaceBundle is a Java surface, and the TextureOwner or Overlay that // backs it. // // Once a MediaCodec is configured with an output surface, the corresponding @@ -29,8 +29,7 @@ // Create an empty bundle to be manually populated. explicit AVDASurfaceBundle(); explicit AVDASurfaceBundle(std::unique_ptr<AndroidOverlay> overlay); - explicit AVDASurfaceBundle( - scoped_refptr<SurfaceTextureGLOwner> surface_texture_owner); + explicit AVDASurfaceBundle(scoped_refptr<TextureOwner> texture_owner); const base::android::JavaRef<jobject>& GetJavaSurface() const; @@ -39,12 +38,12 @@ // |this|; the cb will do nothing if |this| is destroyed. ScheduleLayoutCB GetScheduleLayoutCB(); - // The Overlay or SurfaceTexture. + // The Overlay or TextureOwner. std::unique_ptr<AndroidOverlay> overlay; - scoped_refptr<SurfaceTextureGLOwner> surface_texture; + scoped_refptr<TextureOwner> texture_owner_; - // The Java surface for |surface_texture|. - gl::ScopedJavaSurface surface_texture_surface; + // The Java surface for |texture_owner_|. + gl::ScopedJavaSurface texture_owner_surface; private: ~AVDASurfaceBundle();
diff --git a/media/gpu/android/codec_image.cc b/media/gpu/android/codec_image.cc index 4e9450c1..face8a2 100644 --- a/media/gpu/android/codec_image.cc +++ b/media/gpu/android/codec_image.cc
@@ -10,35 +10,34 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/texture_manager.h" -#include "media/gpu/android/surface_texture_gl_owner.h" #include "ui/gl/gl_context.h" #include "ui/gl/scoped_make_current.h" namespace media { namespace { -// Makes |surface_texture|'s context current if it isn't already. +// Makes |texture_owner|'s context current if it isn't already. std::unique_ptr<ui::ScopedMakeCurrent> MakeCurrentIfNeeded( - SurfaceTextureGLOwner* surface_texture) { + TextureOwner* texture_owner) { // Note: this works for virtual contexts too, because IsCurrent() returns true // if their shared platform context is current, regardless of which virtual // context is current. return std::unique_ptr<ui::ScopedMakeCurrent>( - surface_texture->GetContext()->IsCurrent(nullptr) + texture_owner->GetContext()->IsCurrent(nullptr) ? nullptr - : new ui::ScopedMakeCurrent(surface_texture->GetContext(), - surface_texture->GetSurface())); + : new ui::ScopedMakeCurrent(texture_owner->GetContext(), + texture_owner->GetSurface())); } } // namespace CodecImage::CodecImage( std::unique_ptr<CodecOutputBuffer> output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb) : phase_(Phase::kInCodec), output_buffer_(std::move(output_buffer)), - surface_texture_(std::move(surface_texture)), + texture_owner_(std::move(texture_owner)), promotion_hint_cb_(std::move(promotion_hint_cb)) {} CodecImage::~CodecImage() { @@ -68,16 +67,16 @@ void CodecImage::ReleaseTexImage(unsigned target) {} bool CodecImage::CopyTexImage(unsigned target) { - if (!surface_texture_ || target != GL_TEXTURE_EXTERNAL_OES) + if (!texture_owner_ || target != GL_TEXTURE_EXTERNAL_OES) return false; GLint bound_service_id = 0; glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); - // The currently bound texture should be the surface texture's texture. - if (bound_service_id != static_cast<GLint>(surface_texture_->GetTextureId())) + // The currently bound texture should be the texture owner's texture. + if (bound_service_id != static_cast<GLint>(texture_owner_->GetTextureId())) return false; - RenderToSurfaceTextureFrontBuffer(BindingsMode::kDontRestore); + RenderToTextureOwnerFrontBuffer(BindingsMode::kDontRestore); return true; } @@ -93,9 +92,9 @@ const gfx::Rect& bounds_rect, const gfx::RectF& crop_rect, bool enable_blend) { - if (surface_texture_) { + if (texture_owner_) { DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is " - "SurfaceTexture backed."; + "TextureOwner backed."; return false; } @@ -127,14 +126,14 @@ 0, 1, 0, 1 // }; memcpy(matrix, kYInvertedIdentity, sizeof(kYInvertedIdentity)); - if (!surface_texture_) + if (!texture_owner_) return; // The matrix is available after we render to the front buffer. If that fails // we'll return the matrix from the previous frame, which is more likely to be // correct than the identity matrix anyway. - RenderToSurfaceTextureFrontBuffer(BindingsMode::kDontRestore); - surface_texture_->GetTransformMatrix(matrix); + RenderToTextureOwnerFrontBuffer(BindingsMode::kDontRestore); + texture_owner_->GetTransformMatrix(matrix); YInvertMatrix(matrix); } @@ -145,7 +144,7 @@ int display_height) { // If this is promotable, and we're using an overlay, then skip sending this // hint. ScheduleOverlayPlane will do it. - if (promotion_hint && !surface_texture_) + if (promotion_hint && !texture_owner_) return; promotion_hint_cb_.Run(PromotionHintAggregator::Hint( @@ -154,13 +153,13 @@ } bool CodecImage::RenderToFrontBuffer() { - return surface_texture_ - ? RenderToSurfaceTextureFrontBuffer(BindingsMode::kRestore) + return texture_owner_ + ? RenderToTextureOwnerFrontBuffer(BindingsMode::kRestore) : RenderToOverlay(); } -bool CodecImage::RenderToSurfaceTextureBackBuffer() { - DCHECK(surface_texture_); +bool CodecImage::RenderToTextureOwnerBackBuffer() { + DCHECK(texture_owner_); DCHECK_NE(phase_, Phase::kInFrontBuffer); if (phase_ == Phase::kInBackBuffer) return true; @@ -169,35 +168,35 @@ // Wait for a previous frame available so we don't confuse it with the one // we're about to release. - if (surface_texture_->IsExpectingFrameAvailable()) - surface_texture_->WaitForFrameAvailable(); + if (texture_owner_->IsExpectingFrameAvailable()) + texture_owner_->WaitForFrameAvailable(); if (!output_buffer_->ReleaseToSurface()) { phase_ = Phase::kInvalidated; return false; } phase_ = Phase::kInBackBuffer; - surface_texture_->SetReleaseTimeToNow(); + texture_owner_->SetReleaseTimeToNow(); return true; } -bool CodecImage::RenderToSurfaceTextureFrontBuffer(BindingsMode bindings_mode) { - DCHECK(surface_texture_); +bool CodecImage::RenderToTextureOwnerFrontBuffer(BindingsMode bindings_mode) { + DCHECK(texture_owner_); if (phase_ == Phase::kInFrontBuffer) return true; if (phase_ == Phase::kInvalidated) return false; // Render it to the back buffer if it's not already there. - if (!RenderToSurfaceTextureBackBuffer()) + if (!RenderToTextureOwnerBackBuffer()) return false; // The image is now in the back buffer, so promote it to the front buffer. phase_ = Phase::kInFrontBuffer; - if (surface_texture_->IsExpectingFrameAvailable()) - surface_texture_->WaitForFrameAvailable(); + if (texture_owner_->IsExpectingFrameAvailable()) + texture_owner_->WaitForFrameAvailable(); std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current = - MakeCurrentIfNeeded(surface_texture_.get()); + MakeCurrentIfNeeded(texture_owner_.get()); // If we have to switch contexts, then we always want to restore the // bindings. bool should_restore_bindings = @@ -206,7 +205,7 @@ GLint bound_service_id = 0; if (should_restore_bindings) glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id); - surface_texture_->UpdateTexImage(); + texture_owner_->UpdateTexImage(); if (should_restore_bindings) glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id); return true;
diff --git a/media/gpu/android/codec_image.h b/media/gpu/android/codec_image.h index 19eb6c4b..df4a12a 100644 --- a/media/gpu/android/codec_image.h +++ b/media/gpu/android/codec_image.h
@@ -14,12 +14,12 @@ #include "gpu/command_buffer/service/gl_stream_texture_image.h" #include "media/gpu/android/codec_wrapper.h" #include "media/gpu/android/promotion_hint_aggregator.h" -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include "media/gpu/media_gpu_export.h" namespace media { -// A GLImage that renders MediaCodec buffers to a SurfaceTexture or overlay +// A GLImage that renders MediaCodec buffers to a TextureOwner or overlay // as needed in order to draw them. class MEDIA_GPU_EXPORT CodecImage : public gpu::gles2::GLStreamTextureImage { public: @@ -28,7 +28,7 @@ using DestructionCb = base::RepeatingCallback<void(CodecImage*)>; CodecImage(std::unique_ptr<CodecOutputBuffer> output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb); void SetDestructionCb(DestructionCb destruction_cb); @@ -66,12 +66,10 @@ return phase_ == Phase::kInFrontBuffer; } - // Whether this image is backed by a surface texture. - bool is_surface_texture_backed() const { return !!surface_texture_; } + // Whether this image is backed by a texture owner. + bool is_texture_owner_backed() const { return !!texture_owner_; } - scoped_refptr<SurfaceTextureGLOwner> surface_texture() const { - return surface_texture_; - } + scoped_refptr<TextureOwner> texture_owner() const { return texture_owner_; } // Renders this image to the front buffer of its backing surface. // Returns true if the buffer is in the front buffer. Returns false if the @@ -79,10 +77,10 @@ // possible to render it. bool RenderToFrontBuffer(); - // Renders this image to the back buffer of its surface texture. Only valid if - // is_surface_texture_backed(). Returns true if the buffer is in the back + // Renders this image to the back buffer of its texture owner. Only valid if + // is_texture_owner_backed(). Returns true if the buffer is in the back // buffer. Returns false if the buffer was invalidated. - bool RenderToSurfaceTextureBackBuffer(); + bool RenderToTextureOwnerBackBuffer(); // Called when we're no longer renderable because our surface is gone. We'll // discard any codec buffer, and generally do nothing. @@ -97,16 +95,16 @@ // kInFrontBuffer and kInvalidated are terminal. enum class Phase { kInCodec, kInBackBuffer, kInFrontBuffer, kInvalidated }; - // Renders this image to the surface texture front buffer by first rendering + // Renders this image to the texture owner front buffer by first rendering // it to the back buffer if it's not already there, and then waiting for the // frame available event before calling UpdateTexImage(). Passing // BindingsMode::kDontRestore skips the work of restoring the current texture - // bindings if the surface texture's context is already current. Otherwise, + // bindings if the texture owner's context is already current. Otherwise, // this switches contexts and preserves the texture bindings. // Returns true if the buffer is in the front buffer. Returns false if the // buffer was invalidated. enum class BindingsMode { kRestore, kDontRestore }; - bool RenderToSurfaceTextureFrontBuffer(BindingsMode bindings_mode); + bool RenderToTextureOwnerFrontBuffer(BindingsMode bindings_mode); // Renders this image to the overlay. Returns true if the buffer is in the // overlay front buffer. Returns false if the buffer was invalidated. @@ -118,9 +116,9 @@ // The buffer backing this image. std::unique_ptr<CodecOutputBuffer> output_buffer_; - // The SurfaceTexture that |output_buffer_| will be rendered to. Or null, if + // The TextureOwner that |output_buffer_| will be rendered to. Or null, if // this image is backed by an overlay. - scoped_refptr<SurfaceTextureGLOwner> surface_texture_; + scoped_refptr<TextureOwner> texture_owner_; // The bounds last sent to the overlay. gfx::Rect most_recent_bounds_;
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc index 702e5d7..ccae01c 100644 --- a/media/gpu/android/codec_image_unittest.cc +++ b/media/gpu/android/codec_image_unittest.cc
@@ -13,7 +13,7 @@ #include "media/base/android/media_codec_bridge.h" #include "media/base/android/mock_media_codec_bridge.h" #include "media/gpu/android/codec_image.h" -#include "media/gpu/android/mock_surface_texture_gl_owner.h" +#include "media/gpu/android/mock_texture_owner.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/rect.h" @@ -59,8 +59,8 @@ glGenTextures(1, &texture_id); // The tests rely on this texture being bound. glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); - surface_texture_ = new NiceMock<MockSurfaceTextureGLOwner>( - texture_id, context_.get(), surface_.get()); + texture_owner_ = new NiceMock<MockTextureOwner>(texture_id, context_.get(), + surface_.get()); } void TearDown() override { @@ -71,14 +71,14 @@ wrapper_->TakeCodecSurfacePair(); } - enum ImageKind { kOverlay, kSurfaceTexture }; + enum ImageKind { kOverlay, kTextureOwner }; scoped_refptr<CodecImage> NewImage( ImageKind kind, CodecImage::DestructionCb destruction_cb = base::DoNothing()) { std::unique_ptr<CodecOutputBuffer> buffer; wrapper_->DequeueOutputBuffer(nullptr, nullptr, &buffer); scoped_refptr<CodecImage> image = new CodecImage( - std::move(buffer), kind == kSurfaceTexture ? surface_texture_ : nullptr, + std::move(buffer), kind == kTextureOwner ? texture_owner_ : nullptr, base::BindRepeating(&PromotionHintReceiver::OnPromotionHint, base::Unretained(&promotion_hint_receiver_))); @@ -89,7 +89,7 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; NiceMock<MockMediaCodecBridge>* codec_; std::unique_ptr<CodecWrapper> wrapper_; - scoped_refptr<NiceMock<MockSurfaceTextureGLOwner>> surface_texture_; + scoped_refptr<NiceMock<MockTextureOwner>> texture_owner_; scoped_refptr<gl::GLContext> context_; scoped_refptr<gl::GLShareGroup> share_group_; scoped_refptr<gl::GLSurface> surface_; @@ -110,7 +110,7 @@ } TEST_F(CodecImageTest, ImageStartsUnrendered) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); ASSERT_FALSE(i->was_rendered_to_front_buffer()); } @@ -119,20 +119,20 @@ ASSERT_FALSE(i->CopyTexImage(GL_TEXTURE_EXTERNAL_OES)); } -TEST_F(CodecImageTest, ScheduleOverlayPlaneIsInvalidForSurfaceTextureImages) { - auto i = NewImage(kSurfaceTexture); +TEST_F(CodecImageTest, ScheduleOverlayPlaneIsInvalidForTextureOwnerImages) { + auto i = NewImage(kTextureOwner); ASSERT_FALSE(i->ScheduleOverlayPlane(gfx::AcceleratedWidget(), 0, gfx::OverlayTransform(), gfx::Rect(), gfx::RectF(), true)); } TEST_F(CodecImageTest, CopyTexImageFailsIfTargetIsNotOES) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); ASSERT_FALSE(i->CopyTexImage(GL_TEXTURE_2D)); } TEST_F(CodecImageTest, CopyTexImageFailsIfTheWrongTextureIsBound) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); GLuint wrong_texture_id; glGenTextures(1, &wrong_texture_id); glBindTexture(GL_TEXTURE_EXTERNAL_OES, wrong_texture_id); @@ -140,29 +140,29 @@ } TEST_F(CodecImageTest, CopyTexImageCanBeCalledRepeatedly) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); ASSERT_TRUE(i->CopyTexImage(GL_TEXTURE_EXTERNAL_OES)); ASSERT_TRUE(i->CopyTexImage(GL_TEXTURE_EXTERNAL_OES)); } TEST_F(CodecImageTest, CopyTexImageTriggersFrontBufferRendering) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); // Verify that the release comes before the wait. InSequence s; EXPECT_CALL(*codec_, ReleaseOutputBuffer(_, true)); - EXPECT_CALL(*surface_texture_, WaitForFrameAvailable()); - EXPECT_CALL(*surface_texture_, UpdateTexImage()); + EXPECT_CALL(*texture_owner_, WaitForFrameAvailable()); + EXPECT_CALL(*texture_owner_, UpdateTexImage()); i->CopyTexImage(GL_TEXTURE_EXTERNAL_OES); ASSERT_TRUE(i->was_rendered_to_front_buffer()); } TEST_F(CodecImageTest, GetTextureMatrixTriggersFrontBufferRendering) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); InSequence s; EXPECT_CALL(*codec_, ReleaseOutputBuffer(_, true)); - EXPECT_CALL(*surface_texture_, WaitForFrameAvailable()); - EXPECT_CALL(*surface_texture_, UpdateTexImage()); - EXPECT_CALL(*surface_texture_, GetTransformMatrix(_)); + EXPECT_CALL(*texture_owner_, WaitForFrameAvailable()); + EXPECT_CALL(*texture_owner_, UpdateTexImage()); + EXPECT_CALL(*texture_owner_, GetTransformMatrix(_)); float matrix[16]; i->GetTextureMatrix(matrix); ASSERT_TRUE(i->was_rendered_to_front_buffer()); @@ -189,39 +189,39 @@ ASSERT_TRUE(i->was_rendered_to_front_buffer()); } -TEST_F(CodecImageTest, CanRenderSurfaceTextureImageToBackBuffer) { - auto i = NewImage(kSurfaceTexture); - ASSERT_TRUE(i->RenderToSurfaceTextureBackBuffer()); +TEST_F(CodecImageTest, CanRenderTextureOwnerImageToBackBuffer) { + auto i = NewImage(kTextureOwner); + ASSERT_TRUE(i->RenderToTextureOwnerBackBuffer()); ASSERT_FALSE(i->was_rendered_to_front_buffer()); } TEST_F(CodecImageTest, CodecBufferInvalidationResultsInRenderingFailure) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); // Invalidate the backing codec buffer. wrapper_->TakeCodecSurfacePair(); - ASSERT_FALSE(i->RenderToSurfaceTextureBackBuffer()); + ASSERT_FALSE(i->RenderToTextureOwnerBackBuffer()); } TEST_F(CodecImageTest, RenderToBackBufferDoesntWait) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); InSequence s; EXPECT_CALL(*codec_, ReleaseOutputBuffer(_, true)); - EXPECT_CALL(*surface_texture_, SetReleaseTimeToNow()); - EXPECT_CALL(*surface_texture_, WaitForFrameAvailable()).Times(0); - ASSERT_TRUE(i->RenderToSurfaceTextureBackBuffer()); + EXPECT_CALL(*texture_owner_, SetReleaseTimeToNow()); + EXPECT_CALL(*texture_owner_, WaitForFrameAvailable()).Times(0); + ASSERT_TRUE(i->RenderToTextureOwnerBackBuffer()); } TEST_F(CodecImageTest, PromotingTheBackBufferWaits) { - auto i = NewImage(kSurfaceTexture); - EXPECT_CALL(*surface_texture_, SetReleaseTimeToNow()).Times(1); - i->RenderToSurfaceTextureBackBuffer(); - EXPECT_CALL(*surface_texture_, WaitForFrameAvailable()); + auto i = NewImage(kTextureOwner); + EXPECT_CALL(*texture_owner_, SetReleaseTimeToNow()).Times(1); + i->RenderToTextureOwnerBackBuffer(); + EXPECT_CALL(*texture_owner_, WaitForFrameAvailable()); ASSERT_TRUE(i->RenderToFrontBuffer()); } TEST_F(CodecImageTest, PromotingTheBackBufferAlwaysSucceeds) { - auto i = NewImage(kSurfaceTexture); - i->RenderToSurfaceTextureBackBuffer(); + auto i = NewImage(kTextureOwner); + i->RenderToTextureOwnerBackBuffer(); // Invalidating the codec buffer doesn't matter after it's rendered to the // back buffer. wrapper_->TakeCodecSurfacePair(); @@ -229,9 +229,9 @@ } TEST_F(CodecImageTest, FrontBufferRenderingFailsIfBackBufferRenderingFailed) { - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); wrapper_->TakeCodecSurfacePair(); - i->RenderToSurfaceTextureBackBuffer(); + i->RenderToTextureOwnerBackBuffer(); ASSERT_FALSE(i->RenderToFrontBuffer()); } @@ -239,8 +239,8 @@ GLuint pre_bound_texture = 0; glGenTextures(1, &pre_bound_texture); glBindTexture(GL_TEXTURE_EXTERNAL_OES, pre_bound_texture); - auto i = NewImage(kSurfaceTexture); - EXPECT_CALL(*surface_texture_, UpdateTexImage()); + auto i = NewImage(kTextureOwner); + EXPECT_CALL(*texture_owner_, UpdateTexImage()); i->RenderToFrontBuffer(); GLint post_bound_texture = 0; glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &post_bound_texture); @@ -257,9 +257,9 @@ context->Initialize(surface.get(), gl::GLContextAttribs()); ASSERT_TRUE(context->MakeCurrent(surface.get())); - auto i = NewImage(kSurfaceTexture); + auto i = NewImage(kTextureOwner); // Our context should not be current when UpdateTexImage() is called. - EXPECT_CALL(*surface_texture_, UpdateTexImage()).WillOnce(Invoke([&]() { + EXPECT_CALL(*texture_owner_, UpdateTexImage()).WillOnce(Invoke([&]() { ASSERT_FALSE(context->IsCurrent(surface.get())); })); i->RenderToFrontBuffer();
diff --git a/media/gpu/android/fake_codec_allocator.cc b/media/gpu/android/fake_codec_allocator.cc index 1c9f5d5..e7b80630 100644 --- a/media/gpu/android/fake_codec_allocator.cc +++ b/media/gpu/android/fake_codec_allocator.cc
@@ -30,7 +30,7 @@ std::unique_ptr<MediaCodecBridge> FakeCodecAllocator::CreateMediaCodecSync( scoped_refptr<CodecConfig> config) { CopyCodecConfig(config); - MockCreateMediaCodecSync(most_recent_overlay, most_recent_surface_texture); + MockCreateMediaCodecSync(most_recent_overlay, most_recent_texture_owner); std::unique_ptr<MockMediaCodecBridge> codec; if (allow_sync_creation) { @@ -57,14 +57,14 @@ client_ = client; codec_creation_pending_ = true; - MockCreateMediaCodecAsync(most_recent_overlay, most_recent_surface_texture); + MockCreateMediaCodecAsync(most_recent_overlay, most_recent_texture_owner); } void FakeCodecAllocator::ReleaseMediaCodec( std::unique_ptr<MediaCodecBridge> media_codec, scoped_refptr<AVDASurfaceBundle> surface_bundle) { MockReleaseMediaCodec(media_codec.get(), surface_bundle->overlay.get(), - surface_bundle->surface_texture.get()); + surface_bundle->texture_owner_.get()); } MockMediaCodecBridge* FakeCodecAllocator::ProvideMockCodecAsync( @@ -97,7 +97,7 @@ void FakeCodecAllocator::CopyCodecConfig(scoped_refptr<CodecConfig> config) { // CodecConfig isn't copyable, since it has unique_ptrs and such. most_recent_overlay = config->surface_bundle->overlay.get(); - most_recent_surface_texture = config->surface_bundle->surface_texture.get(); + most_recent_texture_owner = config->surface_bundle->texture_owner_.get(); most_recent_config->media_crypto = config->media_crypto ? std::make_unique<base::android::ScopedJavaGlobalRef<jobject>>(
diff --git a/media/gpu/android/fake_codec_allocator.h b/media/gpu/android/fake_codec_allocator.h index e0ff1dd..5823a06 100644 --- a/media/gpu/android/fake_codec_allocator.h +++ b/media/gpu/android/fake_codec_allocator.h
@@ -30,18 +30,14 @@ // These are called with some parameters of the codec config by our // implementation of their respective functions. This allows tests to set // expectations on them. - MOCK_METHOD2(MockCreateMediaCodecSync, - void(AndroidOverlay*, SurfaceTextureGLOwner*)); - MOCK_METHOD2(MockCreateMediaCodecAsync, - void(AndroidOverlay*, SurfaceTextureGLOwner*)); + MOCK_METHOD2(MockCreateMediaCodecSync, void(AndroidOverlay*, TextureOwner*)); + MOCK_METHOD2(MockCreateMediaCodecAsync, void(AndroidOverlay*, TextureOwner*)); // Note that this doesn't exactly match the signature, since unique_ptr // doesn't work. plus, we expand |surface_bundle| a bit to make it more // convenient to set expectations. MOCK_METHOD3(MockReleaseMediaCodec, - void(MediaCodecBridge*, - AndroidOverlay*, - SurfaceTextureGLOwner*)); + void(MediaCodecBridge*, AndroidOverlay*, TextureOwner*)); std::unique_ptr<MediaCodecBridge> CreateMediaCodecSync( scoped_refptr<CodecConfig> config) override; @@ -70,8 +66,8 @@ // The most recent overlay provided during codec allocation. AndroidOverlay* most_recent_overlay = nullptr; - // The most recent surface texture provided during codec allocation. - SurfaceTextureGLOwner* most_recent_surface_texture = nullptr; + // The most recent texture owner provided during codec allocation. + TextureOwner* most_recent_texture_owner = nullptr; // Whether CreateMediaCodecSync() is allowed to succeed. bool allow_sync_creation = true;
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc index ae312c0d..70e58ff 100644 --- a/media/gpu/android/media_codec_video_decoder.cc +++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -253,7 +253,7 @@ requires_secure_codec_ = requires_secure_video_codec; // Request a secure surface in all cases. For L3, it's okay if we fall back - // to SurfaceTexture rather than fail composition. For L1, it's required. + // to TextureOwner rather than fail composition. For L1, it's required. surface_chooser_helper_.SetSecureSurfaceMode( requires_secure_video_codec ? SurfaceChooserHelper::SecureSurfaceMode::kRequired @@ -286,13 +286,13 @@ } void MediaCodecVideoDecoder::OnVideoFrameFactoryInitialized( - scoped_refptr<SurfaceTextureGLOwner> surface_texture) { + scoped_refptr<TextureOwner> texture_owner) { DVLOG(2) << __func__; - if (!surface_texture) { + if (!texture_owner) { EnterTerminalState(State::kError); return; } - surface_texture_bundle_ = new AVDASurfaceBundle(std::move(surface_texture)); + texture_owner_bundle_ = new AVDASurfaceBundle(std::move(texture_owner)); // Overlays are disabled when |enable_threaded_texture_mailboxes| is true // (http://crbug.com/582170). @@ -338,7 +338,7 @@ weak_factory_.GetWeakPtr())); target_surface_bundle_ = new AVDASurfaceBundle(std::move(overlay)); } else { - target_surface_bundle_ = surface_texture_bundle_; + target_surface_bundle_ = texture_owner_bundle_; } // If we were waiting for our first surface during initialization, then @@ -367,7 +367,7 @@ // Reset the target bundle if it is the one being destroyed. if (target_surface_bundle_ && target_surface_bundle_->overlay.get() == overlay) { - target_surface_bundle_ = surface_texture_bundle_; + target_surface_bundle_ = texture_owner_bundle_; } // Transition the codec away from the overlay if necessary. @@ -747,7 +747,7 @@ pump_codec_timer_.Stop(); ReleaseCodec(); target_surface_bundle_ = nullptr; - surface_texture_bundle_ = nullptr; + texture_owner_bundle_ = nullptr; if (state == State::kError) CancelPendingDecodes(DecodeStatus::DECODE_ERROR); if (drain_type_)
diff --git a/media/gpu/android/media_codec_video_decoder.h b/media/gpu/android/media_codec_video_decoder.h index adbfa1de..1bdaab2 100644 --- a/media/gpu/android/media_codec_video_decoder.h +++ b/media/gpu/android/media_codec_video_decoder.h
@@ -44,7 +44,7 @@ // first Decode() (see StartLazyInit()). We do this because there are cases in // our media pipeline where we'll initialize a decoder but never use it // (e.g., MSE with no media data appended), and if we eagerly allocator decoder -// resources, like MediaCodecs and SurfaceTextures, we will block other +// resources, like MediaCodecs and TextureOwners, we will block other // playbacks that need them. // TODO: Lazy initialization should be handled at a higher layer of the media // stack for both simplicity and cross platform support. @@ -120,7 +120,7 @@ // Finishes initialization. void StartLazyInit(); void OnVideoFrameFactoryInitialized( - scoped_refptr<SurfaceTextureGLOwner> surface_texture); + scoped_refptr<TextureOwner> texture_owner); // Resets |waiting_for_key_| to false, indicating that MediaCodec might now // accept buffers. @@ -242,9 +242,9 @@ // non-null from the first surface choice. scoped_refptr<AVDASurfaceBundle> target_surface_bundle_; - // A SurfaceTexture bundle that is kept for the lifetime of MCVD so that if we + // A TextureOwner bundle that is kept for the lifetime of MCVD so that if we // have to synchronously switch surfaces we always have one available. - scoped_refptr<AVDASurfaceBundle> surface_texture_bundle_; + scoped_refptr<AVDASurfaceBundle> texture_owner_bundle_; // A callback for requesting overlay info updates. RequestOverlayInfoCB request_overlay_info_cb_; @@ -267,7 +267,7 @@ // Most recently cached frame information, so that we can dispatch it without // recomputing it on every frame. It changes very rarely. SurfaceChooserHelper::FrameInformation cached_frame_information_ = - SurfaceChooserHelper::FrameInformation::SURFACETEXTURE_INSECURE; + SurfaceChooserHelper::FrameInformation::NON_OVERLAY_INSECURE; // CDM related stuff.
diff --git a/media/gpu/android/media_codec_video_decoder_unittest.cc b/media/gpu/android/media_codec_video_decoder_unittest.cc index 3032532..38bc0b88 100644 --- a/media/gpu/android/media_codec_video_decoder_unittest.cc +++ b/media/gpu/android/media_codec_video_decoder_unittest.cc
@@ -21,7 +21,7 @@ #include "media/gpu/android/fake_codec_allocator.h" #include "media/gpu/android/mock_android_video_surface_chooser.h" #include "media/gpu/android/mock_device_info.h" -#include "media/gpu/android/mock_surface_texture_gl_owner.h" +#include "media/gpu/android/mock_texture_owner.h" #include "media/gpu/android/video_frame_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -61,7 +61,7 @@ MOCK_METHOD6( MockCreateVideoFrame, void(CodecOutputBuffer* raw_output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner, base::TimeDelta timestamp, gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, @@ -74,10 +74,10 @@ scoped_refptr<AVDASurfaceBundle> surface_bundle) override { MockSetSurfaceBundle(surface_bundle); if (!surface_bundle) { - surface_texture_ = nullptr; + texture_owner_ = nullptr; } else { - surface_texture_ = - surface_bundle->overlay ? nullptr : surface_bundle->surface_texture; + texture_owner_ = + surface_bundle->overlay ? nullptr : surface_bundle->texture_owner_; } } @@ -87,7 +87,7 @@ gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, VideoDecoder::OutputCB output_cb) override { - MockCreateVideoFrame(output_buffer.get(), surface_texture_, timestamp, + MockCreateVideoFrame(output_buffer.get(), texture_owner_, timestamp, natural_size, promotion_hint_cb, output_cb); last_output_buffer_ = std::move(output_buffer); output_cb.Run(VideoFrame::CreateBlackFrame(gfx::Size(10, 10))); @@ -99,7 +99,7 @@ } std::unique_ptr<CodecOutputBuffer> last_output_buffer_; - scoped_refptr<SurfaceTextureGLOwner> surface_texture_; + scoped_refptr<TextureOwner> texture_owner_; base::OnceClosure last_closure_; }; @@ -126,19 +126,18 @@ std::make_unique<NiceMock<MockAndroidVideoSurfaceChooser>>(); surface_chooser_ = surface_chooser.get(); - auto surface_texture = - base::MakeRefCounted<NiceMock<MockSurfaceTextureGLOwner>>(0, nullptr, - nullptr); - surface_texture_ = surface_texture.get(); + auto texture_owner = + base::MakeRefCounted<NiceMock<MockTextureOwner>>(0, nullptr, nullptr); + texture_owner_ = texture_owner.get(); auto video_frame_factory = std::make_unique<NiceMock<MockVideoFrameFactory>>(); video_frame_factory_ = video_frame_factory.get(); - // Set up VFF to pass |surface_texture_| via its InitCb. + // Set up VFF to pass |texture_owner_| via its InitCb. const bool want_promotion_hint = device_info_->IsSetOutputSurfaceSupported(); ON_CALL(*video_frame_factory_, Initialize(want_promotion_hint, _)) - .WillByDefault(RunCallback<1>(surface_texture)); + .WillByDefault(RunCallback<1>(texture_owner)); auto* observable_mcvd = new DestructionObservableMCVD( gpu_preferences_, device_info_.get(), codec_allocator_.get(), @@ -209,19 +208,19 @@ // Call Initialize() and Decode() to start lazy init. MCVD will be waiting for // a codec and have one decode pending. - void InitializeWithSurfaceTexture_OneDecodePending( + void InitializeWithTextureOwner_OneDecodePending( VideoDecoderConfig config = TestVideoConfig::Large(kCodecH264)) { Initialize(config); mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get()); provide_overlay_info_cb_.Run(OverlayInfo()); - surface_chooser_->ProvideSurfaceTexture(); + surface_chooser_->ProvideTextureOwner(); } // Fully initializes MCVD and returns the codec it's configured with. MCVD // will have one decode pending. MockMediaCodecBridge* InitializeFully_OneDecodePending( VideoDecoderConfig config = TestVideoConfig::Large(kCodecH264)) { - InitializeWithSurfaceTexture_OneDecodePending(config); + InitializeWithTextureOwner_OneDecodePending(config); return codec_allocator_->ProvideMockCodecAsync(); } @@ -243,7 +242,7 @@ std::unique_ptr<MockDeviceInfo> device_info_; std::unique_ptr<FakeCodecAllocator> codec_allocator_; MockAndroidVideoSurfaceChooser* surface_chooser_; - MockSurfaceTextureGLOwner* surface_texture_; + MockTextureOwner* texture_owner_; MockVideoFrameFactory* video_frame_factory_; NiceMock<base::MockCallback<VideoDecoder::DecodeCB>> decode_cb_; std::unique_ptr<DestructionObserver> destruction_observer_; @@ -326,7 +325,7 @@ } TEST_F(MediaCodecVideoDecoderTest, OverlayInfoDuringInitUpdatesSurfaceChooser) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); EXPECT_CALL(*surface_chooser_, MockUpdateState()); provide_overlay_info_cb_.Run(OverlayInfo()); } @@ -336,7 +335,7 @@ mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get()); provide_overlay_info_cb_.Run(OverlayInfo()); EXPECT_CALL(*codec_allocator_, MockCreateMediaCodecAsync(_, NotNull())); - surface_chooser_->ProvideSurfaceTexture(); + surface_chooser_->ProvideTextureOwner(); } TEST_F(MediaCodecVideoDecoderTest, FrameFactoryInitFailureIsAnError) { @@ -349,7 +348,7 @@ } TEST_F(MediaCodecVideoDecoderTest, CodecCreationFailureIsAnError) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get()); EXPECT_CALL(decode_cb_, Run(DecodeStatus::DECODE_ERROR)).Times(2); // Failing to create a codec should put MCVD into an error state. @@ -383,7 +382,7 @@ } TEST_F(MediaCodecVideoDecoderTest, SurfaceChooserIsUpdatedOnOverlayChanges) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); EXPECT_CALL(*surface_chooser_, MockReplaceOverlayFactory(_)).Times(2); OverlayInfo info; @@ -396,7 +395,7 @@ } TEST_F(MediaCodecVideoDecoderTest, OverlayInfoUpdatesAreIgnoredInStateError) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); // Enter the error state. codec_allocator_->ProvideNullCodecAsync(); @@ -407,7 +406,7 @@ } TEST_F(MediaCodecVideoDecoderTest, DuplicateOverlayInfoUpdatesAreIgnored) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); // The second overlay info update should be ignored. EXPECT_CALL(*surface_chooser_, MockReplaceOverlayFactory(_)).Times(1); @@ -481,7 +480,7 @@ auto* codec = codec_allocator_->ProvideMockCodecAsync(); // Set a pending surface transition and then call PumpCodec(). - surface_chooser_->ProvideSurfaceTexture(); + surface_chooser_->ProvideTextureOwner(); EXPECT_CALL(*codec, SetSurface(_)).WillOnce(Return(true)); PumpCodec(); } @@ -491,7 +490,7 @@ InitializeWithOverlay_OneDecodePending(); auto* codec = codec_allocator_->ProvideMockCodecAsync(); - surface_chooser_->ProvideSurfaceTexture(); + surface_chooser_->ProvideTextureOwner(); EXPECT_CALL(*codec, SetSurface(_)).WillOnce(Return(false)); EXPECT_CALL(decode_cb_, Run(DecodeStatus::DECODE_ERROR)).Times(2); EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(codec, NotNull(), _)); @@ -501,19 +500,19 @@ } TEST_F(MediaCodecVideoDecoderTest, SurfaceTransitionsCanBeCanceled) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); auto* codec = codec_allocator_->ProvideMockCodecAsync(); - // Set a pending transition to an overlay, and then back to a surface texture. + // Set a pending transition to an overlay, and then back to a texture owner. // They should cancel each other out and leave the codec as-is. EXPECT_CALL(*codec, SetSurface(_)).Times(0); auto overlay = std::make_unique<MockAndroidOverlay>(); auto observer = overlay->CreateDestructionObserver(); surface_chooser_->ProvideOverlay(std::move(overlay)); - // Switching back to surface texture should delete the pending overlay. + // Switching back to texture owner should delete the pending overlay. observer->ExpectDestruction(); - surface_chooser_->ProvideSurfaceTexture(); + surface_chooser_->ProvideTextureOwner(); observer.reset(); // Verify that Decode() does not transition the surface @@ -521,23 +520,23 @@ } TEST_F(MediaCodecVideoDecoderTest, TransitionToSameSurfaceIsIgnored) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); auto* codec = codec_allocator_->ProvideMockCodecAsync(); EXPECT_CALL(*codec, SetSurface(_)).Times(0); - surface_chooser_->ProvideSurfaceTexture(); + surface_chooser_->ProvideTextureOwner(); mcvd_->Decode(fake_decoder_buffer_, decode_cb_.Get()); } TEST_F(MediaCodecVideoDecoderTest, ResetBeforeCodecInitializedSucceedsImmediately) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); base::MockCallback<base::Closure> reset_cb; EXPECT_CALL(reset_cb, Run()); mcvd_->Reset(reset_cb.Get()); } TEST_F(MediaCodecVideoDecoderTest, ResetAbortsPendingDecodes) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); EXPECT_CALL(decode_cb_, Run(DecodeStatus::ABORTED)); mcvd_->Reset(base::DoNothing()); } @@ -680,7 +679,7 @@ } TEST_F(MediaCodecVideoDecoderTest, TeardownInvalidatesCodecCreationWeakPtr) { - InitializeWithSurfaceTexture_OneDecodePending(); + InitializeWithTextureOwner_OneDecodePending(); destruction_observer_->DoNotAllowDestruction(); mcvd_.reset(); // DeleteSoon() is now pending. Ensure it's safe if the codec creation
diff --git a/media/gpu/android/mock_android_video_surface_chooser.cc b/media/gpu/android/mock_android_video_surface_chooser.cc index 21641c8..35f701f 100644 --- a/media/gpu/android/mock_android_video_surface_chooser.cc +++ b/media/gpu/android/mock_android_video_surface_chooser.cc
@@ -11,10 +11,10 @@ void MockAndroidVideoSurfaceChooser::SetClientCallbacks( UseOverlayCB use_overlay_cb, - UseSurfaceTextureCB use_surface_texture_cb) { + UseTextureOwnerCB use_texture_owner_cb) { MockSetClientCallbacks(); use_overlay_cb_ = std::move(use_overlay_cb); - use_surface_texture_cb_ = std::move(use_surface_texture_cb); + use_texture_owner_cb_ = std::move(use_texture_owner_cb); } void MockAndroidVideoSurfaceChooser::UpdateState( @@ -28,8 +28,8 @@ current_state_ = new_state; } -void MockAndroidVideoSurfaceChooser::ProvideSurfaceTexture() { - use_surface_texture_cb_.Run(); +void MockAndroidVideoSurfaceChooser::ProvideTextureOwner() { + use_texture_owner_cb_.Run(); } void MockAndroidVideoSurfaceChooser::ProvideOverlay(
diff --git a/media/gpu/android/mock_android_video_surface_chooser.h b/media/gpu/android/mock_android_video_surface_chooser.h index 9f3fdc6..24a2322 100644 --- a/media/gpu/android/mock_android_video_surface_chooser.h +++ b/media/gpu/android/mock_android_video_surface_chooser.h
@@ -12,7 +12,7 @@ namespace media { // A mock surface chooser that lets tests choose the surface with -// ProvideOverlay() and ProvideSurfaceTexture(). +// ProvideOverlay() and ProvideTextureOwner(). class MockAndroidVideoSurfaceChooser : public AndroidVideoSurfaceChooser { public: MockAndroidVideoSurfaceChooser(); @@ -27,16 +27,16 @@ MOCK_METHOD1(MockReplaceOverlayFactory, void(bool)); void SetClientCallbacks(UseOverlayCB use_overlay_cb, - UseSurfaceTextureCB use_surface_texture_cb) override; + UseTextureOwnerCB use_texture_owner_cb) override; void UpdateState(base::Optional<AndroidOverlayFactoryCB> factory, const State& new_state) override; // Calls the corresponding callback to choose the surface. void ProvideOverlay(std::unique_ptr<AndroidOverlay> overlay); - void ProvideSurfaceTexture(); + void ProvideTextureOwner(); UseOverlayCB use_overlay_cb_; - UseSurfaceTextureCB use_surface_texture_cb_; + UseTextureOwnerCB use_texture_owner_cb_; AndroidOverlayFactoryCB factory_; State current_state_;
diff --git a/media/gpu/android/mock_surface_texture_gl_owner.cc b/media/gpu/android/mock_surface_texture_gl_owner.cc deleted file mode 100644 index 5411305..0000000 --- a/media/gpu/android/mock_surface_texture_gl_owner.cc +++ /dev/null
@@ -1,39 +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 "media/gpu/android/mock_surface_texture_gl_owner.h" - -namespace media { - -using testing::Invoke; -using testing::Return; - -MockSurfaceTextureGLOwner::MockSurfaceTextureGLOwner( - GLuint fake_texture_id, - gl::GLContext* fake_context, - gl::GLSurface* fake_surface) - : fake_texture_id(fake_texture_id), - fake_context(fake_context), - fake_surface(fake_surface), - expecting_frame_available(false) { - ON_CALL(*this, GetTextureId()).WillByDefault(Return(fake_texture_id)); - ON_CALL(*this, GetContext()).WillByDefault(Return(fake_context)); - ON_CALL(*this, GetSurface()).WillByDefault(Return(fake_surface)); - ON_CALL(*this, SetReleaseTimeToNow()) - .WillByDefault( - Invoke(this, &MockSurfaceTextureGLOwner::FakeSetReleaseTimeToNow)); - ON_CALL(*this, IgnorePendingRelease()) - .WillByDefault( - Invoke(this, &MockSurfaceTextureGLOwner::FakeIgnorePendingRelease)); - ON_CALL(*this, IsExpectingFrameAvailable()) - .WillByDefault(Invoke( - this, &MockSurfaceTextureGLOwner::FakeIsExpectingFrameAvailable)); - ON_CALL(*this, WaitForFrameAvailable()) - .WillByDefault( - Invoke(this, &MockSurfaceTextureGLOwner::FakeWaitForFrameAvailable)); -} - -MockSurfaceTextureGLOwner::~MockSurfaceTextureGLOwner() = default; - -} // namespace media
diff --git a/media/gpu/android/mock_texture_owner.cc b/media/gpu/android/mock_texture_owner.cc new file mode 100644 index 0000000..bd1368b --- /dev/null +++ b/media/gpu/android/mock_texture_owner.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 "media/gpu/android/mock_texture_owner.h" + +namespace media { + +using testing::Invoke; +using testing::Return; + +MockTextureOwner::MockTextureOwner(GLuint fake_texture_id, + gl::GLContext* fake_context, + gl::GLSurface* fake_surface) + : fake_texture_id(fake_texture_id), + fake_context(fake_context), + fake_surface(fake_surface), + expecting_frame_available(false) { + ON_CALL(*this, GetTextureId()).WillByDefault(Return(fake_texture_id)); + ON_CALL(*this, GetContext()).WillByDefault(Return(fake_context)); + ON_CALL(*this, GetSurface()).WillByDefault(Return(fake_surface)); + ON_CALL(*this, SetReleaseTimeToNow()) + .WillByDefault(Invoke(this, &MockTextureOwner::FakeSetReleaseTimeToNow)); + ON_CALL(*this, IgnorePendingRelease()) + .WillByDefault(Invoke(this, &MockTextureOwner::FakeIgnorePendingRelease)); + ON_CALL(*this, IsExpectingFrameAvailable()) + .WillByDefault( + Invoke(this, &MockTextureOwner::FakeIsExpectingFrameAvailable)); + ON_CALL(*this, WaitForFrameAvailable()) + .WillByDefault( + Invoke(this, &MockTextureOwner::FakeWaitForFrameAvailable)); +} + +MockTextureOwner::~MockTextureOwner() = default; + +} // namespace media
diff --git a/media/gpu/android/mock_surface_texture_gl_owner.h b/media/gpu/android/mock_texture_owner.h similarity index 75% rename from media/gpu/android/mock_surface_texture_gl_owner.h rename to media/gpu/android/mock_texture_owner.h index f43efe73..8f3d5e0 100644 --- a/media/gpu/android/mock_surface_texture_gl_owner.h +++ b/media/gpu/android/mock_texture_owner.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_GPU_ANDROID_MOCK_SURFACE_TEXTURE_GL_OWNER_H_ -#define MEDIA_GPU_ANDROID_MOCK_SURFACE_TEXTURE_GL_OWNER_H_ +#ifndef MEDIA_GPU_ANDROID_MOCK_TEXTURE_OWNER_H_ +#define MEDIA_GPU_ANDROID_MOCK_TEXTURE_OWNER_H_ -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_bindings.h" @@ -15,11 +15,11 @@ namespace media { // This is a mock with a small amount of fake functionality too. -class MockSurfaceTextureGLOwner : public SurfaceTextureGLOwner { +class MockTextureOwner : public TextureOwner { public: - MockSurfaceTextureGLOwner(GLuint fake_texture_id, - gl::GLContext* fake_context, - gl::GLSurface* fake_surface); + MockTextureOwner(GLuint fake_texture_id, + gl::GLContext* fake_context, + gl::GLSurface* fake_surface); MOCK_CONST_METHOD0(GetTextureId, GLuint()); MOCK_CONST_METHOD0(GetContext, gl::GLContext*()); @@ -45,9 +45,9 @@ bool expecting_frame_available; protected: - ~MockSurfaceTextureGLOwner(); + ~MockTextureOwner(); }; } // namespace media -#endif // MEDIA_GPU_ANDROID_MOCK_SURFACE_TEXTURE_GL_OWNER_H_ +#endif // MEDIA_GPU_ANDROID_MOCK_TEXTURE_OWNER_H_
diff --git a/media/gpu/android/surface_chooser_helper.cc b/media/gpu/android/surface_chooser_helper.cc index 1704289..d329090 100644 --- a/media/gpu/android/surface_chooser_helper.cc +++ b/media/gpu/android/surface_chooser_helper.cc
@@ -143,8 +143,8 @@ if (!is_using_overlay) { // Not an overlay. return surface_chooser_state_.is_secure - ? FrameInformation::SURFACETEXTURE_L3 - : FrameInformation::SURFACETEXTURE_INSECURE; + ? FrameInformation::NON_OVERLAY_L3 + : FrameInformation::NON_OVERLAY_INSECURE; } // Overlay.
diff --git a/media/gpu/android/surface_chooser_helper.h b/media/gpu/android/surface_chooser_helper.h index 2bfaddf9..907d077 100644 --- a/media/gpu/android/surface_chooser_helper.h +++ b/media/gpu/android/surface_chooser_helper.h
@@ -39,11 +39,11 @@ enum class SecureSurfaceMode { // The surface should not be secure. This allows both overlays and - // SurfaceTexture surfaces. + // TextureOwner surfaces. kInsecure, // It is preferable to have a secure surface, but insecure - // (SurfaceTexture) is better than failing. + // (TextureOwner) is better than failing. kRequested, // The surface must be a secure surface, and should fail otherwise. @@ -53,8 +53,8 @@ // Must match AVDAFrameInformation UMA enum. Please do not remove or re-order // values, only append new ones. enum class FrameInformation { - SURFACETEXTURE_INSECURE = 0, - SURFACETEXTURE_L3 = 1, + NON_OVERLAY_INSECURE = 0, + NON_OVERLAY_L3 = 1, OVERLAY_L3 = 2, OVERLAY_L1 = 3, OVERLAY_INSECURE_PLAYER_ELEMENT_FULLSCREEN = 4,
diff --git a/media/gpu/android/surface_chooser_helper_unittest.cc b/media/gpu/android/surface_chooser_helper_unittest.cc index e1d7c92..06b74db 100644 --- a/media/gpu/android/surface_chooser_helper_unittest.cc +++ b/media/gpu/android/surface_chooser_helper_unittest.cc
@@ -242,7 +242,7 @@ ASSERT_EQ(SurfaceChooserHelper::FrameInformation::OVERLAY_L3, helper_->ComputeFrameInformation(true)); - ASSERT_EQ(SurfaceChooserHelper::FrameInformation::SURFACETEXTURE_L3, + ASSERT_EQ(SurfaceChooserHelper::FrameInformation::NON_OVERLAY_L3, helper_->ComputeFrameInformation(false)); } @@ -251,8 +251,8 @@ helper_->SetSecureSurfaceMode( SurfaceChooserHelper::SecureSurfaceMode::kInsecure); - // Not using an overlay should be SURFACETEXTURE_INSECURE - ASSERT_EQ(SurfaceChooserHelper::FrameInformation::SURFACETEXTURE_INSECURE, + // Not using an overlay should be NON_OVERLAY_INSECURE + ASSERT_EQ(SurfaceChooserHelper::FrameInformation::NON_OVERLAY_INSECURE, helper_->ComputeFrameInformation(false)); // Fullscreen state should affect the result, so that we can tell the
diff --git a/media/gpu/android/surface_texture_gl_owner_unittest.cc b/media/gpu/android/surface_texture_gl_owner_unittest.cc index 1d395cb..a8898b9 100644 --- a/media/gpu/android/surface_texture_gl_owner_unittest.cc +++ b/media/gpu/android/surface_texture_gl_owner_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include <stdint.h> @@ -43,7 +43,7 @@ context_->Initialize(surface_.get(), gl::GLContextAttribs()); ASSERT_TRUE(context_->MakeCurrent(surface_.get())); - surface_texture_ = SurfaceTextureGLOwnerImpl::Create(); + surface_texture_ = SurfaceTextureGLOwner::Create(); texture_id_ = surface_texture_->GetTextureId(); // Bind and un-bind the texture, since that's required for glIsTexture to // return true. @@ -60,7 +60,7 @@ gl::init::ShutdownGL(false); } - scoped_refptr<SurfaceTextureGLOwner> surface_texture_; + scoped_refptr<TextureOwner> surface_texture_; GLuint texture_id_ = 0; scoped_refptr<gl::GLContext> context_;
diff --git a/media/gpu/android/surface_texture_gl_owner.cc b/media/gpu/android/texture_owner.cc similarity index 77% rename from media/gpu/android/surface_texture_gl_owner.cc rename to media/gpu/android/texture_owner.cc index f4b4d5b..7dd014b 100644 --- a/media/gpu/android/surface_texture_gl_owner.cc +++ b/media/gpu/android/texture_owner.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -30,14 +30,14 @@ ~FrameAvailableEvent() = default; }; -SurfaceTextureGLOwner::SurfaceTextureGLOwner() - : base::RefCountedDeleteOnSequence<SurfaceTextureGLOwner>( +TextureOwner::TextureOwner() + : base::RefCountedDeleteOnSequence<TextureOwner>( base::ThreadTaskRunnerHandle::Get()), task_runner_(base::ThreadTaskRunnerHandle::Get()) {} -SurfaceTextureGLOwner::~SurfaceTextureGLOwner() = default; +TextureOwner::~TextureOwner() = default; -scoped_refptr<SurfaceTextureGLOwner> SurfaceTextureGLOwnerImpl::Create() { +scoped_refptr<TextureOwner> SurfaceTextureGLOwner::Create() { GLuint texture_id; glGenTextures(1, &texture_id); if (!texture_id) @@ -52,10 +52,10 @@ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); - return new SurfaceTextureGLOwnerImpl(texture_id); + return new SurfaceTextureGLOwner(texture_id); } -SurfaceTextureGLOwnerImpl::SurfaceTextureGLOwnerImpl(GLuint texture_id) +SurfaceTextureGLOwner::SurfaceTextureGLOwner(GLuint texture_id) : surface_texture_(gl::SurfaceTexture::Create(texture_id)), texture_id_(texture_id), context_(gl::GLContext::GetCurrent()), @@ -63,11 +63,11 @@ frame_available_event_(new FrameAvailableEvent()) { DCHECK(context_); DCHECK(surface_); - surface_texture_->SetFrameAvailableCallbackOnAnyThread( - base::Bind(&FrameAvailableEvent::Signal, frame_available_event_)); + surface_texture_->SetFrameAvailableCallbackOnAnyThread(base::BindRepeating( + &FrameAvailableEvent::Signal, frame_available_event_)); } -SurfaceTextureGLOwnerImpl::~SurfaceTextureGLOwnerImpl() { +SurfaceTextureGLOwner::~SurfaceTextureGLOwner() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Make sure that the SurfaceTexture isn't using the GL objects. @@ -80,56 +80,56 @@ } } -GLuint SurfaceTextureGLOwnerImpl::GetTextureId() const { +GLuint SurfaceTextureGLOwner::GetTextureId() const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return texture_id_; } -gl::ScopedJavaSurface SurfaceTextureGLOwnerImpl::CreateJavaSurface() const { +gl::ScopedJavaSurface SurfaceTextureGLOwner::CreateJavaSurface() const { return gl::ScopedJavaSurface(surface_texture_.get()); } -void SurfaceTextureGLOwnerImpl::UpdateTexImage() { +void SurfaceTextureGLOwner::UpdateTexImage() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); surface_texture_->UpdateTexImage(); } -void SurfaceTextureGLOwnerImpl::GetTransformMatrix(float mtx[]) { +void SurfaceTextureGLOwner::GetTransformMatrix(float mtx[]) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); surface_texture_->GetTransformMatrix(mtx); } -void SurfaceTextureGLOwnerImpl::ReleaseBackBuffers() { +void SurfaceTextureGLOwner::ReleaseBackBuffers() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); surface_texture_->ReleaseBackBuffers(); } -gl::GLContext* SurfaceTextureGLOwnerImpl::GetContext() const { +gl::GLContext* SurfaceTextureGLOwner::GetContext() const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return context_.get(); } -gl::GLSurface* SurfaceTextureGLOwnerImpl::GetSurface() const { +gl::GLSurface* SurfaceTextureGLOwner::GetSurface() const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return surface_.get(); } -void SurfaceTextureGLOwnerImpl::SetReleaseTimeToNow() { +void SurfaceTextureGLOwner::SetReleaseTimeToNow() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); release_time_ = base::TimeTicks::Now(); } -void SurfaceTextureGLOwnerImpl::IgnorePendingRelease() { +void SurfaceTextureGLOwner::IgnorePendingRelease() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); release_time_ = base::TimeTicks(); } -bool SurfaceTextureGLOwnerImpl::IsExpectingFrameAvailable() { +bool SurfaceTextureGLOwner::IsExpectingFrameAvailable() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return !release_time_.is_null(); } -void SurfaceTextureGLOwnerImpl::WaitForFrameAvailable() { +void SurfaceTextureGLOwner::WaitForFrameAvailable() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!release_time_.is_null());
diff --git a/media/gpu/android/surface_texture_gl_owner.h b/media/gpu/android/texture_owner.h similarity index 79% rename from media/gpu/android/surface_texture_gl_owner.h rename to media/gpu/android/texture_owner.h index 904dc34..f07ca23 100644 --- a/media/gpu/android/surface_texture_gl_owner.h +++ b/media/gpu/android/texture_owner.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 MEDIA_GPU_ANDROID_SURFACE_TEXTURE_GL_OWNER_H_ -#define MEDIA_GPU_ANDROID_SURFACE_TEXTURE_GL_OWNER_H_ +#ifndef MEDIA_GPU_ANDROID_TEXTURE_OWNER_H_ +#define MEDIA_GPU_ANDROID_TEXTURE_OWNER_H_ #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_delete_on_sequence.h" @@ -29,22 +29,22 @@ // exception of CreateJavaSurface(), which can be called on any thread. // It's safe to keep and drop refptrs to it on any thread; it will be // automatically destructed on the thread it was constructed on. -// Virtual for testing; see SurfaceTextureGLOwnerImpl. -class MEDIA_GPU_EXPORT SurfaceTextureGLOwner - : public base::RefCountedDeleteOnSequence<SurfaceTextureGLOwner> { +// Virtual for testing; see SurfaceTextureGLOwner. +class MEDIA_GPU_EXPORT TextureOwner + : public base::RefCountedDeleteOnSequence<TextureOwner> { public: - SurfaceTextureGLOwner(); + TextureOwner(); scoped_refptr<base::SingleThreadTaskRunner> task_runner() { return task_runner_; } - // Returns the GL texture id that the SurfaceTexture is attached to. + // Returns the GL texture id that the TextureOwner is attached to. virtual GLuint GetTextureId() const = 0; virtual gl::GLContext* GetContext() const = 0; virtual gl::GLSurface* GetSurface() const = 0; - // Create a java surface for the SurfaceTexture. + // Create a java surface for the TextureOwner. virtual gl::ScopedJavaSurface CreateJavaSurface() const = 0; // See gl::SurfaceTexture for the following. @@ -73,22 +73,21 @@ virtual void WaitForFrameAvailable() = 0; protected: - friend class base::RefCountedDeleteOnSequence<SurfaceTextureGLOwner>; - friend class base::DeleteHelper<SurfaceTextureGLOwner>; - virtual ~SurfaceTextureGLOwner(); + friend class base::RefCountedDeleteOnSequence<TextureOwner>; + friend class base::DeleteHelper<TextureOwner>; + virtual ~TextureOwner(); private: scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - DISALLOW_COPY_AND_ASSIGN(SurfaceTextureGLOwner); + DISALLOW_COPY_AND_ASSIGN(TextureOwner); }; -class MEDIA_GPU_EXPORT SurfaceTextureGLOwnerImpl - : public SurfaceTextureGLOwner { +class MEDIA_GPU_EXPORT SurfaceTextureGLOwner : public TextureOwner { public: // Creates a GL texture using the current platform GL context and returns a - // new SurfaceTextureGLOwnerImpl attached to it. Returns null on failure. - static scoped_refptr<SurfaceTextureGLOwner> Create(); + // new SurfaceTextureGLOwner attached to it. Returns null on failure. + static scoped_refptr<TextureOwner> Create(); GLuint GetTextureId() const override; gl::GLContext* GetContext() const override; @@ -103,8 +102,8 @@ void WaitForFrameAvailable() override; private: - SurfaceTextureGLOwnerImpl(GLuint texture_id); - ~SurfaceTextureGLOwnerImpl() override; + SurfaceTextureGLOwner(GLuint texture_id); + ~SurfaceTextureGLOwner() override; scoped_refptr<gl::SurfaceTexture> surface_texture_; GLuint texture_id_; @@ -121,9 +120,9 @@ THREAD_CHECKER(thread_checker_); - DISALLOW_COPY_AND_ASSIGN(SurfaceTextureGLOwnerImpl); + DISALLOW_COPY_AND_ASSIGN(SurfaceTextureGLOwner); }; } // namespace media -#endif // MEDIA_GPU_ANDROID_SURFACE_TEXTURE_GL_OWNER_H_ +#endif // MEDIA_GPU_ANDROID_TEXTURE_OWNER_H_
diff --git a/media/gpu/android/video_frame_factory.h b/media/gpu/android/video_frame_factory.h index ee65a1d..f4507e8d 100644 --- a/media/gpu/android/video_frame_factory.h +++ b/media/gpu/android/video_frame_factory.h
@@ -23,7 +23,7 @@ struct AVDASurfaceBundle; class CodecOutputBuffer; -class SurfaceTextureGLOwner; +class TextureOwner; class VideoFrame; // VideoFrameFactory creates CodecOutputBuffer backed VideoFrames. Not thread @@ -31,13 +31,13 @@ class MEDIA_GPU_EXPORT VideoFrameFactory { public: using GetStubCb = base::Callback<gpu::CommandBufferStub*()>; - using InitCb = base::Callback<void(scoped_refptr<SurfaceTextureGLOwner>)>; + using InitCb = base::RepeatingCallback<void(scoped_refptr<TextureOwner>)>; VideoFrameFactory() = default; virtual ~VideoFrameFactory() = default; // Initializes the factory and runs |init_cb| on the current thread when it's - // complete. If initialization fails, the returned surface texture will be + // complete. If initialization fails, the returned texture owner will be // null. |wants_promotion_hint| tells us whether to mark VideoFrames for // compositor overlay promotion hints or not. virtual void Initialize(bool wants_promotion_hint, InitCb init_cb) = 0; @@ -47,8 +47,8 @@ virtual void SetSurfaceBundle( scoped_refptr<AVDASurfaceBundle> surface_bundle) = 0; - // Creates a new VideoFrame backed by |output_buffer| and |surface_texture|. - // |surface_texture| may be null if the buffer is backed by an overlay + // Creates a new VideoFrame backed by |output_buffer| and |texture_owner|. + // |texture_owner| may be null if the buffer is backed by an overlay // instead. Runs |output_cb| on the calling sequence to return the frame. // TODO(liberato): update the comment. virtual void CreateVideoFrame(
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc index 2bf885f..683aa89 100644 --- a/media/gpu/android/video_frame_factory_impl.cc +++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -67,11 +67,11 @@ scoped_refptr<CodecImageGroup> image_group; if (!surface_bundle) { // Clear everything, just so we're not holding a reference. - surface_texture_ = nullptr; + texture_owner_ = nullptr; } else { - // If |surface_bundle| is using a SurfaceTexture, then get it. - surface_texture_ = - surface_bundle->overlay ? nullptr : surface_bundle->surface_texture; + // If |surface_bundle| is using a TextureOwner, then get it. + texture_owner_ = + surface_bundle->overlay ? nullptr : surface_bundle->texture_owner_; // Start a new image group. Note that there's no reason that we can't have // more than one group per surface bundle; it's okay if we're called @@ -103,7 +103,7 @@ FROM_HERE, base::Bind(&GpuVideoFrameFactory::CreateVideoFrame, base::Unretained(gpu_video_frame_factory_.get()), - base::Passed(&output_buffer), surface_texture_, timestamp, + base::Passed(&output_buffer), texture_owner_, timestamp, natural_size, std::move(promotion_hint_cb), std::move(output_cb), base::ThreadTaskRunnerHandle::Get())); } @@ -126,7 +126,7 @@ stub_->RemoveDestructionObserver(this); } -scoped_refptr<SurfaceTextureGLOwner> GpuVideoFrameFactory::Initialize( +scoped_refptr<TextureOwner> GpuVideoFrameFactory::Initialize( bool wants_promotion_hint, VideoFrameFactoryImpl::GetStubCb get_stub_cb) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -140,12 +140,12 @@ new TexturePool(std::make_unique<CommandBufferStubWrapperImpl>(stub_)); decoder_helper_ = GLES2DecoderHelper::Create(stub_->decoder_context()); - return SurfaceTextureGLOwnerImpl::Create(); + return SurfaceTextureGLOwner::Create(); } void GpuVideoFrameFactory::CreateVideoFrame( std::unique_ptr<CodecOutputBuffer> output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner_, base::TimeDelta timestamp, gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, @@ -154,7 +154,7 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); scoped_refptr<VideoFrame> frame; scoped_refptr<gpu::gles2::TextureRef> texture_ref; - CreateVideoFrameInternal(std::move(output_buffer), std::move(surface_texture), + CreateVideoFrameInternal(std::move(output_buffer), std::move(texture_owner_), timestamp, natural_size, std::move(promotion_hint_cb), &frame, &texture_ref); if (!frame || !texture_ref) @@ -183,7 +183,7 @@ void GpuVideoFrameFactory::CreateVideoFrameInternal( std::unique_ptr<CodecOutputBuffer> output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner_, base::TimeDelta timestamp, gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, @@ -219,27 +219,27 @@ size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE); auto image = base::MakeRefCounted<CodecImage>( - std::move(output_buffer), surface_texture, std::move(promotion_hint_cb)); + std::move(output_buffer), texture_owner_, std::move(promotion_hint_cb)); images_.push_back(image.get()); // Add |image| to our current image group. This makes suer that any overlay - // lasts as long as the images. For SurfaceTexture, it doesn't do much. + // lasts as long as the images. For TextureOwner, it doesn't do much. image_group_->AddCodecImage(image.get()); // Attach the image to the texture. - // If we're attaching a SurfaceTexture backed image, we set the state to + // If we're attaching a TextureOwner backed image, we set the state to // UNBOUND. This ensures that the implementation will call CopyTexImage() - // which lets us update the surface texture at the right time. + // which lets us update the texture owner at the right time. // For overlays we set the state to BOUND because it's required for // ScheduleOverlayPlane() to be called. If something tries to sample from an // overlay texture it won't work, but there's no way to make that work. - auto image_state = surface_texture ? gpu::gles2::Texture::UNBOUND - : gpu::gles2::Texture::BOUND; - GLuint surface_texture_service_id = - surface_texture ? surface_texture->GetTextureId() : 0; + auto image_state = texture_owner_ ? gpu::gles2::Texture::UNBOUND + : gpu::gles2::Texture::BOUND; + GLuint texture_owner_service_id = + texture_owner_ ? texture_owner_->GetTextureId() : 0; texture_manager->SetLevelStreamTextureImage( texture_ref.get(), GL_TEXTURE_EXTERNAL_OES, 0, image.get(), image_state, - surface_texture_service_id); + texture_owner_service_id); texture_manager->SetLevelCleared(texture_ref.get(), GL_TEXTURE_EXTERNAL_OES, 0, true); @@ -258,16 +258,16 @@ frame->metadata()->SetBoolean(VideoFrameMetadata::COPY_REQUIRED, true); // We unconditionally mark the picture as overlayable, even if - // |!surface_texture|, if we want to get hints. It's required, else we won't + // |!texture_owner_|, if we want to get hints. It's required, else we won't // get hints. - const bool allow_overlay = !surface_texture || wants_promotion_hint_; + const bool allow_overlay = !texture_owner_ || wants_promotion_hint_; frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, allow_overlay); frame->metadata()->SetBoolean(VideoFrameMetadata::WANTS_PROMOTION_HINT, wants_promotion_hint_); - frame->metadata()->SetBoolean(VideoFrameMetadata::SURFACE_TEXTURE, - !!surface_texture); + frame->metadata()->SetBoolean(VideoFrameMetadata::TEXTURE_OWNER, + !!texture_owner_); *video_frame_out = std::move(frame); *texture_ref_out = std::move(texture_ref);
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h index 56592129..b8b7621 100644 --- a/media/gpu/android/video_frame_factory_impl.h +++ b/media/gpu/android/video_frame_factory_impl.h
@@ -13,7 +13,7 @@ #include "media/base/video_frame.h" #include "media/gpu/android/codec_image.h" #include "media/gpu/android/codec_wrapper.h" -#include "media/gpu/android/surface_texture_gl_owner.h" +#include "media/gpu/android/texture_owner.h" #include "media/gpu/android/video_frame_factory.h" #include "media/gpu/gles2_decoder_helper.h" #include "media/gpu/media_gpu_export.h" @@ -54,8 +54,8 @@ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; GetStubCb get_stub_cb_; - // The surface texture that video frames should use, or nullptr. - scoped_refptr<SurfaceTextureGLOwner> surface_texture_; + // The texture owner that video frames should use, or nullptr. + scoped_refptr<TextureOwner> texture_owner_; SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryImpl); @@ -69,14 +69,14 @@ GpuVideoFrameFactory(); ~GpuVideoFrameFactory() override; - scoped_refptr<SurfaceTextureGLOwner> Initialize( + scoped_refptr<TextureOwner> Initialize( bool wants_promotion_hint, VideoFrameFactory::GetStubCb get_stub_cb); // Creates and returns a VideoFrame with its ReleaseMailboxCB. void CreateVideoFrame( std::unique_ptr<CodecOutputBuffer> output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner, base::TimeDelta timestamp, gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, @@ -91,7 +91,7 @@ // Creates a TextureRef and VideoFrame. void CreateVideoFrameInternal( std::unique_ptr<CodecOutputBuffer> output_buffer, - scoped_refptr<SurfaceTextureGLOwner> surface_texture, + scoped_refptr<TextureOwner> texture_owner, base::TimeDelta timestamp, gfx::Size natural_size, PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb, @@ -167,8 +167,8 @@ // Try to render the image following the front buffer to the back buffer. size_t back_buffer_index = *front_buffer_index + 1; if (back_buffer_index < images.size() && - images[back_buffer_index]->is_surface_texture_backed()) { - images[back_buffer_index]->RenderToSurfaceTextureBackBuffer(); + images[back_buffer_index]->is_texture_owner_backed()) { + images[back_buffer_index]->RenderToTextureOwnerBackBuffer(); } }
diff --git a/media/gpu/android/video_frame_factory_impl_unittest.cc b/media/gpu/android/video_frame_factory_impl_unittest.cc index 9125ae4..11fb25a3 100644 --- a/media/gpu/android/video_frame_factory_impl_unittest.cc +++ b/media/gpu/android/video_frame_factory_impl_unittest.cc
@@ -13,15 +13,15 @@ using testing::Return; // The dimensions for specifying MockImage behavior. -enum ImageKind { kSurfaceTexture, kOverlay }; +enum ImageKind { kTextureOwner, kOverlay }; enum Phase { kInCodec, kInFrontBuffer, kInvalidated }; enum Expectation { kRenderToFrontBuffer, kRenderToBackBuffer, kNone }; // A mock image with the same interface as CodecImage. struct MockImage { MockImage(ImageKind kind, Phase phase, Expectation expectation) { - ON_CALL(*this, is_surface_texture_backed()) - .WillByDefault(Return(kind == kSurfaceTexture)); + ON_CALL(*this, is_texture_owner_backed()) + .WillByDefault(Return(kind == kTextureOwner)); ON_CALL(*this, was_rendered_to_front_buffer()) .WillByDefault(Return(phase == kInFrontBuffer)); @@ -34,17 +34,17 @@ } if (expectation == kRenderToBackBuffer) { - EXPECT_CALL(*this, RenderToSurfaceTextureBackBuffer()) + EXPECT_CALL(*this, RenderToTextureOwnerBackBuffer()) .WillOnce(Return(phase != kInvalidated)); } else { - EXPECT_CALL(*this, RenderToSurfaceTextureBackBuffer()).Times(0); + EXPECT_CALL(*this, RenderToTextureOwnerBackBuffer()).Times(0); } } MOCK_METHOD0(was_rendered_to_front_buffer, bool()); - MOCK_METHOD0(is_surface_texture_backed, bool()); + MOCK_METHOD0(is_texture_owner_backed, bool()); MOCK_METHOD0(RenderToFrontBuffer, bool()); - MOCK_METHOD0(RenderToSurfaceTextureBackBuffer, bool()); + MOCK_METHOD0(RenderToTextureOwnerBackBuffer, bool()); }; class MaybeRenderEarlyTest : public testing::Test { @@ -67,7 +67,7 @@ } TEST_F(MaybeRenderEarlyTest, SingleUnrenderedSTImageIsRendered) { - AddImage(kSurfaceTexture, kInCodec, Expectation::kRenderToFrontBuffer); + AddImage(kTextureOwner, kInCodec, Expectation::kRenderToFrontBuffer); internal::MaybeRenderEarly(&images_); } @@ -77,9 +77,9 @@ } TEST_F(MaybeRenderEarlyTest, InvalidatedImagesAreSkippedOver) { - AddImage(kSurfaceTexture, kInvalidated, Expectation::kRenderToFrontBuffer); - AddImage(kSurfaceTexture, kInvalidated, Expectation::kRenderToFrontBuffer); - AddImage(kSurfaceTexture, kInCodec, Expectation::kRenderToFrontBuffer); + AddImage(kTextureOwner, kInvalidated, Expectation::kRenderToFrontBuffer); + AddImage(kTextureOwner, kInvalidated, Expectation::kRenderToFrontBuffer); + AddImage(kTextureOwner, kInCodec, Expectation::kRenderToFrontBuffer); internal::MaybeRenderEarly(&images_); } @@ -92,10 +92,10 @@ TEST_F(MaybeRenderEarlyTest, ImageFollowingLatestFrontBufferIsBackBufferRendered) { - AddImage(kSurfaceTexture, kInCodec, Expectation::kNone); - AddImage(kSurfaceTexture, kInFrontBuffer, Expectation::kNone); - AddImage(kSurfaceTexture, kInCodec, Expectation::kRenderToBackBuffer); - AddImage(kSurfaceTexture, kInCodec, Expectation::kNone); + AddImage(kTextureOwner, kInCodec, Expectation::kNone); + AddImage(kTextureOwner, kInFrontBuffer, Expectation::kNone); + AddImage(kTextureOwner, kInCodec, Expectation::kRenderToBackBuffer); + AddImage(kTextureOwner, kInCodec, Expectation::kNone); internal::MaybeRenderEarly(&images_); }
diff --git a/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc b/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc index 2132f03..c8de1270 100644 --- a/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc +++ b/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc
@@ -263,7 +263,7 @@ params.visible_rect, params.color_space, params.allow_overlay); picture.set_size_changed(params.size_changed); - picture.set_surface_texture(params.surface_texture); + picture.set_texture_owner(params.surface_texture); picture.set_wants_promotion_hint(params.wants_promotion_hint); client_->PictureReady(picture); }
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc index 33c4c89..126d1046 100644 --- a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc +++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -268,7 +268,7 @@ params.color_space = picture.color_space(); params.allow_overlay = picture.allow_overlay(); params.size_changed = picture.size_changed(); - params.surface_texture = picture.surface_texture(); + params.surface_texture = picture.texture_owner(); params.wants_promotion_hint = picture.wants_promotion_hint(); if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(host_route_id_, params))) {
diff --git a/media/gpu/ipc/service/picture_buffer_manager.cc b/media/gpu/ipc/service/picture_buffer_manager.cc index 2ecdb51c..06d743df 100644 --- a/media/gpu/ipc/service/picture_buffer_manager.cc +++ b/media/gpu/ipc/service/picture_buffer_manager.cc
@@ -167,7 +167,7 @@ gfx::Size natural_size) override { DVLOG(2) << __func__ << "(" << picture.picture_buffer_id() << ")"; DCHECK(!picture.size_changed()); - DCHECK(!picture.surface_texture()); + DCHECK(!picture.texture_owner()); DCHECK(!picture.wants_promotion_hint()); base::AutoLock lock(picture_buffers_lock_);
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc index bfad3c2..672a225 100644 --- a/media/gpu/video_decode_accelerator_unittest.cc +++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -122,11 +122,10 @@ // the specified number of times. In different test cases, we have different // values for |num_play_throughs|. This setting will override the value. A // special value "0" means no override. -int g_num_play_throughs = 0; +size_t g_num_play_throughs = 0; -// TODO(hiroh): Change this type to bool // Fake decode -int g_fake_decoder = 0; +bool g_fake_decoder = 0; // Test buffer import into VDA, providing buffers allocated by us, instead of // requesting the VDA itself to allocate buffers. @@ -143,15 +142,15 @@ // Environment to store rendering thread. media::test::VideoDecodeAcceleratorTestEnvironment* g_env; -const int kMaxResetAfterFrameNum = 100; -const int kMaxFramesToDelayReuse = 64; +constexpr size_t kMaxResetAfterFrameNum = 100; +constexpr size_t kMaxFramesToDelayReuse = 64; const base::TimeDelta kReuseDelay = base::TimeDelta::FromSeconds(1); // Simulate WebRTC and call VDA::Decode 30 times per second. -const int kWebRtcDecodeCallsPerSecond = 30; +constexpr size_t kWebRtcDecodeCallsPerSecond = 30; // Simulate an adjustment to a larger number of pictures to make sure the // decoder supports an upwards adjustment. -const int kExtraPictureBuffers = 2; -const int kNoMidStreamReset = -1; +constexpr size_t kExtraPictureBuffers = 2; +constexpr size_t kNoMidStreamReset = std::numeric_limits<size_t>::max(); const gfx::Size kThumbnailsPageSize(1600, 1200); const gfx::Size kThumbnailSize(160, 120); @@ -159,7 +158,7 @@ // We assert a minimal number of concurrent decoders we expect to succeed. // Different platforms can support more concurrent decoders, so we don't assert // failure above this. -const size_t kMinSupportedNumConcurrentDecoders = 3; +constexpr size_t kMinSupportedNumConcurrentDecoders = 3; // Magic constants for differentiating the reasons for NotifyResetDone being // called. @@ -197,24 +196,24 @@ struct TestVideoFile { explicit TestVideoFile(base::FilePath::StringType file_name) : file_name(file_name), - width(-1), - height(-1), - num_frames(-1), - num_fragments(-1), - min_fps_render(-1), - min_fps_no_render(-1), + width(0), + height(0), + num_frames(0), + num_fragments(0), + min_fps_render(0), + min_fps_no_render(0), profile(VIDEO_CODEC_PROFILE_UNKNOWN), - reset_after_frame_num(-1) {} + reset_after_frame_num(std::numeric_limits<size_t>::max()) {} base::FilePath::StringType file_name; int width; int height; - int num_frames; - int num_fragments; - int min_fps_render; - int min_fps_no_render; + size_t num_frames; + size_t num_fragments; + double min_fps_render; + double min_fps_no_render; VideoCodecProfile profile; - int reset_after_frame_num; + size_t reset_after_frame_num; std::string data_str; }; @@ -237,7 +236,6 @@ : public VideoDecodeAccelerator::Client, public base::SupportsWeakPtr<GLRenderingVDAClient> { public: - // TODO(hiroh): Change some int type variables to size_t or uint32/64_t. // |window_id| the window_id of the client, which is used to identify the // rendering area in the |rendering_helper_|. // |num_in_flight_decodes| is the number of concurrent in-flight Decode() @@ -264,16 +262,19 @@ // as thumbnails at the end of tests. struct Config { size_t window_id = 0; - int num_in_flight_decodes = 1; - int num_play_throughs = 1; + size_t num_in_flight_decodes = 1; + size_t num_play_throughs = 1; ResetPoint reset_point = END_OF_STREAM_RESET; - int reset_after_frame_num = kNoMidStreamReset; + size_t reset_after_frame_num = kNoMidStreamReset; + // TODO(hiroh): Refactor as delete_decoder_state can be enum class. + // This can be set to not only ClientState, but also an integer in + // TearDownTiming test case. int delete_decoder_state = CS_RESET; gfx::Size frame_size; VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; - int fake_decoder = 0; - int delay_reuse_after_frame_num = std::numeric_limits<int>::max(); - int decode_calls_per_second = 0; + bool fake_decoder = false; + size_t delay_reuse_after_frame_num = std::numeric_limits<size_t>::max(); + size_t decode_calls_per_second = 0; bool render_as_thumbnails = false; }; @@ -304,12 +305,12 @@ void OutputFrameDeliveryTimes(base::File* output); // Simple getters for inspecting the state of the Client. - int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } - int num_skipped_fragments() { + size_t num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } + size_t num_skipped_fragments() { return encoded_data_helper_->num_skipped_fragments(); } - int num_queued_fragments() { return num_queued_fragments_; } - int num_decoded_frames() { return num_decoded_frames_; } + size_t num_queued_fragments() { return num_queued_fragments_; } + size_t num_decoded_frames() { return num_decoded_frames_; } double frames_per_second(); // Return the median of the decode time of all decoded frames. base::TimeDelta decode_time_median(); @@ -334,7 +335,7 @@ const Config config_; RenderingHelper* const rendering_helper_; gfx::Size frame_size_; - int outstanding_decodes_; + size_t outstanding_decodes_; int next_bitstream_buffer_id_; ClientStateNotification<ClientState>* const note_; std::unique_ptr<VideoDecodeAccelerator> decoder_; @@ -342,12 +343,12 @@ std::unique_ptr<base::WeakPtrFactory<VideoDecodeAccelerator>> weak_vda_ptr_factory_; std::unique_ptr<GpuVideoDecodeAcceleratorFactory> vda_factory_; - int remaining_play_throughs_; + size_t remaining_play_throughs_; ResetPoint reset_point_; ClientState state_; - int num_queued_fragments_; - int num_decoded_frames_; - int num_done_bitstream_buffers_; + size_t num_queued_fragments_; + size_t num_decoded_frames_; + size_t num_done_bitstream_buffers_; base::TimeTicks initialize_done_ticks_; GLenum texture_target_; VideoPixelFormat pixel_format_; @@ -418,9 +419,9 @@ LOG_ASSERT(1 == config_.num_in_flight_decodes); weak_this_ = weak_this_factory_.GetWeakPtr(); if (config_.reset_point == MID_STREAM_RESET) { - EXPECT_GE(config_.reset_after_frame_num, 0) - << "reset_ater_frame_num_ must be >=0 " - << "when reset_point == MID_STREAM_RESET"; + EXPECT_NE(config_.reset_after_frame_num, kNoMidStreamReset) + << "reset_ater_frame_num_ must not be kNoMidStreamReset " + << "when reset_point = MID_STREAM_RESET"; } else { EXPECT_EQ(config_.reset_after_frame_num, kNoMidStreamReset); } @@ -490,7 +491,7 @@ LOG_ASSERT(textures_per_buffer == 1u); std::vector<PictureBuffer> buffers; - requested_num_of_buffers += kExtraPictureBuffers; + requested_num_of_buffers += static_cast<uint32_t>(kExtraPictureBuffers); if (pixel_format == PIXEL_FORMAT_UNKNOWN) pixel_format = PIXEL_FORMAT_ARGB; @@ -626,8 +627,8 @@ } void GLRenderingVDAClient::ResetDecoderAfterFlush() { + DCHECK_GE(remaining_play_throughs_, 1u); --remaining_play_throughs_; - DCHECK_GE(remaining_play_throughs_, 0); // SetState(CS_RESETTING) should be called before decoder_->Reset(), because // VDA can call NotifyFlushDone() from Reset(). // TODO(johnylin): call SetState() before all decoder Flush() and Reset(). @@ -648,6 +649,7 @@ // forward progress during a Reset(). But the VDA::Reset() API doesn't // guarantee this, so stop relying on it (and remove the notifications from // VaapiVideoDecodeAccelerator::FinishReset()). + LOG_ASSERT(outstanding_decodes_ != 0); ++num_done_bitstream_buffers_; --outstanding_decodes_; @@ -694,7 +696,7 @@ return; case START_OF_STREAM_RESET: reset_point_ = END_OF_STREAM_RESET; - for (int i = 0; i < config_.num_in_flight_decodes; ++i) + for (size_t i = 0; i < config_.num_in_flight_decodes; ++i) DecodeNextFragment(); return; case END_OF_STREAM_RESET: @@ -754,7 +756,7 @@ return; } - for (int i = 0; i < config_.num_in_flight_decodes; ++i) + for (size_t i = 0; i < config_.num_in_flight_decodes; ++i) DecodeNextFragment(); DCHECK_EQ(outstanding_decodes_, config_.num_in_flight_decodes); } @@ -842,7 +844,7 @@ if (decode_time_.size() == 0) return base::TimeDelta(); std::sort(decode_time_.begin(), decode_time_.end()); - int index = decode_time_.size() / 2; + size_t index = decode_time_.size() / 2; if (decode_time_.size() % 2 != 0) return decode_time_[index]; @@ -867,7 +869,7 @@ // |num_concurrent_decoders| and |reset_point|. Ex: the expected number of // frames should be adjusted if decoder is reset in the middle of the stream. void UpdateTestVideoFileParams(size_t num_concurrent_decoders, - int reset_point, + ResetPoint reset_point, TestFilesVector* test_video_files); void InitializeRenderingHelper(const RenderingHelperParams& helper_params); @@ -952,13 +954,17 @@ if (!fields[2].empty()) LOG_ASSERT(base::StringToInt(fields[2], &video_file->height)); if (!fields[3].empty()) - LOG_ASSERT(base::StringToInt(fields[3], &video_file->num_frames)); + LOG_ASSERT(base::StringToSizeT(fields[3], &video_file->num_frames)); if (!fields[4].empty()) - LOG_ASSERT(base::StringToInt(fields[4], &video_file->num_fragments)); - if (!fields[5].empty()) - LOG_ASSERT(base::StringToInt(fields[5], &video_file->min_fps_render)); - if (!fields[6].empty()) - LOG_ASSERT(base::StringToInt(fields[6], &video_file->min_fps_no_render)); + LOG_ASSERT(base::StringToSizeT(fields[4], &video_file->num_fragments)); + if (!fields[5].empty()) { + std::string field(fields[5].begin(), fields[5].end()); + LOG_ASSERT(base::StringToDouble(field, &video_file->min_fps_render)); + } + if (!fields[6].empty()) { + std::string field(fields[5].begin(), fields[5].end()); + LOG_ASSERT(base::StringToDouble(field, &video_file->min_fps_no_render)); + } // Default to H264 baseline if no profile provided. int profile = static_cast<int>(H264PROFILE_BASELINE); if (!fields[7].empty()) @@ -977,7 +983,7 @@ void VideoDecodeAcceleratorTest::UpdateTestVideoFileParams( size_t num_concurrent_decoders, - int reset_point, + ResetPoint reset_point, TestFilesVector* test_video_files) { for (size_t i = 0; i < test_video_files->size(); i++) { TestVideoFile* video_file = (*test_video_files)[i].get(); @@ -1060,9 +1066,13 @@ // - whether the video frames are rendered as thumbnails. class VideoDecodeAcceleratorParamTest : public VideoDecodeAcceleratorTest, - public ::testing::WithParamInterface< - std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> { -}; + public ::testing::WithParamInterface<std::tuple<size_t, + size_t, + size_t, + ResetPoint, + ClientState, + bool, + bool>> {}; // Wait for |note| to report a state and if it's not |expected_state| then // assert |client| has deleted its decoder. @@ -1086,7 +1096,7 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { size_t num_concurrent_decoders = std::get<0>(GetParam()); const size_t num_in_flight_decodes = std::get<1>(GetParam()); - int num_play_throughs = std::get<2>(GetParam()); + size_t num_play_throughs = std::get<2>(GetParam()); const ResetPoint reset_point = std::get<3>(GetParam()); const int delete_decoder_state = std::get<4>(GetParam()); bool test_reuse_delay = std::get<5>(GetParam()); @@ -1119,7 +1129,7 @@ std::make_unique<ClientStateNotification<ClientState>>(); notes_[index] = std::move(note); - int delay_reuse_after_frame_num = std::numeric_limits<int>::max(); + size_t delay_reuse_after_frame_num = std::numeric_limits<size_t>::max(); if (test_reuse_delay && kMaxFramesToDelayReuse * 2 < video_file->num_frames) { delay_reuse_after_frame_num = @@ -1174,7 +1184,7 @@ static_cast<size_t>(kMinSupportedNumConcurrentDecoders)); continue; } - for (int n = 0; n < num_play_throughs; ++n) { + for (size_t n = 0; n < num_play_throughs; ++n) { // For play-throughs other than the first, we expect initialization to // succeed unconditionally. if (n > 0) { @@ -1226,8 +1236,8 @@ } LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); if (!render_as_thumbnails) { - int min_fps = g_rendering_fps == 0 ? video_file->min_fps_no_render - : video_file->min_fps_render; + double min_fps = g_rendering_fps == 0 ? video_file->min_fps_no_render + : video_file->min_fps_render; if (min_fps > 0 && !test_reuse_delay) EXPECT_GT(client->frames_per_second(), min_fps); } @@ -1277,7 +1287,8 @@ << filepath.value().c_str(); int num_bytes = base::WriteFile( filepath, reinterpret_cast<char*>(&png[0]), png.size()); - EXPECT_EQ(num_bytes, static_cast<int>(png.size())); + LOG_ASSERT(num_bytes != -1); + EXPECT_EQ(static_cast<size_t>(num_bytes), png.size()); LOG(FATAL) << "Unknown thumbnails MD5: " << md5_string; } } @@ -1601,11 +1612,11 @@ if (it->first == "num_play_throughs") { std::string input(it->second.begin(), it->second.end()); - LOG_ASSERT(base::StringToInt(input, &media::g_num_play_throughs)); + LOG_ASSERT(base::StringToSizeT(input, &media::g_num_play_throughs)); continue; } if (it->first == "fake_decoder") { - media::g_fake_decoder = 1; + media::g_fake_decoder = true; continue; } if (it->first == "v" || it->first == "vmodule")
diff --git a/media/gpu/windows/d3d11_cdm_proxy.cc b/media/gpu/windows/d3d11_cdm_proxy.cc index cdd37f6..d00e580 100644 --- a/media/gpu/windows/d3d11_cdm_proxy.cc +++ b/media/gpu/windows/d3d11_cdm_proxy.cc
@@ -12,6 +12,7 @@ #include "media/base/callback_registry.h" #include "media/base/cdm_context.h" #include "media/base/cdm_proxy_context.h" +#include "media/gpu/windows/d3d11_decryptor.h" namespace media { @@ -112,9 +113,18 @@ } CdmProxyContext* GetCdmProxyContext() override { return &cdm_proxy_context_; } + Decryptor* GetDecryptor() override { + if (!decryptor_) + decryptor_.reset(new D3D11Decryptor(&cdm_proxy_context_)); + + return decryptor_.get(); + } + private: D3D11CdmProxyContext cdm_proxy_context_; + std::unique_ptr<D3D11Decryptor> decryptor_; + // TODO(rkuroiwa): Call Notify() when new usable key is available. ClosureRegistry new_key_callbacks_;
diff --git a/media/gpu/windows/d3d11_decryptor.cc b/media/gpu/windows/d3d11_decryptor.cc new file mode 100644 index 0000000..87b064ca --- /dev/null +++ b/media/gpu/windows/d3d11_decryptor.cc
@@ -0,0 +1,71 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/gpu/windows/d3d11_decryptor.h" + +#include "base/logging.h" +#include "media/base/decoder_buffer.h" + +namespace media { + +D3D11Decryptor::D3D11Decryptor(CdmProxyContext* cdm_proxy_context) + : cdm_proxy_context_(cdm_proxy_context), weak_factory_(this) { + DCHECK(cdm_proxy_context_); +} + +D3D11Decryptor::~D3D11Decryptor() {} + +void D3D11Decryptor::RegisterNewKeyCB(StreamType stream_type, + const NewKeyCB& new_key_cb) { + // TODO(xhwang): Use RegisterNewKeyCB() on CdmContext, and remove + // RegisterNewKeyCB from Decryptor interface. + NOTREACHED(); +} + +void D3D11Decryptor::Decrypt(StreamType stream_type, + scoped_refptr<DecoderBuffer> encrypted, + const DecryptCB& decrypt_cb) { + // TODO(rkuroiwa): Implemented this function using |cdm_proxy_context_|. + NOTIMPLEMENTED(); +} + +void D3D11Decryptor::CancelDecrypt(StreamType stream_type) { + // Decrypt() calls the DecryptCB synchronously so there's nothing to cancel. +} + +void D3D11Decryptor::InitializeAudioDecoder(const AudioDecoderConfig& config, + const DecoderInitCB& init_cb) { + // D3D11Decryptor does not support audio decoding. + init_cb.Run(false); +} + +void D3D11Decryptor::InitializeVideoDecoder(const VideoDecoderConfig& config, + const DecoderInitCB& init_cb) { + // D3D11Decryptor does not support video decoding. + init_cb.Run(false); +} + +void D3D11Decryptor::DecryptAndDecodeAudio( + scoped_refptr<DecoderBuffer> encrypted, + const AudioDecodeCB& audio_decode_cb) { + NOTREACHED() << "D3D11Decryptor does not support audio decoding"; +} + +void D3D11Decryptor::DecryptAndDecodeVideo( + scoped_refptr<DecoderBuffer> encrypted, + const VideoDecodeCB& video_decode_cb) { + NOTREACHED() << "D3D11Decryptor does not support video decoding"; +} + +void D3D11Decryptor::ResetDecoder(StreamType stream_type) { + NOTREACHED() << "D3D11Decryptor does not support audio/video decoding"; +} + +void D3D11Decryptor::DeinitializeDecoder(StreamType stream_type) { + // D3D11Decryptor does not support audio/video decoding, but since this can be + // called any time after InitializeAudioDecoder/InitializeVideoDecoder, + // nothing to be done here. +} + +} // namespace media
diff --git a/media/gpu/windows/d3d11_decryptor.h b/media/gpu/windows/d3d11_decryptor.h new file mode 100644 index 0000000..ef4d5ae --- /dev/null +++ b/media/gpu/windows/d3d11_decryptor.h
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_WINDOWS_D3D11_DECRYPTOR_H_ +#define MEDIA_GPU_WINDOWS_D3D11_DECRYPTOR_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "media/base/decryptor.h" +#include "media/gpu/media_gpu_export.h" + +namespace media { + +class CdmProxyContext; + +class MEDIA_GPU_EXPORT D3D11Decryptor : public Decryptor { + public: + explicit D3D11Decryptor(CdmProxyContext* cdm_proxy_context); + ~D3D11Decryptor() final; + + // Decryptor implementation. + void RegisterNewKeyCB(StreamType stream_type, + const NewKeyCB& key_added_cb) final; + void Decrypt(StreamType stream_type, + scoped_refptr<DecoderBuffer> encrypted, + const DecryptCB& decrypt_cb) final; + void CancelDecrypt(StreamType stream_type) final; + void InitializeAudioDecoder(const AudioDecoderConfig& config, + const DecoderInitCB& init_cb) final; + void InitializeVideoDecoder(const VideoDecoderConfig& config, + const DecoderInitCB& init_cb) final; + void DecryptAndDecodeAudio(scoped_refptr<DecoderBuffer> encrypted, + const AudioDecodeCB& audio_decode_cb) final; + void DecryptAndDecodeVideo(scoped_refptr<DecoderBuffer> encrypted, + const VideoDecodeCB& video_decode_cb) final; + void ResetDecoder(StreamType stream_type) final; + void DeinitializeDecoder(StreamType stream_type) final; + + private: + CdmProxyContext* cdm_proxy_context_; + + base::WeakPtrFactory<D3D11Decryptor> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(D3D11Decryptor); +}; + +} // namespace media + +#endif // MEDIA_GPU_WINDOWS_D3D11_DECRYPTOR_H_
diff --git a/media/mojo/interfaces/interface_factory.mojom b/media/mojo/interfaces/interface_factory.mojom index 821d924..73b1e687e 100644 --- a/media/mojo/interfaces/interface_factory.mojom +++ b/media/mojo/interfaces/interface_factory.mojom
@@ -6,6 +6,7 @@ import "media/mojo/interfaces/audio_decoder.mojom"; import "media/mojo/interfaces/cdm_proxy.mojom"; +import "media/mojo/interfaces/decryptor.mojom"; import "media/mojo/interfaces/content_decryption_module.mojom"; import "media/mojo/interfaces/renderer.mojom"; import "media/mojo/interfaces/video_decoder.mojom"; @@ -60,6 +61,9 @@ // implementation must fully validate |key_system| before creating the CDM. CreateCdm(string key_system, ContentDecryptionModule& cdm); + // Creates a Decryptor associated with the |cdm_id|. + CreateDecryptor(int32 cdm_id, Decryptor& decryptor); + // Creates a CdmProxy that proxies part of CDM functionalities to a different // entity, e.g. hardware CDM modules. The created |cdm_proxy| must match the // type of the CDM, identified by |cdm_guid|.
diff --git a/media/mojo/services/interface_factory_impl.cc b/media/mojo/services/interface_factory_impl.cc index 0caf1c6..96f59ff 100644 --- a/media/mojo/services/interface_factory_impl.cc +++ b/media/mojo/services/interface_factory_impl.cc
@@ -11,6 +11,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "media/base/media_log.h" +#include "media/mojo/services/mojo_decryptor_service.h" #include "media/mojo/services/mojo_media_client.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h" @@ -167,6 +168,20 @@ #endif // BUILDFLAG(ENABLE_MOJO_CDM) } +void InterfaceFactoryImpl::CreateDecryptor(int cdm_id, + mojom::DecryptorRequest request) { + DVLOG(2) << __func__; + auto mojo_decryptor_service = + MojoDecryptorService::Create(cdm_id, &cdm_service_context_); + if (!mojo_decryptor_service) { + DLOG(ERROR) << "MojoDecryptorService creation failed."; + return; + } + + decryptor_bindings_.AddBinding(std::move(mojo_decryptor_service), + std::move(request)); +} + void InterfaceFactoryImpl::CreateCdmProxy(const std::string& cdm_guid, mojom::CdmProxyRequest request) { DVLOG(2) << __func__; @@ -223,6 +238,9 @@ return false; #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + if (!decryptor_bindings_.empty()) + return false; + return true; } @@ -252,6 +270,8 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) cdm_proxy_bindings_.set_connection_error_handler(connection_error_cb); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + + decryptor_bindings_.set_connection_error_handler(connection_error_cb); } void InterfaceFactoryImpl::OnBindingConnectionError() {
diff --git a/media/mojo/services/interface_factory_impl.h b/media/mojo/services/interface_factory_impl.h index 05ed491..02d48e0 100644 --- a/media/mojo/services/interface_factory_impl.h +++ b/media/mojo/services/interface_factory_impl.h
@@ -40,6 +40,7 @@ mojom::RendererRequest request) final; void CreateCdm(const std::string& key_system, mojom::ContentDecryptionModuleRequest request) final; + void CreateDecryptor(int cdm_id, mojom::DecryptorRequest request) final; void CreateCdmProxy(const std::string& cdm_guid, mojom::CdmProxyRequest request) final; @@ -91,6 +92,8 @@ mojo::StrongBindingSet<mojom::CdmProxy> cdm_proxy_bindings_; #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + mojo::StrongBindingSet<mojom::Decryptor> decryptor_bindings_; + std::unique_ptr<service_manager::ServiceContextRef> connection_ref_; MojoMediaClient* mojo_media_client_; base::OnceClosure destroy_cb_;
diff --git a/media/mojo/services/media_service_unittest.cc b/media/mojo/services/media_service_unittest.cc index 6aa13a1..4897ac8 100644 --- a/media/mojo/services/media_service_unittest.cc +++ b/media/mojo/services/media_service_unittest.cc
@@ -17,6 +17,7 @@ #include "media/base/mock_filters.h" #include "media/base/test_helpers.h" #include "media/mojo/buildflags.h" +#include "media/mojo/clients/mojo_decryptor.h" #include "media/mojo/clients/mojo_demuxer_stream_impl.h" #include "media/mojo/common/media_type_converters.h" #include "media/mojo/interfaces/constants.mojom.h" @@ -34,8 +35,8 @@ #include "url/origin.h" #if BUILDFLAG(ENABLE_LIBRARY_CDMS) -#include "media/cdm/cdm_paths.h" // nogncheck -#include "media/mojo/interfaces/cdm_proxy.mojom.h" // nogncheck +#include "media/cdm/cdm_paths.h" // nogncheck +#include "media/mojo/interfaces/cdm_proxy.mojom.h" #endif namespace media { @@ -43,11 +44,13 @@ namespace { using testing::_; +using testing::DoAll; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; +using testing::SaveArg; using testing::StrictMock; -using testing::WithoutArgs; +using testing::WithArg; MATCHER_P(MatchesResult, success, "") { return arg->success == success; @@ -60,6 +63,14 @@ const char kSecurityOrigin[] = "https://foo.com"; +// Returns a trivial encrypted DecoderBuffer. +scoped_refptr<DecoderBuffer> CreateEncryptedBuffer() { + scoped_refptr<DecoderBuffer> encrypted_buffer(new DecoderBuffer(100)); + encrypted_buffer->set_decrypt_config( + DecryptConfig::CreateCencConfig("dummy_key_id", "0123456789ABCDEF", {})); + return encrypted_buffer; +} + class MockCdmProxyClient : public mojom::CdmProxyClient { public: MockCdmProxyClient() = default; @@ -119,14 +130,16 @@ void SetUp() override { ServiceTest::SetUp(); - media::mojom::MediaServicePtr media_service; - connector()->BindInterface(media::mojom::kMediaServiceName, &media_service); - - service_manager::mojom::InterfaceProviderPtr interfaces; + service_manager::mojom::InterfaceProviderPtr host_interfaces; auto provider = std::make_unique<MediaInterfaceProvider>( - mojo::MakeRequest(&interfaces)); - media_service->CreateInterfaceFactory( - mojo::MakeRequest(&interface_factory_), std::move(interfaces)); + mojo::MakeRequest(&host_interfaces)); + + connector()->BindInterface(mojom::kMediaServiceName, &media_service_); + media_service_.set_connection_error_handler( + base::BindRepeating(&MediaServiceTest::MediaServiceConnectionClosed, + base::Unretained(this))); + media_service_->CreateInterfaceFactory( + mojo::MakeRequest(&interface_factory_), std::move(host_interfaces)); } MOCK_METHOD3(OnCdmInitialized, @@ -135,23 +148,26 @@ mojom::DecryptorPtr decryptor)); MOCK_METHOD0(OnCdmConnectionError, void()); - void InitializeCdm(const std::string& key_system, - bool expected_result, - int cdm_id) { + // Returns the CDM ID associated with the CDM. + int InitializeCdm(const std::string& key_system, bool expected_result) { base::RunLoop run_loop; interface_factory_->CreateCdm(key_system, mojo::MakeRequest(&cdm_)); cdm_.set_connection_error_handler(base::BindRepeating( &MediaServiceTest::OnCdmConnectionError, base::Unretained(this))); - // Have to use WithoutArgs since move-only types do not work with actions. - EXPECT_CALL(*this, - OnCdmInitialized(MatchesResult(expected_result), cdm_id, _)) - .WillOnce(WithoutArgs(QuitLoop(&run_loop))); + int cdm_id = CdmContext::kInvalidCdmId; + + // The last parameter mojom::DecryptorPtr is move-only and not supported by + // DoAll. Hence use WithArg to only extract the "int cdm_id" out and then + // call DoAll. + EXPECT_CALL(*this, OnCdmInitialized(MatchesResult(expected_result), _, _)) + .WillOnce(WithArg<1>(DoAll(SaveArg<0>(&cdm_id), QuitLoop(&run_loop)))); cdm_->Initialize(key_system, url::Origin::Create(GURL(kSecurityOrigin)), CdmConfig(), base::BindOnce(&MediaServiceTest::OnCdmInitialized, base::Unretained(this))); run_loop.Run(); + return cdm_id; } MOCK_METHOD4(OnCdmProxyInitialized, @@ -160,20 +176,47 @@ uint32_t crypto_session_id, int cdm_id)); - void InitializeCdmProxy(const std::string& cdm_guid) { + // Returns the CDM ID associated with the CdmProxy. + int InitializeCdmProxy(const std::string& cdm_guid) { base::RunLoop run_loop; interface_factory_->CreateCdmProxy(cdm_guid, mojo::MakeRequest(&cdm_proxy_)); - EXPECT_CALL(*this, OnCdmProxyInitialized(CdmProxy::Status::kOk, _, _, _)) - .WillOnce(QuitLoop(&run_loop)); mojom::CdmProxyClientAssociatedPtrInfo client_ptr_info; cdm_proxy_client_binding_.Bind(mojo::MakeRequest(&client_ptr_info)); + int cdm_id = CdmContext::kInvalidCdmId; + + EXPECT_CALL(*this, OnCdmProxyInitialized(CdmProxy::Status::kOk, _, _, _)) + .WillOnce(DoAll(SaveArg<3>(&cdm_id), QuitLoop(&run_loop))); cdm_proxy_->Initialize( std::move(client_ptr_info), base::BindOnce(&MediaServiceTest::OnCdmProxyInitialized, base::Unretained(this))); run_loop.Run(); + return cdm_id; + } + + MOCK_METHOD2(OnDecrypted, + void(Decryptor::Status, scoped_refptr<DecoderBuffer>)); + + void CreateDecryptor(int cdm_id, bool expected_result) { + base::RunLoop run_loop; + mojom::DecryptorPtr decryptor_ptr; + interface_factory_->CreateDecryptor(cdm_id, + mojo::MakeRequest(&decryptor_ptr)); + MojoDecryptor mojo_decryptor(std::move(decryptor_ptr)); + + // In the success case, there's no decryption key to decrypt the buffer so + // we would expect no-key. + auto expected_status = + expected_result ? Decryptor::kNoKey : Decryptor::kError; + + EXPECT_CALL(*this, OnDecrypted(expected_status, _)) + .WillOnce(QuitLoop(&run_loop)); + mojo_decryptor.Decrypt(Decryptor::kVideo, CreateEncryptedBuffer(), + base::BindRepeating(&MediaServiceTest::OnDecrypted, + base::Unretained(this))); + run_loop.Run(); } MOCK_METHOD1(OnRendererInitialized, void(bool)); @@ -194,10 +237,11 @@ mojom::RendererClientAssociatedPtrInfo client_ptr_info; renderer_client_binding_.Bind(mojo::MakeRequest(&client_ptr_info)); - EXPECT_CALL(*this, OnRendererInitialized(expected_result)) - .WillOnce(QuitLoop(&run_loop)); std::vector<mojom::DemuxerStreamPtrInfo> streams; streams.push_back(std::move(video_stream_proxy_info)); + + EXPECT_CALL(*this, OnRendererInitialized(expected_result)) + .WillOnce(QuitLoop(&run_loop)); renderer_->Initialize( std::move(client_ptr_info), std::move(streams), base::nullopt, base::nullopt, @@ -209,6 +253,7 @@ MOCK_METHOD0(MediaServiceConnectionClosed, void()); protected: + mojom::MediaServicePtr media_service_; mojom::InterfaceFactoryPtr interface_factory_; mojom::ContentDecryptionModulePtr cdm_; mojom::CdmProxyPtr cdm_proxy_; @@ -232,18 +277,24 @@ // Note: base::RunLoop::RunUntilIdle() does not work well in these tests because // even when the loop is idle, we may still have pending events in the pipe. // - If you have an InterfacePtr hosted by the service in the service process, -// you can use InterfacePtr::FlushForTesting(). +// you can use InterfacePtr::FlushForTesting(). Note that this doesn't drain +// the task runner in the test process and doesn't cover all negative cases. // - If you expect a callback on an InterfacePtr call or connection error, use // base::RunLoop::Run() and QuitLoop(). // TODO(crbug.com/829233): Enable these tests on Android. #if BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID) TEST_F(MediaServiceTest, InitializeCdm_Success) { - InitializeCdm(kClearKeyKeySystem, true, 1); + InitializeCdm(kClearKeyKeySystem, true); } TEST_F(MediaServiceTest, InitializeCdm_InvalidKeySystem) { - InitializeCdm(kInvalidKeySystem, false, 0); + InitializeCdm(kInvalidKeySystem, false); +} + +TEST_F(MediaServiceTest, Decryptor_WithCdm) { + int cdm_id = InitializeCdm(kClearKeyKeySystem, true); + CreateDecryptor(cdm_id, true); } #endif // BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID) @@ -257,19 +308,66 @@ TEST_F(MediaServiceTest, CdmProxy) { InitializeCdmProxy(kClearKeyCdmGuid); } + +TEST_F(MediaServiceTest, Decryptor_WithCdmProxy) { + int cdm_id = InitializeCdmProxy(kClearKeyCdmGuid); + CreateDecryptor(cdm_id, true); +} + +TEST_F(MediaServiceTest, Decryptor_WrongCdmId) { + int cdm_id = InitializeCdmProxy(kClearKeyCdmGuid); + CreateDecryptor(cdm_id + 1, false); +} + +TEST_F(MediaServiceTest, DeferredDestruction_CdmProxy) { + InitializeCdmProxy(kClearKeyCdmGuid); + + // Disconnecting InterfaceFactory should not terminate the MediaService since + // there is still a CdmProxy hosted. + interface_factory_.reset(); + cdm_proxy_.FlushForTesting(); + + // Disconnecting CdmProxy will now terminate the MediaService. + base::RunLoop run_loop; + EXPECT_CALL(*this, MediaServiceConnectionClosed()) + .WillOnce(QuitLoop(&run_loop)); + cdm_proxy_.reset(); + run_loop.Run(); +} #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) -TEST_F(MediaServiceTest, Lifetime) { - // The lifetime of the media service is controlled by the number of - // live InterfaceFactory impls, which are then deferred destroyed until no - // media components (CDM or Renderer) are hosted. - media::mojom::MediaServicePtr media_service; - connector()->BindInterface(media::mojom::kMediaServiceName, &media_service); - media_service.set_connection_error_handler(base::BindRepeating( - &MediaServiceTest::MediaServiceConnectionClosed, base::Unretained(this))); +TEST_F(MediaServiceTest, Decryptor_WithoutCdmOrCdmProxy) { + // Creating decryptor without creating CDM or CdmProxy. + CreateDecryptor(1, false); +} +TEST_F(MediaServiceTest, Lifetime_DestroyMediaService) { + // Disconnecting |media_service_| doesn't terminate MediaService + // since |interface_factory_| is still alive. This is ensured here since + // MediaServiceConnectionClosed() is not called. + EXPECT_CALL(*this, MediaServiceConnectionClosed()).Times(0); + media_service_.reset(); + interface_factory_.FlushForTesting(); +} + +TEST_F(MediaServiceTest, Lifetime_DestroyInterfaceFactory) { + // Disconnecting InterfaceFactory will now terminate the MediaService since + // there's no media components hosted. + base::RunLoop run_loop; + EXPECT_CALL(*this, MediaServiceConnectionClosed()) + .WillOnce(QuitLoop(&run_loop)); + interface_factory_.reset(); + run_loop.Run(); +} + +#if (BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID)) || \ + BUILDFLAG(ENABLE_MOJO_RENDERER) +// MediaService stays alive as long as there are InterfaceFactory impls, which +// are then deferred destroyed until no media components (e.g. CDM or Renderer) +// are hosted. +TEST_F(MediaServiceTest, Lifetime) { #if BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID) - InitializeCdm(kClearKeyKeySystem, true, 1); + InitializeCdm(kClearKeyKeySystem, true); #endif #if BUILDFLAG(ENABLE_MOJO_RENDERER) @@ -290,19 +388,9 @@ run_loop.Run(); } -#if (BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID)) || \ - BUILDFLAG(ENABLE_MOJO_RENDERER) TEST_F(MediaServiceTest, DeferredDestruction) { - // The lifetime of the media service is controlled by the number of - // live InterfaceFactory impls, which are then deferred destroyed until no - // media components (CDM or Renderer) are hosted. - media::mojom::MediaServicePtr media_service; - connector()->BindInterface(media::mojom::kMediaServiceName, &media_service); - media_service.set_connection_error_handler(base::BindRepeating( - &MediaServiceTest::MediaServiceConnectionClosed, base::Unretained(this))); - #if BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID) - InitializeCdm(kClearKeyKeySystem, true, 1); + InitializeCdm(kClearKeyKeySystem, true); #endif #if BUILDFLAG(ENABLE_MOJO_RENDERER) @@ -323,10 +411,10 @@ // Disconnecting CDM and Renderer will now terminate the MediaService. base::RunLoop run_loop; - cdm_.reset(); - renderer_.reset(); EXPECT_CALL(*this, MediaServiceConnectionClosed()) .WillOnce(QuitLoop(&run_loop)); + cdm_.reset(); + renderer_.reset(); run_loop.Run(); } #endif // (BUILDFLAG(ENABLE_MOJO_CDM) && !defined(OS_ANDROID)) ||
diff --git a/media/mojo/services/mojo_cdm_service_context.cc b/media/mojo/services/mojo_cdm_service_context.cc index f7d62cc..49e71b5 100644 --- a/media/mojo/services/mojo_cdm_service_context.cc +++ b/media/mojo/services/mojo_cdm_service_context.cc
@@ -38,13 +38,14 @@ private: // CdmContext implementation. + Decryptor* GetDecryptor() final { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return cdm_context_ ? cdm_context_->GetDecryptor() : nullptr; + } + CdmProxyContext* GetCdmProxyContext() final { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - if (!cdm_context_) - return nullptr; - - return cdm_context_->GetCdmProxyContext(); + return cdm_context_ ? cdm_context_->GetCdmProxyContext() : nullptr; } base::WeakPtr<CdmContext> cdm_context_;
diff --git a/media/mojo/services/mojo_decryptor_service.cc b/media/mojo/services/mojo_decryptor_service.cc index c6cf6ee..8a08b90 100644 --- a/media/mojo/services/mojo_decryptor_service.cc +++ b/media/mojo/services/mojo_decryptor_service.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/numerics/safe_conversions.h" #include "media/base/audio_decoder_config.h" +#include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/decryptor.h" #include "media/base/video_decoder_config.h" @@ -17,6 +18,7 @@ #include "media/mojo/common/mojo_decoder_buffer_converter.h" #include "media/mojo/common/mojo_shared_buffer_video_frame.h" #include "media/mojo/interfaces/demuxer_stream.mojom.h" +#include "media/mojo/services/mojo_cdm_service_context.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace media { @@ -45,6 +47,29 @@ } // namespace +// static +std::unique_ptr<MojoDecryptorService> MojoDecryptorService::Create( + int cdm_id, + MojoCdmServiceContext* mojo_cdm_service_context) { + auto cdm_context_ref = mojo_cdm_service_context->GetCdmContextRef(cdm_id); + if (!cdm_context_ref) { + DVLOG(1) << "CdmContextRef not found for CDM ID: " << cdm_id; + return nullptr; + } + + auto* cdm_context = cdm_context_ref->GetCdmContext(); + DCHECK(cdm_context); + + auto* decryptor = cdm_context->GetDecryptor(); + if (!decryptor) { + DVLOG(1) << "CdmContext does not support Decryptor"; + return nullptr; + } + + return std::make_unique<MojoDecryptorService>(decryptor, + std::move(cdm_context_ref)); +} + MojoDecryptorService::MojoDecryptorService( media::Decryptor* decryptor, std::unique_ptr<CdmContextRef> cdm_context_ref)
diff --git a/media/mojo/services/mojo_decryptor_service.h b/media/mojo/services/mojo_decryptor_service.h index c9d25fc..17e8258 100644 --- a/media/mojo/services/mojo_decryptor_service.h +++ b/media/mojo/services/mojo_decryptor_service.h
@@ -21,6 +21,7 @@ namespace media { class DecoderBuffer; +class MojoCdmServiceContext; class MojoDecoderBufferReader; class MojoDecoderBufferWriter; @@ -31,6 +32,10 @@ using StreamType = media::Decryptor::StreamType; using Status = media::Decryptor::Status; + static std::unique_ptr<MojoDecryptorService> Create( + int cdm_id, + MojoCdmServiceContext* mojo_cdm_service_context); + // If |cdm_context_ref| is null, caller must ensure that |decryptor| outlives // |this|. Otherwise, |decryptor| is guaranteed to be valid as long as // |cdm_context_ref| is held. @@ -101,6 +106,9 @@ std::unique_ptr<MojoDecoderBufferWriter> decrypted_buffer_writer_; media::Decryptor* decryptor_; + + // Holds the CdmContextRef to keep the CdmContext alive for the lifetime of + // the |decryptor_|. std::unique_ptr<CdmContextRef> cdm_context_ref_; base::WeakPtr<MojoDecryptorService> weak_this_;
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index f1a5128f..2efddd6d 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -147,7 +147,20 @@ static const char kSfxLosslessHash[] = "3.03,2.86,2.99,3.31,3.57,4.06,"; #if defined(OPUS_FIXED_POINT) -// NOTE: Hashes are specific to ARM devices. x86 will not match. +// NOTE: These hashes are specific to ARM devices, which use fixed-point Opus +// implementation. x86 uses floating-point Opus, so x86 hashes won't match +#if defined(ARCH_CPU_ARM64) +static const char kOpusEndTrimmingHash_1[] = + "-4.57,-5.66,-6.52,-6.29,-4.37,-3.60,"; +static const char kOpusEndTrimmingHash_2[] = + "-11.90,-11.10,-8.26,-7.12,-7.85,-9.99,"; +static const char kOpusEndTrimmingHash_3[] = + "-13.30,-14.37,-13.70,-11.69,-10.20,-10.48,"; +static const char kOpusSmallCodecDelayHash_1[] = + "-0.48,-0.09,1.27,1.06,1.54,-0.22,"; +static const char kOpusSmallCodecDelayHash_2[] = + "0.29,0.15,-0.19,0.25,0.68,0.83,"; +#else static const char kOpusEndTrimmingHash_1[] = "-4.57,-5.66,-6.52,-6.30,-4.37,-3.61,"; static const char kOpusEndTrimmingHash_2[] = @@ -158,6 +171,8 @@ "-0.48,-0.09,1.27,1.06,1.54,-0.22,"; static const char kOpusSmallCodecDelayHash_2[] = "0.29,0.14,-0.20,0.24,0.68,0.83,"; +#endif // defined(ARCH_CPU_ARM64) + #else // Hash for a full playthrough of "opus-trimming-test.(webm|ogg)". static const char kOpusEndTrimmingHash_1[] =
diff --git a/media/video/picture.cc b/media/video/picture.cc index dc1d48e..e7ab1db 100644 --- a/media/video/picture.cc +++ b/media/video/picture.cc
@@ -75,7 +75,7 @@ color_space_(color_space), allow_overlay_(allow_overlay), size_changed_(false), - surface_texture_(false), + texture_owner_(false), wants_promotion_hint_(false) {} Picture::Picture(const Picture& other) = default;
diff --git a/media/video/picture.h b/media/video/picture.h index 5da84c2..0dedb51 100644 --- a/media/video/picture.h +++ b/media/video/picture.h
@@ -116,11 +116,9 @@ void set_size_changed(bool size_changed) { size_changed_ = size_changed; } - bool surface_texture() const { return surface_texture_; } + bool texture_owner() const { return texture_owner_; } - void set_surface_texture(bool surface_texture) { - surface_texture_ = surface_texture; - } + void set_texture_owner(bool texture_owner) { texture_owner_ = texture_owner; } bool wants_promotion_hint() const { return wants_promotion_hint_; } @@ -135,7 +133,7 @@ gfx::ColorSpace color_space_; bool allow_overlay_; bool size_changed_; - bool surface_texture_; + bool texture_owner_; bool wants_promotion_hint_; };
diff --git a/mojo/edk/BUILD.gn b/mojo/edk/BUILD.gn index 8b6c6a19..d5beead 100644 --- a/mojo/edk/BUILD.gn +++ b/mojo/edk/BUILD.gn
@@ -87,6 +87,12 @@ "system/user_message_impl.h", ] + if (is_win) { + public += [ "embedder/named_platform_handle_win.h" ] + } else if (is_posix || is_fuchsia) { + public += [ "embedder/named_platform_handle_posix.h" ] + } + sources = [ "embedder/connection_params.cc", "embedder/entrypoints.cc",
diff --git a/mojo/edk/embedder/named_platform_handle.h b/mojo/edk/embedder/named_platform_handle.h index 15ca656..e212792 100644 --- a/mojo/edk/embedder/named_platform_handle.h +++ b/mojo/edk/embedder/named_platform_handle.h
@@ -5,47 +5,12 @@ #ifndef MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_ #define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_ -#include <string> - -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" -#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "mojo/edk/system/system_impl_export.h" -namespace mojo { -namespace edk { - -#if defined(OS_POSIX) -struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle { - NamedPlatformHandle() {} - explicit NamedPlatformHandle(const base::StringPiece& name) - : name(name.as_string()) {} - - bool is_valid() const { return !name.empty(); } - - std::string name; -}; -#elif defined(OS_WIN) -struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle { - NamedPlatformHandle() {} - explicit NamedPlatformHandle(const base::StringPiece& name) - : name(base::UTF8ToUTF16(name)) {} - - explicit NamedPlatformHandle(const base::StringPiece16& name) - : name(name.as_string()) {} - - bool is_valid() const { return !name.empty(); } - - base::string16 pipe_name() const { return L"\\\\.\\pipe\\mojo." + name; } - - base::string16 name; -}; -#else -#error "Platform not yet supported." +#if defined(OS_WIN) +#include "mojo/edk/embedder/named_platform_handle_win.h" +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include "mojo/edk/embedder/named_platform_handle_posix.h" #endif -} // namespace edk -} // namespace mojo - #endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
diff --git a/mojo/edk/embedder/named_platform_handle_posix.h b/mojo/edk/embedder/named_platform_handle_posix.h new file mode 100644 index 0000000..3c7e0a1e5 --- /dev/null +++ b/mojo/edk/embedder/named_platform_handle_posix.h
@@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_POSIX_H_ +#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_POSIX_H_ + +#include <string> + +#include "base/strings/string_piece.h" +#include "mojo/edk/system/system_impl_export.h" + +namespace mojo { +namespace edk { + +struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle { + NamedPlatformHandle() {} + explicit NamedPlatformHandle(const base::StringPiece& name) + : name(name.as_string()) {} + + bool is_valid() const { return !name.empty(); } + + std::string name; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_POSIX_H_
diff --git a/mojo/edk/embedder/named_platform_handle_win.h b/mojo/edk/embedder/named_platform_handle_win.h new file mode 100644 index 0000000..febeb689 --- /dev/null +++ b/mojo/edk/embedder/named_platform_handle_win.h
@@ -0,0 +1,34 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_WIN_H_ +#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_WIN_H_ + +#include "base/strings/string16.h" +#include "base/strings/string_piece.h" +#include "base/strings/utf_string_conversions.h" +#include "mojo/edk/system/system_impl_export.h" + +namespace mojo { +namespace edk { + +struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle { + NamedPlatformHandle() {} + explicit NamedPlatformHandle(const base::StringPiece& name) + : name(base::UTF8ToUTF16(name)) {} + + explicit NamedPlatformHandle(const base::StringPiece16& name) + : name(name.as_string()) {} + + bool is_valid() const { return !name.empty(); } + + base::string16 pipe_name() const { return L"\\\\.\\pipe\\mojo." + name; } + + base::string16 name; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_WIN_H_
diff --git a/mojo/edk/embedder/platform_handle.cc b/mojo/edk/embedder/platform_handle.cc index 3a1fb174..f4eb0eb3 100644 --- a/mojo/edk/embedder/platform_handle.cc +++ b/mojo/edk/embedder/platform_handle.cc
@@ -5,16 +5,15 @@ #include "mojo/edk/embedder/platform_handle.h" #include "build/build_config.h" -#if defined(OS_FUCHSIA) + +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_FUCHSIA) +#include <unistd.h> #include <zircon/status.h> #include <zircon/syscalls.h> -#endif -#if defined(OS_POSIX) +#elif defined(OS_POSIX) #include <unistd.h> -#elif defined(OS_WIN) -#include <windows.h> -#else -#error "Platform not yet supported." #endif #include "base/logging.h" @@ -26,32 +25,7 @@ if (!is_valid()) return; -#if defined(OS_FUCHSIA) - if (handle != ZX_HANDLE_INVALID) { - zx_status_t result = zx_handle_close(handle); - DCHECK_EQ(ZX_OK, result) << "CloseIfNecessary(zx_handle_close): " - << zx_status_get_string(result); - handle = ZX_HANDLE_INVALID; - } - if (fd >= 0) { - bool success = (close(fd) == 0); - DPCHECK(success); - fd = -1; - } -#elif defined(OS_POSIX) - if (type == Type::POSIX) { - bool success = (close(handle) == 0); - DPCHECK(success); - handle = -1; - } -#if defined(OS_MACOSX) && !defined(OS_IOS) - else if (type == Type::MACH) { - kern_return_t rv = mach_port_deallocate(mach_task_self(), port); - DPCHECK(rv == KERN_SUCCESS); - port = MACH_PORT_NULL; - } -#endif // defined(OS_MACOSX) && !defined(OS_IOS) -#elif defined(OS_WIN) +#if defined(OS_WIN) if (owning_process != base::GetCurrentProcessHandle()) { // This handle may have been duplicated to a new target process but not yet // sent there. In this case CloseHandle should NOT be called. From MSDN @@ -84,9 +58,34 @@ bool success = !!CloseHandle(handle); DPCHECK(success); handle = INVALID_HANDLE_VALUE; +#elif defined(OS_FUCHSIA) + if (handle != ZX_HANDLE_INVALID) { + zx_status_t result = zx_handle_close(handle); + DCHECK_EQ(ZX_OK, result) << "CloseIfNecessary(zx_handle_close): " + << zx_status_get_string(result); + handle = ZX_HANDLE_INVALID; + } + if (fd >= 0) { + bool success = (close(fd) == 0); + DPCHECK(success); + fd = -1; + } +#elif defined(OS_POSIX) + if (type == Type::POSIX) { + bool success = (close(handle) == 0); + DPCHECK(success); + handle = -1; + } +#if defined(OS_MACOSX) && !defined(OS_IOS) + else if (type == Type::MACH) { + kern_return_t rv = mach_port_deallocate(mach_task_self(), port); + DPCHECK(rv == KERN_SUCCESS); + port = MACH_PORT_NULL; + } +#endif // defined(OS_MACOSX) && !defined(OS_IOS) #else #error "Platform not yet supported." -#endif +#endif // defined(OS_WIN) } } // namespace edk
diff --git a/mojo/edk/embedder/platform_handle.h b/mojo/edk/embedder/platform_handle.h index 9f6aa23..807fb6a 100644 --- a/mojo/edk/embedder/platform_handle.h +++ b/mojo/edk/embedder/platform_handle.h
@@ -12,11 +12,11 @@ #include <windows.h> #include "base/process/process_handle.h" -#elif defined(OS_MACOSX) && !defined(OS_IOS) -#include <mach/mach.h> #elif defined(OS_FUCHSIA) #include <fdio/limits.h> #include <zircon/syscalls.h> +#elif defined(OS_MACOSX) && !defined(OS_IOS) +#include <mach/mach.h> #endif #include "base/logging.h" @@ -24,7 +24,29 @@ namespace mojo { namespace edk { -#if defined(OS_FUCHSIA) +#if defined(OS_WIN) +struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { + PlatformHandle() : PlatformHandle(INVALID_HANDLE_VALUE) {} + explicit PlatformHandle(HANDLE handle) + : handle(handle), owning_process(base::GetCurrentProcessHandle()) {} + + void CloseIfNecessary(); + + bool is_valid() const { return handle != INVALID_HANDLE_VALUE; } + + HANDLE handle; + + // A Windows HANDLE may be duplicated to another process but not yet sent to + // that process. This tracks the handle's owning process and this process + // handle (if not null, i.e., the current process) is *owned* by this + // PlatformHandle. + base::ProcessHandle owning_process; + + // A Windows HANDLE may be an unconnected named pipe. In this case, we need to + // wait for a connection before communicating on the pipe. + bool needs_connection = false; +}; +#elif defined(OS_FUCHSIA) // TODO(fuchsia): Find a clean way to share this with the POSIX version. // |zx_handle_t| is a typedef of |int|, so we only allow PlatformHandle to be // created via explicit For<type>() creator functions. @@ -94,28 +116,6 @@ mach_port_t port = MACH_PORT_NULL; #endif }; -#elif defined(OS_WIN) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { - PlatformHandle() : PlatformHandle(INVALID_HANDLE_VALUE) {} - explicit PlatformHandle(HANDLE handle) - : handle(handle), owning_process(base::GetCurrentProcessHandle()) {} - - void CloseIfNecessary(); - - bool is_valid() const { return handle != INVALID_HANDLE_VALUE; } - - HANDLE handle; - - // A Windows HANDLE may be duplicated to another process but not yet sent to - // that process. This tracks the handle's owning process and this process - // handle (if not null, i.e., the current process) is *owned* by this - // PlatformHandle. - base::ProcessHandle owning_process; - - // A Windows HANDLE may be an unconnected named pipe. In this case, we need to - // wait for a connection before communicating on the pipe. - bool needs_connection = false; -}; #else #error "Platform not yet supported." #endif
diff --git a/mojo/edk/system/platform_wrapper_unittest.cc b/mojo/edk/system/platform_wrapper_unittest.cc index f97be52..6b74a91 100644 --- a/mojo/edk/system/platform_wrapper_unittest.cc +++ b/mojo/edk/system/platform_wrapper_unittest.cc
@@ -23,25 +23,25 @@ #include <windows.h> #endif -#if defined(OS_POSIX) -#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR -#elif defined(OS_WIN) +#if defined(OS_WIN) #define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR #endif -#if defined(OS_MACOSX) && !defined(OS_IOS) -#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT -#elif defined(OS_FUCHSIA) +#if defined(OS_FUCHSIA) #define SHARED_BUFFER_PLATFORM_HANDLE_TYPE \ MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE -#else +#elif defined(OS_MACOSX) && !defined(OS_IOS) +#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT +#elif defined(OS_WIN) || defined(OS_POSIX) #define SHARED_BUFFER_PLATFORM_HANDLE_TYPE SIMPLE_PLATFORM_HANDLE_TYPE #endif uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) { #if defined(OS_WIN) return reinterpret_cast<uint64_t>(file); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) return static_cast<uint64_t>(file); #endif } @@ -49,7 +49,7 @@ base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) { #if defined(OS_WIN) return reinterpret_cast<base::PlatformFile>(value); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) return static_cast<base::PlatformFile>(value); #endif } @@ -126,12 +126,14 @@ MojoPlatformHandle os_buffer; os_buffer.struct_size = sizeof(MojoPlatformHandle); os_buffer.type = SHARED_BUFFER_PLATFORM_HANDLE_TYPE; -#if defined(OS_MACOSX) && !defined(OS_IOS) - os_buffer.value = static_cast<uint64_t>(memory_handle.GetMemoryObject()); -#elif defined(OS_WIN) +#if defined(OS_WIN) os_buffer.value = reinterpret_cast<uint64_t>(memory_handle.GetHandle()); -#else +#elif defined(OS_MACOSX) && !defined(OS_IOS) + os_buffer.value = static_cast<uint64_t>(memory_handle.GetMemoryObject()); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) os_buffer.value = static_cast<uint64_t>(memory_handle.GetHandle()); +#else +#error Unsupported platform #endif MojoSharedBufferGuid mojo_guid; @@ -179,23 +181,23 @@ base::UnguessableToken guid = base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low); -#if defined(OS_MACOSX) && !defined(OS_IOS) - ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, os_buffer.type); +#if defined(OS_WIN) + ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type); base::SharedMemoryHandle memory_handle( - static_cast<mach_port_t>(os_buffer.value), size, guid); + reinterpret_cast<HANDLE>(os_buffer.value), size, guid); #elif defined(OS_FUCHSIA) ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE, os_buffer.type); base::SharedMemoryHandle memory_handle( static_cast<zx_handle_t>(os_buffer.value), size, guid); +#elif defined(OS_MACOSX) && !defined(OS_IOS) + ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, os_buffer.type); + base::SharedMemoryHandle memory_handle( + static_cast<mach_port_t>(os_buffer.value), size, guid); #elif defined(OS_POSIX) ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR, os_buffer.type); base::SharedMemoryHandle memory_handle( base::FileDescriptor(static_cast<int>(os_buffer.value), false), size, guid); -#elif defined(OS_WIN) - ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type); - base::SharedMemoryHandle memory_handle( - reinterpret_cast<HANDLE>(os_buffer.value), size, guid); #endif base::SharedMemory memory(memory_handle, read_only);
diff --git a/mojo/public/cpp/system/platform_handle.h b/mojo/public/cpp/system/platform_handle.h index 2f0cba07..5e4748c1 100644 --- a/mojo/public/cpp/system/platform_handle.h +++ b/mojo/public/cpp/system/platform_handle.h
@@ -22,6 +22,7 @@ #include "base/memory/unsafe_shared_memory_region.h" #include "base/memory/writable_shared_memory_region.h" #include "base/process/process_handle.h" +#include "build/build_config.h" #include "mojo/public/c/system/platform_handle.h" #include "mojo/public/cpp/system/buffer.h" #include "mojo/public/cpp/system/handle.h" @@ -33,28 +34,32 @@ namespace mojo { -#if defined(OS_POSIX) +#if defined(OS_WIN) +const MojoPlatformHandleType kPlatformFileHandleType = + MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; + +const MojoPlatformHandleType kPlatformSharedBufferHandleType = + MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; + +#elif defined(OS_FUCHSIA) +const MojoPlatformHandleType kPlatformFileHandleType = + MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; +const MojoPlatformHandleType kPlatformSharedBufferHandleType = + MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE; + +#elif defined(OS_POSIX) const MojoPlatformHandleType kPlatformFileHandleType = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; #if defined(OS_MACOSX) && !defined(OS_IOS) const MojoPlatformHandleType kPlatformSharedBufferHandleType = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; -#elif defined(OS_FUCHSIA) -const MojoPlatformHandleType kPlatformSharedBufferHandleType = - MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE; #else const MojoPlatformHandleType kPlatformSharedBufferHandleType = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; #endif // defined(OS_MACOSX) && !defined(OS_IOS) -#elif defined(OS_WIN) -const MojoPlatformHandleType kPlatformFileHandleType = - MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; - -const MojoPlatformHandleType kPlatformSharedBufferHandleType = - MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; -#endif // defined(OS_POSIX) +#endif // defined(OS_WIN) // Used to specify the protection status of a base::SharedMemoryHandle memory // handle wrapped or unwrapped by mojo::WrapSharedMemoryHandle or
diff --git a/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl index 176f1b89..b2ca3ea 100644 --- a/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl +++ b/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl
@@ -32,35 +32,30 @@ {#--- Fuzzing #} {%- if generate_fuzzing %} +{%- from "fuzzing.tmpl" import generate_or_mutate %} {{struct.name}}.generate = function(generator_) { var generated = new {{struct.name}}; {%- for field in struct.fields %} -{%- if not field.kind|is_any_handle_or_interface_kind %} -{%- from "fuzzing.tmpl" import generate_or_mutate %} generated.{{field.name}} = {{generate_or_mutate('generator_', 'generate', field.kind)|indent(4)}}; -{%- endif %} {%- endfor %} return generated; }; {{struct.name}}.prototype.mutate = function(mutator_) { {%- for field in struct.fields %} -{%- if not field.kind|is_any_handle_or_interface_kind %} if (mutator_.chooseMutateField()) { -{%- from "fuzzing.tmpl" import generate_or_mutate %} this.{{field.name}} = {{generate_or_mutate('mutator_', 'mutate', field.kind, 'this.' ~ field.name)|indent(6)}}; } -{%- endif %} {%- endfor %} return this; }; +{%- from "fuzzing.tmpl" import get_handle_deps %} {{struct.name}}.prototype.getHandleDeps = function() { var handles = []; {%- for field in struct.fields %} {%- if field.kind|contains_handles_or_interfaces %} if (this.{{field.name}} !== null) { -{%- from "fuzzing.tmpl" import get_handle_deps %} Array.prototype.push.apply(handles, {{get_handle_deps(field.kind, 'this.' ~ field.name)|indent(6)}}); } {%- endif %} @@ -72,10 +67,10 @@ this.setHandlesInternal_(arguments, 0); }; +{%- from "fuzzing.tmpl" import set_handles %} {{struct.name}}.prototype.setHandlesInternal_ = function(handles, idx) { {%- for field in struct.fields %} {%- if field.kind|contains_handles_or_interfaces %} -{%- from "fuzzing.tmpl" import set_handles %} {{set_handles(field.kind, 'this.' ~ field.name)|indent(4)}}; {%- endif %} {%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl b/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl index d00e641..499c786 100644 --- a/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl +++ b/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl
@@ -39,7 +39,8 @@ this[keys[0]] = value[keys[0]]; } -{% if generate_fuzzing %} +{%- if generate_fuzzing %} +{%- from "fuzzing.tmpl" import generate_or_mutate %} {{union.name}}.generate = function(generator_) { var generated = new {{union.name}}; var generators = [ @@ -47,10 +48,7 @@ { field: "{{field.name}}", -{%- if not field.kind|is_any_handle_or_interface_kind %} -{%- from "fuzzing.tmpl" import generate_or_mutate %} generator: function() { return {{generate_or_mutate('generator_', 'generate', field.kind)|indent(6)}}; }, -{%- endif %} }, {%- endfor %} ]; @@ -66,10 +64,7 @@ { field: "{{field.name}}", -{%- if not field.kind|is_any_handle_or_interface_kind %} -{%- from "fuzzing.tmpl" import generate_or_mutate %} mutator: function() { return {{generate_or_mutate('mutator_', 'mutate', field.kind, 'this.' ~ field.name)|indent(6)}}; }, -{%- endif %} }, {%- endfor %} ]; @@ -79,27 +74,27 @@ return this; } +{%- from "fuzzing.tmpl" import get_handle_deps %} {{union.name}}.prototype.getHandleDeps = function() { -{%- for field in union.fields %} -{%- if field.kind|contains_handles_or_interfaces %} +{%- for field in union.fields %} +{%- if field.kind|contains_handles_or_interfaces %} if (this.$tag == {{union.name}}.Tags.{{field.name}}) { -{%- from "fuzzing.tmpl" import get_handle_deps %} return {{get_handle_deps(field.kind, 'this.' ~ field.name)}}; } -{%- endif %} -{%- endfor %} +{%- endif %} +{%- endfor %} return []; } +{%- from "fuzzing.tmpl" import set_handles %} {{union.name}}.prototype.setHandles = function() { -{%- for field in union.fields %} -{%- if field.kind|contains_handles_or_interfaces %} +{%- for field in union.fields %} +{%- if field.kind|contains_handles_or_interfaces %} if (this.$tag == {{union.name}}.Tags.{{field.name}}) { -{%- from "fuzzing.tmpl" import set_handles %} return {{set_handles(field.kind, 'this.' ~ field.name)}}; } -{%- endif %} -{%- endfor %} +{%- endif %} +{%- endfor %} return []; } {%- endif %}
diff --git a/net/BUILD.gn b/net/BUILD.gn index e4c934c..14dc74c 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -4775,7 +4775,6 @@ "cert/ct_log_response_parser_unittest.cc", "cert/ct_log_verifier_unittest.cc", "cert/ct_objects_extractor_unittest.cc", - "cert/ct_policy_enforcer_unittest.cc", "cert/ct_serialization_unittest.cc", "cert/ev_root_ca_metadata_unittest.cc", "cert/internal/cert_issuer_source_aia_unittest.cc",
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h index 46f0ce3..d7ba39b 100644 --- a/net/base/file_stream_context.h +++ b/net/base/file_stream_context.h
@@ -35,10 +35,11 @@ #include "base/message_loop/message_pump_for_io.h" #include "base/single_thread_task_runner.h" #include "base/task_runner.h" +#include "build/build_config.h" #include "net/base/completion_once_callback.h" #include "net/base/file_stream.h" -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) #include <errno.h> #endif @@ -52,7 +53,7 @@ #if defined(OS_WIN) class FileStream::Context : public base::MessagePumpForIO::IOHandler { -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) class FileStream::Context { #endif public: @@ -65,7 +66,7 @@ Context(base::File file, const scoped_refptr<base::TaskRunner>& task_runner); #if defined(OS_WIN) ~Context() override; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) ~Context(); #endif @@ -204,7 +205,7 @@ // the ReadFile API. void ReadAsyncResult(BOOL read_file_ret, DWORD bytes_read, DWORD os_error); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // ReadFileImpl() is a simple wrapper around read() that handles EINTR // signals and calls RecordAndMapError() to map errno to net error codes. IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); @@ -213,7 +214,7 @@ // signals and calls MapSystemError() to map errno to net error codes. // It tries to write to completion. IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); -#endif +#endif // defined(OS_WIN) base::File file_; bool async_in_progress_;
diff --git a/net/base/filename_util.cc b/net/base/filename_util.cc index 1e1d51c0..16341dc 100644 --- a/net/base/filename_util.cc +++ b/net/base/filename_util.cc
@@ -11,6 +11,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "build/build_config.h" #include "net/base/escape.h" #include "net/base/filename_util_internal.h" #include "net/base/net_string_util.h" @@ -49,7 +50,7 @@ base::ReplaceSubstringsAfterOffset( &url_string, 0, FILE_PATH_LITERAL("?"), FILE_PATH_LITERAL("%3F")); -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) base::ReplaceSubstringsAfterOffset( &url_string, 0, FILE_PATH_LITERAL("\\"), FILE_PATH_LITERAL("%5C")); #endif @@ -165,7 +166,7 @@ "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "clock$"}; #if defined(OS_WIN) std::string filename_lower = base::ToLowerASCII(base::WideToUTF8(filename)); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) std::string filename_lower = base::ToLowerASCII(filename); #endif
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc index 6cb28e7..bf7a6a9 100644 --- a/net/base/filename_util_internal.cc +++ b/net/base/filename_util_internal.cc
@@ -11,6 +11,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "build/build_config.h" #include "net/base/escape.h" #include "net/base/filename_util_internal.h" #include "net/base/mime_util.h" @@ -88,8 +89,10 @@ filename->resize((pos == std::string::npos) ? 0 : (pos + 1)); #if defined(OS_WIN) base::TrimWhitespace(*filename, base::TRIM_TRAILING, filename); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) base::TrimWhitespaceASCII(*filename, base::TRIM_TRAILING, filename); +#else +#error Unsupported platform #endif if (filename->empty()) @@ -207,7 +210,7 @@ #if defined(OS_WIN) *converted = path.value(); return true; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) std::string component8 = path.AsUTF8Unsafe(); return !component8.empty() && base::UTF8ToUTF16(component8.c_str(), component8.size(), converted); @@ -265,9 +268,11 @@ replace_trailing = true; result_str = base::UTF8ToUTF16(filename); default_name_str = base::UTF8ToUTF16(default_name); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) result_str = filename; default_name_str = default_name; +#else +#error Unsupported platform #endif SanitizeGeneratedFileName(&result_str, replace_trailing); if (result_str.find_last_not_of(FILE_PATH_LITERAL("-_")) == @@ -312,7 +317,7 @@ #if defined(OS_WIN) base::FilePath generated_name(file_name); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) base::FilePath generated_name( base::SysWideToNativeMB(base::UTF16ToWide(file_name))); #endif
diff --git a/net/base/filename_util_unittest.cc b/net/base/filename_util_unittest.cc index 5b40aee..f7a4c152 100644 --- a/net/base/filename_util_unittest.cc +++ b/net/base/filename_util_unittest.cc
@@ -38,20 +38,22 @@ std::wstring FilePathAsWString(const base::FilePath& path) { #if defined(OS_WIN) return path.value(); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) return base::UTF8ToWide(path.value()); #endif } base::FilePath WStringAsFilePath(const std::wstring& str) { #if defined(OS_WIN) return base::FilePath(str); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) return base::FilePath(base::WideToUTF8(str)); #endif } std::string GetLocaleWarningString() { -#if defined(OS_POSIX) && !defined(OS_ANDROID) +#if defined(OS_WIN) || defined(OS_ANDROID) + return ""; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // The generate filename tests can fail on certain OS_POSIX platforms when // LC_CTYPE is not "utf8" or "utf-8" because some of the string conversions // fail. @@ -64,8 +66,6 @@ return " this test may have failed because the current LC_CTYPE locale is " "not utf8 (currently set to " + locale + ")"; -#else - return ""; #endif } @@ -108,7 +108,7 @@ FILE_PATH_LITERAL(" Computer"), FILE_PATH_LITERAL("My Computer.{a}"), FILE_PATH_LITERAL("My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), -#if !defined(OS_WIN) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) FILE_PATH_LITERAL("a\\a"), #endif }; @@ -195,7 +195,7 @@ "%E9%A1%B5.doc"}, {L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt", // Math alphabet "AB" "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"}, -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) {L"/foo/bar.txt", "file:///foo/bar.txt"}, {L"/foo/BAR.txt", "file:///foo/BAR.txt"}, {L"/C:/foo/bar.txt", "file:///C:/foo/bar.txt"}, @@ -240,7 +240,7 @@ // %2f ('/') and %5c ('\\') are left alone by both GURL and // FileURLToFilePath. {L"C:\\foo%2f..%5cbar", "file:///C:\\foo%2f..%5cbar"}, -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) {L"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"}, {L"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"}, {L"/foo/bar.txt", "file:/foo/bar.txt"}, @@ -317,7 +317,7 @@ // Dangerous extensions {__LINE__, "text/html", "harmless.local", "harmless.download"}, {__LINE__, "text/html", "harmless.lnk", "harmless.download"}, -#else // OS_WIN +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // On Posix, none of the above set is particularly dangerous. {__LINE__, "text/html", "con.htm", "con.htm"}, {__LINE__, "text/html", "lpt1.htm", "lpt1.htm"}, @@ -327,12 +327,12 @@ {__LINE__, "text/html", "harmless.{mismatched-", "harmless.{mismatched-"}, {__LINE__, "text/html", "harmless.local", "harmless.local"}, {__LINE__, "text/html", "harmless.lnk", "harmless.lnk"}, -#endif // !defined(OS_WIN) +#endif // defined(OS_WIN) }; #if defined(OS_WIN) base::FilePath base_path(L"C:\\foo"); -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) base::FilePath base_path("/foo"); #endif @@ -549,7 +549,7 @@ L"evil_"}, {__LINE__, "", "filename=. . . . .", "", "", "binary/octet-stream", L"download", L"download"}, -#else // OS_WIN +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // Test truncation of trailing dots and spaces (non-Windows) {__LINE__, "", "filename=evil.exe ", "", "", "binary/octet-stream", L"download", L"evil.exe"},
diff --git a/net/base/iovec.h b/net/base/iovec.h index 61e2593..50bf791 100644 --- a/net/base/iovec.h +++ b/net/base/iovec.h
@@ -9,14 +9,14 @@ #include "build/build_config.h" -#if defined(OS_POSIX) && !defined(OS_NACL) -#include <sys/uio.h> -#else +#if defined(OS_WIN) || defined(OS_NACL) /* Structure for scatter/gather I/O. */ struct iovec { void* iov_base; /* Pointer to data. */ size_t iov_len; /* Length of data. */ }; -#endif // defined(OS_POSIX) && !defined(OS_NACL) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <sys/uio.h> +#endif // defined(OS_WIN) || defined(OS_NACL) #endif // NET_BASE_IOVEC_H_
diff --git a/net/base/network_interfaces_fuchsia.cc b/net/base/network_interfaces_fuchsia.cc index 947cd83..f535143 100644 --- a/net/base/network_interfaces_fuchsia.cc +++ b/net/base/network_interfaces_fuchsia.cc
@@ -11,7 +11,7 @@ namespace net { -IPAddress NetAddressToIPAddress(const netstack::NetAddress& addr) { +IPAddress NetAddressToIPAddress(const fuchsia::netstack::NetAddress& addr) { if (addr.ipv4) { return IPAddress(addr.ipv4->addr.data(), addr.ipv4->addr.count()); } @@ -22,25 +22,25 @@ } bool GetNetworkList(NetworkInterfaceList* networks, int policy) { - netstack::NetstackSyncPtr netstack = + fuchsia::netstack::NetstackSyncPtr netstack = base::fuchsia::ComponentContext::GetDefault() - ->ConnectToServiceSync<netstack::Netstack>(); + ->ConnectToServiceSync<fuchsia::netstack::Netstack>(); - fidl::VectorPtr<netstack::NetInterface> interfaces; + fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces; if (!netstack->GetInterfaces(&interfaces)) return false; for (auto& interface : interfaces.get()) { // Check if the interface is up. - if (!(interface.flags & netstack::NetInterfaceFlagUp)) + if (!(interface.flags & fuchsia::netstack::NetInterfaceFlagUp)) continue; // Skip loopback. - if (interface.features & netstack::interfaceFeatureLoopback) + if (interface.features & fuchsia::netstack::interfaceFeatureLoopback) continue; NetworkChangeNotifier::ConnectionType connection_type = - (interface.features & netstack::interfaceFeatureWlan) + (interface.features & fuchsia::netstack::interfaceFeatureWlan) ? NetworkChangeNotifier::CONNECTION_WIFI : NetworkChangeNotifier::CONNECTION_UNKNOWN;
diff --git a/net/base/sockaddr_storage.h b/net/base/sockaddr_storage.h index cc31231..04fa5847 100644 --- a/net/base/sockaddr_storage.h +++ b/net/base/sockaddr_storage.h
@@ -7,12 +7,12 @@ #include "build/build_config.h" -#if defined(OS_POSIX) -#include <sys/socket.h> -#include <sys/types.h> -#elif defined(OS_WIN) +#if defined(OS_WIN) #include <winsock2.h> #include <ws2tcpip.h> +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <sys/socket.h> +#include <sys/types.h> #endif #include "net/base/net_export.h"
diff --git a/net/base/sys_addrinfo.h b/net/base/sys_addrinfo.h index 1799fc2d..e817ad5 100644 --- a/net/base/sys_addrinfo.h +++ b/net/base/sys_addrinfo.h
@@ -22,7 +22,7 @@ #if defined(OS_WIN) #include <ws2tcpip.h> -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h>
diff --git a/net/cert/ct_policy_enforcer.cc b/net/cert/ct_policy_enforcer.cc index 0f77780..4749c19 100644 --- a/net/cert/ct_policy_enforcer.cc +++ b/net/cert/ct_policy_enforcer.cc
@@ -4,302 +4,15 @@ #include "net/cert/ct_policy_enforcer.h" -#include <stdint.h> - -#include <algorithm> -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/build_time.h" -#include "base/callback_helpers.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram_macros.h" -#include "base/numerics/safe_conversions.h" -#include "base/strings/string_number_conversions.h" -#include "base/time/time.h" -#include "base/values.h" -#include "base/version.h" -#include "net/cert/ct_known_logs.h" #include "net/cert/ct_policy_status.h" -#include "net/cert/ct_verify_result.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/x509_certificate.h" -#include "net/cert/x509_certificate_net_log_param.h" -#include "net/log/net_log_capture_mode.h" -#include "net/log/net_log_event_type.h" -#include "net/log/net_log_parameters_callback.h" -#include "net/log/net_log_with_source.h" namespace net { -namespace { - -// Returns true if the current build is recent enough to ensure that -// built-in security information (e.g. CT Logs) is fresh enough. -// TODO(eranm): Move to base or net/base -bool IsBuildTimely() { - const base::Time build_time = base::GetBuildTime(); - // We consider built-in information to be timely for 10 weeks. - return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; -} - -// Returns a rounded-down months difference of |start| and |end|, -// together with an indication of whether the last month was -// a full month, because the range starts specified in the policy -// are not consistent in terms of including the range start value. -void RoundedDownMonthDifference(const base::Time& start, - const base::Time& end, - size_t* rounded_months_difference, - bool* has_partial_month) { - DCHECK(rounded_months_difference); - DCHECK(has_partial_month); - base::Time::Exploded exploded_start; - base::Time::Exploded exploded_expiry; - start.UTCExplode(&exploded_start); - end.UTCExplode(&exploded_expiry); - if (end < start) { - *rounded_months_difference = 0; - *has_partial_month = false; - return; - } - - *has_partial_month = true; - uint32_t month_diff = (exploded_expiry.year - exploded_start.year) * 12 + - (exploded_expiry.month - exploded_start.month); - if (exploded_expiry.day_of_month < exploded_start.day_of_month) - --month_diff; - else if (exploded_expiry.day_of_month == exploded_start.day_of_month) - *has_partial_month = false; - - *rounded_months_difference = month_diff; -} - -const char* CTPolicyComplianceToString(ct::CTPolicyCompliance status) { - switch (status) { - case ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS: - return "COMPLIES_VIA_SCTS"; - case ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS: - return "NOT_ENOUGH_SCTS"; - case ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS: - return "NOT_DIVERSE_SCTS"; - case ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY: - return "BUILD_NOT_TIMELY"; - case ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE: - case ct::CTPolicyCompliance::CT_POLICY_MAX: - NOTREACHED(); - return "unknown"; - } - - NOTREACHED(); - return "unknown"; -} - -std::unique_ptr<base::Value> NetLogCertComplianceCheckResultCallback( - X509Certificate* cert, - bool build_timely, - ct::CTPolicyCompliance compliance, - NetLogCaptureMode capture_mode) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); - dict->SetBoolean("build_timely", build_timely); - dict->SetString("ct_compliance_status", - CTPolicyComplianceToString(compliance)); - return std::move(dict); -} - -// Evaluates against the policy specified at -// https://sites.google.com/a/chromium.org/dev/Home/chromium-security/root-ca-policy/EVCTPlanMay2015edition.pdf?attredirects=0 -ct::CTPolicyCompliance CheckCTPolicyCompliance( - const X509Certificate& cert, - const ct::SCTList& verified_scts) { - // Cert is outside the bounds of parsable; reject it. - if (cert.valid_start().is_null() || cert.valid_expiry().is_null() || - cert.valid_start().is_max() || cert.valid_expiry().is_max()) { - return ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; - } - - // Scan for the earliest SCT. This is used to determine whether to enforce - // log diversity requirements, as well as whether to enforce whether or not - // a log was qualified or pending qualification at time of issuance (in the - // case of embedded SCTs). It's acceptable to ignore the origin of the SCT, - // because SCTs delivered via OCSP/TLS extension will cover the full - // certificate, which necessarily will exist only after the precertificate - // has been logged and the actual certificate issued. - // Note: Here, issuance date is defined as the earliest of all SCTs, rather - // than the latest of embedded SCTs, in order to give CAs the benefit of - // the doubt in the event a log is revoked in the midst of processing - // a precertificate and issuing the certificate. - base::Time issuance_date = base::Time::Max(); - for (const auto& sct : verified_scts) { - base::Time unused; - if (ct::IsLogDisqualified(sct->log_id, &unused)) - continue; - issuance_date = std::min(sct->timestamp, issuance_date); - } - - bool has_valid_google_sct = false; - bool has_valid_nongoogle_sct = false; - bool has_valid_embedded_sct = false; - bool has_valid_nonembedded_sct = false; - bool has_embedded_google_sct = false; - bool has_embedded_nongoogle_sct = false; - std::vector<base::StringPiece> embedded_log_ids; - for (const auto& sct : verified_scts) { - base::Time disqualification_date; - bool is_disqualified = - ct::IsLogDisqualified(sct->log_id, &disqualification_date); - if (is_disqualified && - sct->origin != ct::SignedCertificateTimestamp::SCT_EMBEDDED) { - // For OCSP and TLS delivered SCTs, only SCTs that are valid at the - // time of check are accepted. - continue; - } - - if (ct::IsLogOperatedByGoogle(sct->log_id)) { - has_valid_google_sct |= !is_disqualified; - if (sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED) - has_embedded_google_sct = true; - } else { - has_valid_nongoogle_sct |= !is_disqualified; - if (sct->origin == ct::SignedCertificateTimestamp::SCT_EMBEDDED) - has_embedded_nongoogle_sct = true; - } - if (sct->origin != ct::SignedCertificateTimestamp::SCT_EMBEDDED) { - has_valid_nonembedded_sct = true; - } else { - has_valid_embedded_sct |= !is_disqualified; - // If the log is disqualified, it only counts towards quorum if - // the certificate was issued before the log was disqualified, and the - // SCT was obtained before the log was disqualified. - if (!is_disqualified || (issuance_date < disqualification_date && - sct->timestamp < disqualification_date)) { - embedded_log_ids.push_back(sct->log_id); - } - } - } - - // Option 1: - // An SCT presented via the TLS extension OR embedded within a stapled OCSP - // response is from a log qualified at time of check; - // AND there is at least one SCT from a Google Log that is qualified at - // time of check, presented via any method; - // AND there is at least one SCT from a non-Google Log that is qualified - // at the time of check, presented via any method. - // - // Note: Because SCTs embedded via TLS or OCSP can be updated on the fly, - // the issuance date is irrelevant, as any policy changes can be - // accomodated. - if (has_valid_nonembedded_sct && has_valid_google_sct && - has_valid_nongoogle_sct) { - return ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } - // Note: If has_valid_nonembedded_sct was true, but Option 2 isn't met, - // then the result will be that there weren't diverse enough SCTs, as that - // the only other way for the conditional above to fail). Because Option 1 - // has the diversity requirement, it's implicitly a minimum number of SCTs - // (specifically, 2), but that's not explicitly specified in the policy. - - // Option 2: - // There is at least one embedded SCT from a log qualified at the time of - // check ... - if (!has_valid_embedded_sct) { - // Under Option 2, there weren't enough SCTs, and potentially under - // Option 1, there weren't diverse enough SCTs. Try to signal the error - // that is most easily fixed. - return has_valid_nonembedded_sct - ? ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS - : ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; - } - - // ... AND there is at least one embedded SCT from a Google Log once or - // currently qualified; - // AND there is at least one embedded SCT from a non-Google Log once or - // currently qualified; - // ... - // - // Note: This policy language is only enforced after the below issuance - // date, as that's when the diversity policy first came into effect for - // SCTs embedded in certificates. - // The date when diverse SCTs requirement is effective from. - // 2015-07-01 00:00:00 UTC. - const base::Time kDiverseSCTRequirementStartDate = - base::Time::FromInternalValue(INT64_C(13080182400000000)); - if (issuance_date >= kDiverseSCTRequirementStartDate && - !(has_embedded_google_sct && has_embedded_nongoogle_sct)) { - // Note: This also covers the case for non-embedded SCTs, as it's only - // possible to reach here if both sets are not diverse enough. - return ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS; - } - - size_t lifetime_in_months = 0; - bool has_partial_month = false; - RoundedDownMonthDifference(cert.valid_start(), cert.valid_expiry(), - &lifetime_in_months, &has_partial_month); - - // ... AND the certificate embeds SCTs from AT LEAST the number of logs - // once or currently qualified shown in Table 1 of the CT Policy. - size_t num_required_embedded_scts = 5; - if (lifetime_in_months > 39 || - (lifetime_in_months == 39 && has_partial_month)) { - num_required_embedded_scts = 5; - } else if (lifetime_in_months > 27 || - (lifetime_in_months == 27 && has_partial_month)) { - num_required_embedded_scts = 4; - } else if (lifetime_in_months >= 15) { - num_required_embedded_scts = 3; - } else { - num_required_embedded_scts = 2; - } - - // Sort the embedded log IDs and remove duplicates, so that only a single - // SCT from each log is accepted. This is to handle the case where a given - // log returns different SCTs for the same precertificate (which is - // permitted, but advised against). - std::sort(embedded_log_ids.begin(), embedded_log_ids.end()); - auto sorted_end = - std::unique(embedded_log_ids.begin(), embedded_log_ids.end()); - size_t num_embedded_scts = - std::distance(embedded_log_ids.begin(), sorted_end); - - if (num_embedded_scts >= num_required_embedded_scts) - return ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - - // Under Option 2, there weren't enough SCTs, and potentially under Option - // 1, there weren't diverse enough SCTs. Try to signal the error that is - // most easily fixed. - return has_valid_nonembedded_sct - ? ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS - : ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS; -} - -} // namespace - -ct::CTPolicyCompliance CTPolicyEnforcer::CheckCompliance( +ct::CTPolicyCompliance DefaultCTPolicyEnforcer::CheckCompliance( X509Certificate* cert, const ct::SCTList& verified_scts, const NetLogWithSource& net_log) { - // If the build is not timely, no certificate is considered compliant - // with CT policy. The reasoning is that, for example, a log might - // have been pulled and is no longer considered valid; thus, a client - // needs up-to-date information about logs to consider certificates to - // be compliant with policy. - bool build_timely = IsBuildTimely(); - ct::CTPolicyCompliance compliance; - if (!build_timely) { - compliance = ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY; - } else { - compliance = CheckCTPolicyCompliance(*cert, verified_scts); - } - - NetLogParametersCallback net_log_callback = - base::Bind(&NetLogCertComplianceCheckResultCallback, - base::Unretained(cert), build_timely, compliance); - - net_log.AddEvent(NetLogEventType::CERT_CT_COMPLIANCE_CHECKED, - net_log_callback); - - return compliance; + return ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY; } } // namespace net
diff --git a/net/cert/ct_policy_enforcer.h b/net/cert/ct_policy_enforcer.h index fb6f4847..371d71bc 100644 --- a/net/cert/ct_policy_enforcer.h +++ b/net/cert/ct_policy_enforcer.h
@@ -16,21 +16,19 @@ class NetLogWithSource; namespace ct { - enum class CTPolicyCompliance; - } // namespace ct class X509Certificate; -using SCTList = std::vector<scoped_refptr<ct::SignedCertificateTimestamp>>; - -// Class for checking that a given certificate conforms to -// Certificate Transparency-related policies. +// Interface for checking whether or not a given certificate conforms to any +// policies an application may have regarding Certificate Transparency. +// +// See //net/docs/certificate-transparency.md for more details regarding the +// usage of CT in //net and risks that may exist when defining a CT policy. class NET_EXPORT CTPolicyEnforcer { public: - CTPolicyEnforcer() {} - virtual ~CTPolicyEnforcer() {} + virtual ~CTPolicyEnforcer() = default; // Returns the CT certificate policy compliance status for a given // certificate and collection of SCTs. @@ -40,8 +38,23 @@ // |applying to |cert|). virtual ct::CTPolicyCompliance CheckCompliance( X509Certificate* cert, - const SCTList& verified_scts, - const NetLogWithSource& net_log); + const ct::SCTList& verified_scts, + const NetLogWithSource& net_log) = 0; +}; + +// A default implementation of Certificate Transparency policies that is +// intended for use in applications without auto-update capabilities. +// +// See //net/docs/certificate-transparency.md for more details. +class NET_EXPORT DefaultCTPolicyEnforcer : public net::CTPolicyEnforcer { + public: + DefaultCTPolicyEnforcer() = default; + ~DefaultCTPolicyEnforcer() override = default; + + ct::CTPolicyCompliance CheckCompliance( + X509Certificate* cert, + const ct::SCTList& verified_scts, + const NetLogWithSource& net_log) override; }; } // namespace net
diff --git a/net/cert/ct_verify_result.h b/net/cert/ct_verify_result.h index 4d7ad4f..742ec65 100644 --- a/net/cert/ct_verify_result.h +++ b/net/cert/ct_verify_result.h
@@ -8,7 +8,6 @@ #include <vector> #include "net/base/net_export.h" -#include "net/cert/ct_policy_enforcer.h" #include "net/cert/signed_certificate_timestamp_and_status.h" namespace net { @@ -17,8 +16,6 @@ enum class CTPolicyCompliance; -typedef std::vector<scoped_refptr<SignedCertificateTimestamp> > SCTList; - // Holds Signed Certificate Timestamps, depending on their verification // results, and information about CT policies that were applied on the // connection.
diff --git a/net/cert/signed_certificate_timestamp.h b/net/cert/signed_certificate_timestamp.h index a23b708..ed0743a 100644 --- a/net/cert/signed_certificate_timestamp.h +++ b/net/cert/signed_certificate_timestamp.h
@@ -61,7 +61,7 @@ // Helper structure to represent Digitally Signed data, as described in // Sections 4.7 and 7.4.1.4.1 of RFC 5246. -struct NET_EXPORT_PRIVATE DigitallySigned { +struct NET_EXPORT DigitallySigned { enum HashAlgorithm { HASH_ALGO_NONE = 0, HASH_ALGO_MD5 = 1, @@ -145,6 +145,8 @@ DISALLOW_COPY_AND_ASSIGN(SignedCertificateTimestamp); }; +using SCTList = std::vector<scoped_refptr<ct::SignedCertificateTimestamp>>; + } // namespace ct } // namespace net
diff --git a/net/cert/x509_certificate_net_log_param.h b/net/cert/x509_certificate_net_log_param.h index a6721ab4..ecde73c 100644 --- a/net/cert/x509_certificate_net_log_param.h +++ b/net/cert/x509_certificate_net_log_param.h
@@ -7,6 +7,8 @@ #include <memory> +#include "net/base/net_export.h" + namespace base { class Value; } @@ -17,7 +19,7 @@ class X509Certificate; // Creates NetLog parameter to describe an X509Certificate. -std::unique_ptr<base::Value> NetLogX509CertificateCallback( +NET_EXPORT std::unique_ptr<base::Value> NetLogX509CertificateCallback( const X509Certificate* certificate, NetLogCaptureMode capture_mode);
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc index fbf112b..84ef95f88 100644 --- a/net/cert_net/cert_net_fetcher_impl_unittest.cc +++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -53,7 +53,8 @@ std::make_unique<TransportSecurityState>()); storage_.set_cert_transparency_verifier( std::make_unique<MultiLogCTVerifier>()); - storage_.set_ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>()); + storage_.set_ct_policy_enforcer( + std::make_unique<DefaultCTPolicyEnforcer>()); storage_.set_proxy_resolution_service(ProxyResolutionService::CreateFixed( ProxyConfigWithAnnotation(no_proxy, TRAFFIC_ANNOTATION_FOR_TESTS))); storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
diff --git a/net/disk_cache/cache_util.cc b/net/disk_cache/cache_util.cc index fa18675..8cd39bf 100644 --- a/net/disk_cache/cache_util.cc +++ b/net/disk_cache/cache_util.cc
@@ -14,6 +14,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task_scheduler/post_task.h" #include "base/threading/thread_restrictions.h" +#include "build/build_config.h" namespace { @@ -117,11 +118,11 @@ base::FilePath path = current_path.DirName(); base::FilePath name = current_path.BaseName(); -#if defined(OS_POSIX) - std::string name_str = name.value(); -#elif defined(OS_WIN) +#if defined(OS_WIN) // We created this file so it should only contain ASCII. std::string name_str = base::UTF16ToASCII(name.value()); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + std::string name_str = name.value(); #endif base::FilePath to_delete = GetTempCacheName(path, name_str);
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index 2b68396..a238ecb 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -6,11 +6,8 @@ #if defined(OS_WIN) #include <Winsock2.h> -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <netdb.h> -#endif - -#if defined(OS_POSIX) #include <netinet/in.h> #if !defined(OS_NACL) #include <net/if.h> @@ -18,7 +15,7 @@ #include <ifaddrs.h> #endif // !defined(OS_ANDROID) #endif // !defined(OS_NACL) -#endif // defined(OS_POSIX) +#endif // defined(OS_WIN) #include <cmath> #include <memory> @@ -48,6 +45,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "base/values.h" +#include "build/build_config.h" #include "net/base/address_family.h" #include "net/base/address_list.h" #include "net/base/host_port_pair.h" @@ -124,7 +122,7 @@ "Net.OSErrorsForGetAddrinfo_Mac"; #elif defined(OS_LINUX) "Net.OSErrorsForGetAddrinfo_Linux"; -#else +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) "Net.OSErrorsForGetAddrinfo"; #endif @@ -133,7 +131,21 @@ // a histogram. std::vector<int> GetAllGetAddrinfoOSErrors() { int os_errors[] = { -#if defined(OS_POSIX) +#if defined(OS_WIN) + // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx + WSA_NOT_ENOUGH_MEMORY, + WSAEAFNOSUPPORT, + WSAEINVAL, + WSAESOCKTNOSUPPORT, + WSAHOST_NOT_FOUND, + WSANO_DATA, + WSANO_RECOVERY, + WSANOTINITIALISED, + WSATRY_AGAIN, + WSATYPE_NOT_FOUND, + // The following are not in doc, but might be to appearing in results :-(. + WSA_INVALID_HANDLE, +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #if !defined(OS_FREEBSD) #if !defined(OS_ANDROID) // EAI_ADDRFAMILY has been declared obsolete in Android's and @@ -152,20 +164,6 @@ EAI_SERVICE, EAI_SOCKTYPE, EAI_SYSTEM, -#elif defined(OS_WIN) - // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx - WSA_NOT_ENOUGH_MEMORY, - WSAEAFNOSUPPORT, - WSAEINVAL, - WSAESOCKTNOSUPPORT, - WSAHOST_NOT_FOUND, - WSANO_DATA, - WSANO_RECOVERY, - WSANOTINITIALISED, - WSATRY_AGAIN, - WSATYPE_NOT_FOUND, - // The following are not in doc, but might be to appearing in results :-(. - WSA_INVALID_HANDLE, #endif }; @@ -333,12 +331,16 @@ // Also returns false if it cannot determine this. bool HaveOnlyLoopbackAddresses() { base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::WILL_BLOCK); -#if defined(OS_ANDROID) +#if defined(OS_WIN) + // TODO(wtc): implement with the GetAdaptersAddresses function. + NOTIMPLEMENTED(); + return false; +#elif defined(OS_ANDROID) return android::HaveOnlyLoopbackAddresses(); #elif defined(OS_NACL) NOTIMPLEMENTED(); return false; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) struct ifaddrs* interface_addr = NULL; int rv = getifaddrs(&interface_addr); if (rv != 0) { @@ -373,13 +375,6 @@ } freeifaddrs(interface_addr); return result; -#elif defined(OS_WIN) - // TODO(wtc): implement with the GetAdaptersAddresses function. - NOTIMPLEMENTED(); - return false; -#else - NOTIMPLEMENTED(); - return false; #endif // defined(various platforms) } @@ -397,9 +392,7 @@ if (os_error) { dict->SetInteger("os_error", os_error); -#if defined(OS_POSIX) - dict->SetString("os_error_string", gai_strerror(os_error)); -#elif defined(OS_WIN) +#if defined(OS_WIN) // Map the error code to a human-readable string. LPWSTR error_string = nullptr; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, @@ -411,6 +404,8 @@ 0); // Arguments (unused). dict->SetString("os_error_string", base::WideToUTF8(error_string)); LocalFree(error_string); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + dict->SetString("os_error_string", gai_strerror(os_error)); #endif } @@ -1999,12 +1994,14 @@ #if defined(OS_WIN) EnsureWinsockInit(); #endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) +#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \ + defined(OS_FUCHSIA) RunLoopbackProbeJob(); #endif NetworkChangeNotifier::AddIPAddressObserver(this); NetworkChangeNotifier::AddConnectionTypeObserver(this); NetworkChangeNotifier::AddDNSObserver(this); +// TODO(crbug/836416): Remove OS_FUCHSIA here. #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ !defined(OS_ANDROID) && !defined(OS_FUCHSIA) EnsureDnsReloaderInit(); @@ -2525,7 +2522,8 @@ probe_weak_ptr_factory_.InvalidateWeakPtrs(); if (cache_.get()) cache_->OnNetworkChange(); -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) +#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \ + defined(OS_FUCHSIA) RunLoopbackProbeJob(); #endif AbortAllInProgressJobs();
diff --git a/net/http/http_auth_preferences.cc b/net/http/http_auth_preferences.cc index 10815d1..9b532d1e 100644 --- a/net/http/http_auth_preferences.cc +++ b/net/http/http_auth_preferences.cc
@@ -17,7 +17,7 @@ HttpAuthPreferences::HttpAuthPreferences() : HttpAuthPreferences(std::vector<std::string>()) {} -#if defined(OS_POSIX) && !defined(OS_ANDROID) +#if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) HttpAuthPreferences::HttpAuthPreferences( const std::vector<std::string>& auth_schemes) : HttpAuthPreferences(auth_schemes, @@ -35,7 +35,7 @@ #if defined(OS_CHROMEOS) , bool allow_gssapi_library_load -#elif defined(OS_POSIX) && !defined(OS_ANDROID) +#elif (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) , const std::string& gssapi_library_name #endif @@ -48,7 +48,7 @@ #endif #if defined(OS_CHROMEOS) allow_gssapi_library_load_(allow_gssapi_library_load), -#elif defined(OS_POSIX) && !defined(OS_ANDROID) +#elif (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) gssapi_library_name_(gssapi_library_name), #endif security_manager_(URLSecurityManager::Create()) { @@ -68,7 +68,7 @@ return negotiate_enable_port_; } -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) bool HttpAuthPreferences::NtlmV2Enabled() const { return ntlm_v2_enabled_; } @@ -82,7 +82,7 @@ bool HttpAuthPreferences::AllowGssapiLibraryLoad() const { return allow_gssapi_library_load_; } -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) std::string HttpAuthPreferences::GssapiLibraryName() const { return gssapi_library_name_; }
diff --git a/net/http/http_auth_preferences.h b/net/http/http_auth_preferences.h index 1802765f..372e7e8 100644 --- a/net/http/http_auth_preferences.h +++ b/net/http/http_auth_preferences.h
@@ -27,7 +27,7 @@ // |allow_gssapi_library_load| set to true. HttpAuthPreferences(); -#if defined(OS_POSIX) && !defined(OS_ANDROID) +#if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) // Simplified ctor with empty |gssapi_library_name| and // |allow_gssapi_library_load| set to true. // On platforms where this is not available, the ctor below is already @@ -39,7 +39,7 @@ #if defined(OS_CHROMEOS) , bool allow_gssapi_library_load -#elif defined(OS_POSIX) && !defined(OS_ANDROID) +#elif (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) , const std::string& gssapi_library_name #endif @@ -49,14 +49,14 @@ virtual bool IsSupportedScheme(const std::string& scheme) const; virtual bool NegotiateDisableCnameLookup() const; virtual bool NegotiateEnablePort() const; -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) virtual bool NtlmV2Enabled() const; #endif #if defined(OS_ANDROID) virtual std::string AuthAndroidNegotiateAccountType() const; #elif defined(OS_CHROMEOS) virtual bool AllowGssapiLibraryLoad() const; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) virtual std::string GssapiLibraryName() const; #endif virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const; @@ -70,7 +70,7 @@ negotiate_enable_port_ = negotiate_enable_port; } -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) void set_ntlm_v2_enabled(bool ntlm_v2_enabled) { ntlm_v2_enabled_ = ntlm_v2_enabled; } @@ -94,7 +94,7 @@ bool negotiate_disable_cname_lookup_; bool negotiate_enable_port_; -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) bool ntlm_v2_enabled_; #endif @@ -102,7 +102,7 @@ std::string auth_android_negotiate_account_type_; #elif defined(OS_CHROMEOS) const bool allow_gssapi_library_load_; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // GSSAPI library name cannot change after startup, since changing it // requires unloading the existing GSSAPI library, which could cause all // sorts of problems for, for example, active Negotiate transactions.
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index c73d5ba..eaf1502 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc
@@ -267,7 +267,7 @@ std::unique_ptr<CertVerifier> cert_verifier_; std::unique_ptr<TransportSecurityState> transport_security_state_; MultiLogCTVerifier ct_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; const scoped_refptr<SSLConfigService> ssl_config_service_; std::unique_ptr<HttpNetworkSession> network_session_;
diff --git a/net/http/http_network_transaction_ssl_unittest.cc b/net/http/http_network_transaction_ssl_unittest.cc index fe5c4fb..9d678d7 100644 --- a/net/http/http_network_transaction_ssl_unittest.cc +++ b/net/http/http_network_transaction_ssl_unittest.cc
@@ -99,7 +99,7 @@ MockCertVerifier cert_verifier_; TransportSecurityState transport_security_state_; MultiLogCTVerifier ct_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; HttpNetworkSession::Context session_context_; std::vector<std::unique_ptr<HttpRequestInfo>> request_info_vector_; };
diff --git a/net/http/http_proxy_client_socket_wrapper_unittest.cc b/net/http/http_proxy_client_socket_wrapper_unittest.cc index 0131c08..8e2568c 100644 --- a/net/http/http_proxy_client_socket_wrapper_unittest.cc +++ b/net/http/http_proxy_client_socket_wrapper_unittest.cc
@@ -8,6 +8,7 @@ #include <memory> #include "build/build_config.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cert/do_nothing_ct_verifier.h" #include "net/cert/mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" @@ -210,7 +211,7 @@ MockTaggingClientSocketFactory socket_factory_; HttpServerPropertiesImpl http_server_properties_; std::unique_ptr<MockCertVerifier> cert_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; std::unique_ptr<ChannelIDService> channel_id_service_; TransportSecurityState transport_security_state_; std::unique_ptr<DoNothingCTVerifier> cert_transparency_verifier_;
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc index 0a7d2b1..4525ca2 100644 --- a/net/http/http_response_body_drainer_unittest.cc +++ b/net/http/http_response_body_drainer_unittest.cc
@@ -265,7 +265,7 @@ MockCertVerifier cert_verifier_; TransportSecurityState transport_security_state_; MultiLogCTVerifier ct_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; const std::unique_ptr<HttpNetworkSession> session_; CloseResultWaiter result_waiter_; MockHttpStream* const mock_stream_; // Owned by |drainer_|.
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index cd4ced5..00fca6d 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc
@@ -831,7 +831,7 @@ session_context.transport_security_state = &transport_security_state; MultiLogCTVerifier ct_verifier; session_context.cert_transparency_verifier = &ct_verifier; - CTPolicyEnforcer ct_policy_enforcer; + DefaultCTPolicyEnforcer ct_policy_enforcer; session_context.ct_policy_enforcer = &ct_policy_enforcer; session_context.proxy_resolution_service = proxy_resolution_service.get(); session_context.ssl_config_service = ssl_config_service.get(); @@ -997,7 +997,7 @@ TestProxyDelegate test_proxy_delegate; HttpServerPropertiesImpl http_server_properties; MockCertVerifier cert_verifier; - CTPolicyEnforcer ct_policy_enforcer; + DefaultCTPolicyEnforcer ct_policy_enforcer; MultiLogCTVerifier ct_verifier; scoped_refptr<SSLConfigServiceDefaults> ssl_config_service( new SSLConfigServiceDefaults); @@ -1112,7 +1112,7 @@ TestProxyDelegate test_proxy_delegate; HttpServerPropertiesImpl http_server_properties; MockCertVerifier cert_verifier; - CTPolicyEnforcer ct_policy_enforcer; + DefaultCTPolicyEnforcer ct_policy_enforcer; MultiLogCTVerifier ct_verifier; scoped_refptr<SSLConfigServiceDefaults> ssl_config_service( @@ -2468,7 +2468,7 @@ HttpServerPropertiesImpl http_server_properties_; TransportSecurityState transport_security_state_; MultiLogCTVerifier ct_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; MockHostResolver host_resolver_; std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 44ba3ab..aa1a289 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -30736,7 +30736,6 @@ { "name": "mireillewendling.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "moojp.co.jp", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "momstableonline.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "motosikletevi.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "miguelmartinez.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "monteurzimmerfrei.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "moreserviceleads.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -40857,7 +40856,6 @@ { "name": "wtw.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wyu.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xianguocy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "xtreme-servers.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xuntaosms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yallamotor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yhwj.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -41319,7 +41317,6 @@ { "name": "semaphore-studios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sergefonville.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "servers4all.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "sh0rt.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "shellj.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "shellshock.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "shoxmusic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -46055,7 +46052,6 @@ { "name": "caryefurd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "catalogobiblioteca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cb-crochet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "cbmusa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cd5k.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cdasenegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cedricmartineau.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -49385,7 +49381,6 @@ { "name": "beimchristoph.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "berhampore-gateway.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bitcoinfo.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "brctec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "brplusdigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bsg.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bsgamanet.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -49637,6 +49632,810 @@ { "name": "zhuji5.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zx1168.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zx2268.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "00dani.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "101.qa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "123writings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "12thmanrising.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "22digital.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "24dian30.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "24pcr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "288da.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2rsc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2rsc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "365propertybuyer.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "51845.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "73info.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "8hrs.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "8shequapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "97bros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "9won.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "a1moldsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "abilityone.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ableprop.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "accessoirescheveuxchic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acorntreecare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acoustics.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acrepairgeorgetown.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acrepairhutto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acrepairroundrocktx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acrolife.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "adsl2meg.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aei.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aereco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "affping.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "agingstats.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aginion.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "agliamici.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aide-admin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "akasha.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "akustik.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alasdelalma.com.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aldo-vandini.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alesia-formation.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alikulov.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alloverthehill.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "allstarquilts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aluoblog.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aluoblog.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amisderodin.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "andre-lategan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "angelremigene.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "anime-tip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "anthonyloop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "antifraud.net.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arrowfastener.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "artfullyelegant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "asoftwareco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aspectcontext.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "assistenzaferrodastiro.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "assistenzafrigorifero.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "athenadynamics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atimbertownservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atlasdev.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atsoftware.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aucielrose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "audioonly.stream", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "audiophix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "autocontrol.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "awningsatlantaga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ayanomimi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "azzurrapelletterie.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bahnhelden.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bamahammer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bandar303.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "barnel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "barpodsosnami.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "basementfinishingohio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "batch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bbj.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bednar.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "betterweb.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bezr.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "biehlsoft.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bifrost.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bigshort.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bijouxcherie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "binarization.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blockchainced.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bluerootsmarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bluestardiabetes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bokka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boltbeat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bonsaimedia.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bookingentertainment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boonehenry.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boote.wien", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bravebaby.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "briefassistant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "brouwerijkoelit.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "buileo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "buradangonder.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "businessplanexperts.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bwin8601.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bwin8602.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bwin8603.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bwin8604.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bwin8605.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bwin8606.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cachethome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cachetur.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cafedupont.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cajio.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "callmereda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "capacityproject.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "captivationtheory.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "carbon-project.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "celtadigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "century-group.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cernakova.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "certevia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cftc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "challstrom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "charlespitonltd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "charlotteswimmingpoolbuilder.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chartkick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cheapcaribbean.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chenkun.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "childstats.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "christopherandcharlotte.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ci-suite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cinay.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cineplex.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cintactimber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "clawhammer.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "clod-hacking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cnet-hosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "co-founder-stuttgart.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "codeandpeace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "codeproxy.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "codestep.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cognitip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "collegenavigator.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "collegeprospectsofcentralindiana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "comercialtpv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "comptrollerofthecurrency.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "concertsto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "concreterepairatlanta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "connexas.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "convertimg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "convoitises.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "corder.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "corpoflow.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cosciamoos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cougarsland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cr0nus.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "crawlspaceandbasementsolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cryptoegg.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cryptofrog.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cryptopro.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "crystalgrid.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cultureelbeleggen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "curarnosensalud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "custerweb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cvps.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cybit.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cygu.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cykelbanor.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d-macindustries.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d00r.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d3xx3r.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dak.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "damongant.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "damonline.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "danielhinterlechner.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "datalife.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dayofdays.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dearktiel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deckbuilderamerica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deelmijnreis.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "defcongroups.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "defendtheweb.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dekkercreativedesign.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "delandalucia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "derbuntering.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dermscc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deyute.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "didierghez.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "die-pizzabaeckerei.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "digital-liberal.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "digital.govt.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "diplona.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "directelectricalltd.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "discoveryaima.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "disinfestazioneblatte.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "disinfestazioni.bari.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dlz149.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dogadayiz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "doggedbyirs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dong8.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "doomus.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dougley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dpangerl.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dreamrae.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drei01.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dsyunmall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dunkle-seite.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "e-speak24.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "easyweenies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eat-mine.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ecir.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ecir.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ecofac-bs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "edenvaleplumber24-7.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "edh.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "egamespw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "einser.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "electrician-umhlangaridge.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eliasojala.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elibom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ell-net.tokyo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ellencorddry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "emeraldcityswagger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "empherino.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "energy-initiative.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "engiedev.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ensurtec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "envoie.moi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "envoyez.moi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eru.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "escuelabiblica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "euteamo.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eutotal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eventplace.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "everydaygary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "evoco.vc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "extremeservicesandrestoration.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fabiankoeppen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fabriziorocca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fackovcova.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fackovcova.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fackovcova.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fackovec.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fackovec.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "falling.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "feedfall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ferienhausprovence.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ferm-rotterdam.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ffh.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fileon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "filmesonline.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fiskestang.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.lu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcor.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fleetcorcards.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flirtee.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flirtos.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "floj.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flosserver.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flurp.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fmc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "folk.as", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "foreveryoung.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "francois-gaillard.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "freaksports.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fredericcote.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frei.social", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuckobr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuckobr.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuckobr.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuckobr.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuckobr.su", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuckonthefirst.date", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fur.red", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "future-moves.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fyol.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "g5.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gameblabla.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gamesaviour.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gamesided.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gamilab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gamilab.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ganggalbichler.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "garrowmediallc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gcfadvisors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "geba-online.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "geckler-ee.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "genesysmi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gentooblog.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "get.how", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gilium.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "giraffeduck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "glevolution.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "globcoin.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "golf18staging.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "govisitcostarica.co.cr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "govisitcostarica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gozenhost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gpgscoins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "graf-igor.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "graft.observer", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "greatergoodoffers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "greatfire.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "groenteclub.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gunceloyunhileleri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "guts.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "habbig.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hamiltonlinen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hanfverband-erfurt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hang333.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "haoqi.men", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hardloopfysio.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hausarztpraxis-linn.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "headshopinternational.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "healthit.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hearty.org.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "heatingandairconditioningdallastx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "heiwa-valve.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hejianpeng.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hentaiz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "highperformancehvac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hollerau.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "homegreenmark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hopla.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "housese.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hryniewski.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hstspreload.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "humorce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hunterkehoe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "huurwoordenaar.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hvmk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hybula.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hybula.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hydai.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hyperporn.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ia.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iam.soy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ifreetion.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "illerzell.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "imaginary.stream", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "imobile3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infocon.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infranium.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infranium.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infranium.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infranium.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inox.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inoxio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ins-kreativ.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "insecure.org.je", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "insrt.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "insurgentsmustdie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "interaktiva.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "interiortradingco.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iofort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ionovia.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ipadportfolioapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iphoneportfolioapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iren.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "isabelaflores.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ishet.al", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ispfontela.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "issa.org.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "isthedoorlocked.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ivre.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iwanttoliveinabunker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jaarvistech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jabbers.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jakeslab.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jamesl.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jeda.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jenniferengerwingaantrouwen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jeremypaul.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jiazhao.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jimbiproducts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jmcataffo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jtl-software.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "junias-fenske.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "juusujanar.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jydemarked.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kabarlinux.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kagitreklam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kanetix.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kanzlei-oehler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "karupp-did.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kastorsky.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kellyssportsbarandgrill.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kelvinfichter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kindlezs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kirkify.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "klantenadvies.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "klingsundet.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "koerperkult.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kolcsey.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kotonoha.cafe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kovuthehusky.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kryha.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ksk-agentur.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kuops.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lacetsfun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ladenzeile.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ladenzeile.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lambertshealthcare.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "langkawitrip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "langzijn.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "laohei.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "laplacesicherheit.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lars.moi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lca.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lcars-sv.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lcy.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lcy.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lcybox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "legalisepeacebloom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lemonthy.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lemonthy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lenaneva.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "letsdebug.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leumi-how-to.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lhakustik.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "libertins.date", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "life-emotions.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "littlericket.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "livela.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lixiaojiang.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "liz.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lizhi123.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lnbeauty.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "loafhead.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lobstr.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "localethereum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "logicne-hise.si", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "logoglo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lotro-wiki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lshiy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ludogue.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lunapatch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "luyckx.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lxd.pm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "majkl.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "majkl.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "majkl578.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "malermeister-haussmann.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "malwareverse.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mandanudes.ae", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marco-hegenberg.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marseillekiteclub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "masteragenasia.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mastersquirrel.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mathsweek.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mathsweek.org.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matmessages.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mbaasy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mbanq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mede-handover.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "medmarkt24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mega-aukcion.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "meintragebaby.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "melissaauclaire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "metro-lawn-care.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "michaeliscorp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "michaelpelletterie.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "michaelschmidt.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mikehilldesign.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mikywow.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mindcell.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mirgleich.dnshome.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mirjamderijk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "missyou.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mkchandler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mkkkrc.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mobila-chisinau.md", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "momento.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "monkieteel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "monkieteel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "montemanik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "montessori.edu.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "moot-info.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motd.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mousemessages.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mozektevidi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mrburtbox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mtane0412.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mtlconcerts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "multizone.games", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mxn8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "my4g.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mybagofcoffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mycrypto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mydrone.services", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mydroneservices.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mydroneservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myetherwallet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myipaddr.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myrepubiic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myrepublic.com.kh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myrepublic.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myrepublic.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myrepublicinternet.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mywallets.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "n-a.date", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "n0s.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nami.bo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nami.trade", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "narakenkoland.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "naturblogg.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "naturesbest.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nea.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nems.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nesbase.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "net-rencontre.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newtonproject.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nexthop.co.th", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nflmocks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nhw.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nic.goog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nic.how", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nic.soy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nic.xn--q9jyb4c", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "niki.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "niklas.host", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nmgb.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nmgb.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nobitakun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nodesec.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "northerngate.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nosecrets.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "notora.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "noxi.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nrc-gateway.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nur.berlin", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nvl-game.tokyo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nwr-waffenbuch.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nya.as", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nyan.stream", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oakesfam.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "objectif-leger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "obono.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "odpikedoslike.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ogyaa.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "okotoksbeach.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "olgun.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ollieowlsblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "onazikgu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ongea.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "openreview.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "orgatech-gmbh.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "originalsport.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "orionfinancialservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ovix.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paintcolorsbysue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "palariviera.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "parodesigns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "partiwatch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pashminacachemire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pci-dss.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pcidss.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "penslabyrinth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "performancehealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "perthtrains.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "peters.consulting", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "philippinedroneassociation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "philna.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pinkbikecycle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pintoselectrician.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pjo.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "placebet.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "plumplat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pornhubhd.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "powerball.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "powermatic7.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pplsvc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prematureacceleration.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "preposted.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "princessefoulard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prismacloud.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pro-image.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "projet-fly.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "promo-computers.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "promohulp.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "protege.moi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "psychologie-hofner.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "purbd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qazcloud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qoml.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qoor.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "quic.stream", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qx.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rahadiana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raptorsrapture.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rawdutch.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rcd.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rdwh.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "redgoose.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "redwaterhost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "referdell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reflectores.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "registerex.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rehabmail.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reichardt-home.goip.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reiki-france.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reimaginebelonging.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rekisuta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rencontres-erotiques.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "retetop95.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "retrovideospiele.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "revisit.date", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rheinturm.nrw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "riederle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "robertbln.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "robertopazeller.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "roeleveld.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "romantica-hotel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "romar-bos.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "roms.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rothe.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "route-wird-berechnet.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rritv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "s0laris.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sacprincesse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "safestore.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sagargandecha.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "samdev.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sammenlignakasser.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "satal.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sayori.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sbsbaits.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "schillers-friedberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "schneider-electric.tg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "school-register.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "schur-it.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sclns.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scripter.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sec.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "secteer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "seosec.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "septicrepairspecialists.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sheet.host", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sherrikehoetherapy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shivamber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shopalike.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shybynature.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "si2b.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sictame-tigf.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "silent-clean.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "simonshine.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sircon.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sisgopro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sistov.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skrivande.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smit.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smithchow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smmcab.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sortingwizard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "soulcraft.bz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spar-ni.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spirit-hunters-germany.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spitfiredialers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sportakrobatik.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sportsjaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sppin.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stadtbuecherei-bad-wurzach.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "standard.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stefan-rothe.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stefancosma.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "steffentreeservice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stellarguard.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stickertuningfetzt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stolin.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "straightedgebarbers.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stromberger.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "strommenhome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "studioproapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "subsistence.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "successwithflora.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "succubus.xxx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "suessdeko.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "superaficionados.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "switcheo.exchange", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "switcheo.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "symlnk.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "talking12.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "targetexecutivesearch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tcmwellnessclinic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tea.codes", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "techtrackerpro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tekniskakustik.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "telegramdr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tendance-et-accessoires.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "terabyteit.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "teusink.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "the420vape.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thebakery2go.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thesmokingcuban.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "threatmarket.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tildes.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "timklefisch.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tokens.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toniharant.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "topekafoundationpros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toushi-shakkin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trauer-beileid.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trea98.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trillian.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trtruijens.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ts3-dns.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tunnelventilation.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "twitchplaysleaderboard.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ueberdosis.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "umsolugar.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unityconsciousnessbooks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unsereins.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uprouteyou.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "usatomotori.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "usuluddin.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uteam.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "utilityreport.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "v-spin.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vancityconcerts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vec.ac.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "venje.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ver-ooginoog.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "verasani.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "verizonconnect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vi.photo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vicjuwelen-annelore.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "videosdiversosdatv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "viralsouls.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vistacampus.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "visualdrone.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "viyf.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vkb-remont.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vmzone.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "voluptueuse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vrcholovka.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "walkera-fans.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "walltime.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "walpu.ski", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "walpuski.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "webdesignsandiego.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "webgreat.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "website-engineering.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "weiming.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wer.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "westcentralaor.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "whnpa.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "whosyourdaddy.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "whta.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wilkushka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wilkushka.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wineonthewall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wm-access.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wm-access.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wmaccess.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wolfermann.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wolkoopjes.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "worksitevr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wpexplorer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wpspeed.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wrdx.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wsl.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "www.govt.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xentox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xinex.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xinnixwebshop.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xiongx.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--6o8h.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--80ac0aqlt.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--hwt895j.xn--kpry57d", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xone.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xq55.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yannik-buerkle.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yeswecan.co.bw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yhndnzj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "youjizz.bz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ysun.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yuppi.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yvonnethomet.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zebulon.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zeetoppers.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zephyrbk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zephyrbookkeeping.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zerg.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zhangsidan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zhoutiancai.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zings.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zobworks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zoolaboo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zozzle.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zxavier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, // END OF 1-YEAR BULK HSTS ENTRIES // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc index 35f8df6..600a9321 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc +++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -88,7 +88,8 @@ std::make_unique<TransportSecurityState>()); storage_.set_cert_transparency_verifier( std::make_unique<MultiLogCTVerifier>()); - storage_.set_ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>()); + storage_.set_ct_policy_enforcer( + std::make_unique<DefaultCTPolicyEnforcer>()); storage_.set_proxy_resolution_service(ProxyResolutionService::CreateFixed( ProxyConfigWithAnnotation(no_proxy, TRAFFIC_ANNOTATION_FOR_TESTS))); storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
diff --git a/net/proxy_resolution/proxy_resolution_service.cc b/net/proxy_resolution/proxy_resolution_service.cc index b09e8d1..1f01c283 100644 --- a/net/proxy_resolution/proxy_resolution_service.cc +++ b/net/proxy_resolution/proxy_resolution_service.cc
@@ -15,6 +15,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" @@ -385,6 +386,34 @@ return url.ReplaceComponents(replacements); } +// Do not change the enumerated value as it is relied on by histograms. +enum class PacUrlSchemeForHistogram { + kOther = 0, + + kHttp = 1, + kHttps = 2, + kFtp = 3, + kFile = 4, + kData = 5, + + kMaxValue = kData, +}; + +PacUrlSchemeForHistogram GetPacUrlScheme(const GURL& pac_url) { + if (pac_url.SchemeIs("http")) + return PacUrlSchemeForHistogram::kHttp; + if (pac_url.SchemeIs("https")) + return PacUrlSchemeForHistogram::kHttps; + if (pac_url.SchemeIs("data")) + return PacUrlSchemeForHistogram::kData; + if (pac_url.SchemeIs("ftp")) + return PacUrlSchemeForHistogram::kFtp; + if (pac_url.SchemeIs("file")) + return PacUrlSchemeForHistogram::kFile; + + return PacUrlSchemeForHistogram::kOther; +} + } // namespace // ProxyResolutionService::InitProxyResolver ---------------------------------- @@ -1576,6 +1605,11 @@ &fetched_config_, &effective_config)); } + if (config.value().has_pac_url()) { + UMA_HISTOGRAM_ENUMERATION("Net.ProxyResolutionService.PacUrlScheme", + GetPacUrlScheme(config.value().pac_url())); + } + // Set the new configuration as the most recently fetched one. fetched_config_ = effective_config;
diff --git a/net/proxy_resolution/proxy_resolution_service_unittest.cc b/net/proxy_resolution/proxy_resolution_service_unittest.cc index 92addc9..6f42ddb 100644 --- a/net/proxy_resolution/proxy_resolution_service_unittest.cc +++ b/net/proxy_resolution/proxy_resolution_service_unittest.cc
@@ -15,6 +15,7 @@ #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/histogram_tester.h" #include "net/base/net_errors.h" #include "net/base/proxy_delegate.h" #include "net/base/proxy_server.h" @@ -171,6 +172,12 @@ observer.OnProxyConfigChanged(config_, availability_); } + void SetPacUrlConfig(base::StringPiece pac_url) { + SetConfig(ProxyConfigWithAnnotation( + ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)), + TRAFFIC_ANNOTATION_FOR_TESTS)); + } + private: ConfigAvailability availability_; ProxyConfigWithAnnotation config_; @@ -333,6 +340,42 @@ return GetJobsForURLs(map, urls); } +// Helper class to verify the bucket counts for PacUrlScheme histogram. +class PacUrlSchemeHistogramTester { + public: + void VerifyHistogram() const { + const char kPacUrlSchemeHistogram[] = + "Net.ProxyResolutionService.PacUrlScheme"; + + int total = GetTotal(); + + histograms_.ExpectTotalCount(kPacUrlSchemeHistogram, total); + + if (total > 0) { + histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 0, num_other); + histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 1, num_http); + histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 2, num_https); + histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 3, num_ftp); + histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 4, num_file); + histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 5, num_data); + } + } + + int num_http = 0; + int num_https = 0; + int num_ftp = 0; + int num_data = 0; + int num_file = 0; + int num_other = 0; + + private: + int GetTotal() const { + return num_http + num_https + num_ftp + num_data + num_file + num_other; + } + + base::HistogramTester histograms_; +}; + } // namespace TEST_F(ProxyResolutionServiceTest, Direct) { @@ -3576,4 +3619,58 @@ EXPECT_TRUE(info.is_direct()); } +// Tests that the URL scheme for PAC files gets output to the histogram. +TEST_F(ProxyResolutionServiceTest, PacUrlSchemeHistogram) { + PacUrlSchemeHistogramTester pac_histogram; + + MockProxyConfigService* config_service = + new MockProxyConfigService(ProxyConfig::CreateDirect()); + + ProxyResolutionService service( + base::WrapUnique(config_service), + std::make_unique<MockAsyncProxyResolverFactory>(false), nullptr); + + pac_histogram.VerifyHistogram(); + + // Set an http:// PAC. + config_service->SetPacUrlConfig("http://example.test/"); + pac_histogram.num_http++; + pac_histogram.VerifyHistogram(); + + // Set an https:// PAC. + config_service->SetPacUrlConfig("hTTps://example.test/wpad.dat"); + pac_histogram.num_https++; + pac_histogram.VerifyHistogram(); + + // Set an ftp:// PAC. + config_service->SetPacUrlConfig("ftp://example.test/pac.js"); + pac_histogram.num_ftp++; + pac_histogram.VerifyHistogram(); + + // Set an file:// PAC. + config_service->SetPacUrlConfig("file://example.test/boo"); + pac_histogram.num_file++; + pac_histogram.VerifyHistogram(); + + // Set an mailto: PAC. + config_service->SetPacUrlConfig("mailto:foo@example.test"); + pac_histogram.num_other++; + pac_histogram.VerifyHistogram(); + + // Set an data: PAC. + config_service->SetPacUrlConfig("data:,Hello%2C%20World!"); + pac_histogram.num_data++; + pac_histogram.VerifyHistogram(); + + // Set an filesystem: PAC. + config_service->SetPacUrlConfig("filesystem:http://example.test/pac.js"); + pac_histogram.num_other++; + pac_histogram.VerifyHistogram(); + + // Set another https:// as PAC. + config_service->SetPacUrlConfig("https://example2.test/wpad.dat"); + pac_histogram.num_https++; + pac_histogram.VerifyHistogram(); +} + } // namespace net
diff --git a/net/quic/chromium/crypto/proof_verifier_chromium.cc b/net/quic/chromium/crypto/proof_verifier_chromium.cc index b63bbca..5cafa7f00 100644 --- a/net/quic/chromium/crypto/proof_verifier_chromium.cc +++ b/net/quic/chromium/crypto/proof_verifier_chromium.cc
@@ -391,7 +391,7 @@ if (enforce_policy_checking_ && (result == OK || (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { - SCTList verified_scts = ct::SCTsMatchingStatus( + ct::SCTList verified_scts = ct::SCTsMatchingStatus( verify_details_->ct_verify_result.scts, ct::SCT_STATUS_OK); verify_details_->ct_verify_result.policy_compliance = @@ -399,7 +399,9 @@ cert_verify_result.verified_cert.get(), verified_scts, net_log_); if (verify_details_->cert_verify_result.cert_status & CERT_STATUS_IS_EV) { if (verify_details_->ct_verify_result.policy_compliance != - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS) { + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS && + verify_details_->ct_verify_result.policy_compliance != + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) { verify_details_->cert_verify_result.cert_status |= CERT_STATUS_CT_COMPLIANCE_FAILED; verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
diff --git a/net/quic/chromium/crypto_test_utils_chromium.cc b/net/quic/chromium/crypto_test_utils_chromium.cc index 4ced45f..7e58c1ac 100644 --- a/net/quic/chromium/crypto_test_utils_chromium.cc +++ b/net/quic/chromium/crypto_test_utils_chromium.cc
@@ -99,7 +99,7 @@ return std::make_unique<TestProofVerifierChromium>( std::move(cert_verifier), std::make_unique<TransportSecurityState>(), std::make_unique<MultiLogCTVerifier>(), - std::make_unique<CTPolicyEnforcer>(), "quic-root.pem"); + std::make_unique<DefaultCTPolicyEnforcer>(), "quic-root.pem"); } ProofVerifyContext* ProofVerifyContextForTesting() {
diff --git a/net/quic/chromium/quic_end_to_end_unittest.cc b/net/quic/chromium/quic_end_to_end_unittest.cc index c03f990..7344f7b 100644 --- a/net/quic/chromium/quic_end_to_end_unittest.cc +++ b/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -239,7 +239,7 @@ std::unique_ptr<ChannelIDService> channel_id_service_; TransportSecurityState transport_security_state_; std::unique_ptr<CTVerifier> cert_transparency_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc index 011ab3c..3bfaca5 100644 --- a/net/quic/chromium/quic_network_transaction_unittest.cc +++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -902,7 +902,7 @@ MockCertVerifier cert_verifier_; TransportSecurityState transport_security_state_; std::unique_ptr<CTVerifier> cert_transparency_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_; scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; @@ -6122,7 +6122,7 @@ MockCertVerifier cert_verifier_; TransportSecurityState transport_security_state_; std::unique_ptr<CTVerifier> cert_transparency_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; TestSocketPerformanceWatcherFactory test_socket_performance_watcher_factory_; scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
diff --git a/net/quic/chromium/quic_stream_factory_fuzzer.cc b/net/quic/chromium/quic_stream_factory_fuzzer.cc index decfe07..96fa6c7 100644 --- a/net/quic/chromium/quic_stream_factory_fuzzer.cc +++ b/net/quic/chromium/quic_stream_factory_fuzzer.cc
@@ -8,6 +8,7 @@ #include "net/base/completion_once_callback.h" #include "net/base/test_completion_callback.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cert/do_nothing_ct_verifier.h" #include "net/cert/mock_cert_verifier.h" #include "net/cert/x509_certificate.h" @@ -79,7 +80,7 @@ QuicTagVector connection_options; QuicTagVector client_connection_options; std::unique_ptr<CTVerifier> cert_transparency_verifier; - CTPolicyEnforcer ct_policy_enforcer; + DefaultCTPolicyEnforcer ct_policy_enforcer; }; static struct Env* env = new Env(); @@ -177,12 +178,14 @@ return 0; // TODO(nedwilliamson): attempt connection migration here - stream->ReadResponseHeaders(callback.callback()); + int rv = stream->ReadResponseHeaders(callback.callback()); + if (rv != OK && rv != ERR_IO_PENDING) { + return 0; + } callback.WaitForResult(); scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize); - int rv = - stream->ReadResponseBody(buffer.get(), kBufferSize, callback.callback()); + rv = stream->ReadResponseBody(buffer.get(), kBufferSize, callback.callback()); if (rv == ERR_IO_PENDING) callback.WaitForResult();
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 361dfbc..b6b36390 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -801,7 +801,7 @@ std::unique_ptr<ChannelIDService> channel_id_service_; TransportSecurityState transport_security_state_; std::unique_ptr<CTVerifier> cert_transparency_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; std::unique_ptr<ScopedMockNetworkChangeNotifier> scoped_mock_network_change_notifier_; std::unique_ptr<QuicStreamFactory> factory_;
diff --git a/net/quic/platform/impl/quic_ip_address_impl.cc b/net/quic/platform/impl/quic_ip_address_impl.cc index 961f5f1..1fd9a15 100644 --- a/net/quic/platform/impl/quic_ip_address_impl.cc +++ b/net/quic/platform/impl/quic_ip_address_impl.cc
@@ -4,13 +4,14 @@ #include "net/quic/platform/impl/quic_ip_address_impl.h" +#include "build/build_config.h" #include "net/base/address_family.h" #include "net/quic/platform/api/quic_bug_tracker.h" #if defined(OS_WIN) #include <winsock2.h> #include <ws2bth.h> -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <netinet/in.h> #endif
diff --git a/net/socket/socket.cc b/net/socket/socket.cc index 07e61d1..39e3db0 100644 --- a/net/socket/socket.cc +++ b/net/socket/socket.cc
@@ -17,4 +17,8 @@ return ERR_READ_IF_READY_NOT_IMPLEMENTED; } +int Socket::CancelReadIfReady() { + return ERR_READ_IF_READY_NOT_IMPLEMENTED; +} + } // namespace net
diff --git a/net/socket/socket.h b/net/socket/socket.h index 8b6eb53..e834108 100644 --- a/net/socket/socket.h +++ b/net/socket/socket.h
@@ -52,6 +52,11 @@ int buf_len, CompletionOnceCallback callback); + // Cancels a pending ReadIfReady(). May only be called when a ReadIfReady() is + // pending. Returns net::OK or an error code. ERR_READ_IF_READY_NOT_SUPPORTED + // is returned if ReadIfReady() is not supported. + virtual int CancelReadIfReady(); + // Writes data, up to |buf_len| bytes, to the socket. Note: data may be // written partially. The number of bytes written is returned, or an error // is returned upon failure. ERR_SOCKET_NOT_CONNECTED should be returned if
diff --git a/net/socket/socket_descriptor.cc b/net/socket/socket_descriptor.cc index 5e9623c..5163d76 100644 --- a/net/socket/socket_descriptor.cc +++ b/net/socket/socket_descriptor.cc
@@ -4,14 +4,12 @@ #include "net/socket/socket_descriptor.h" -#if defined(OS_POSIX) -#include <sys/types.h> -#include <sys/socket.h> -#endif - #if defined(OS_WIN) #include <ws2tcpip.h> #include "net/base/winsock_init.h" +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <sys/socket.h> +#include <sys/types.h> #endif #if defined(OS_MACOSX) @@ -34,7 +32,7 @@ } } return result; -#else // OS_WIN +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) SocketDescriptor result = ::socket(family, type, protocol); #if defined(OS_MACOSX) // Disable SIGPIPE on this socket. Although Chromium globally disables
diff --git a/net/socket/socket_descriptor.h b/net/socket/socket_descriptor.h index e58e140..9a42a96 100644 --- a/net/socket/socket_descriptor.h +++ b/net/socket/socket_descriptor.h
@@ -14,12 +14,12 @@ namespace net { -#if defined(OS_POSIX) -typedef int SocketDescriptor; -const SocketDescriptor kInvalidSocket = -1; -#elif defined(OS_WIN) +#if defined(OS_WIN) typedef SOCKET SocketDescriptor; const SocketDescriptor kInvalidSocket = INVALID_SOCKET; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +typedef int SocketDescriptor; +const SocketDescriptor kInvalidSocket = -1; #endif // Creates socket. See WSASocket/socket documentation of parameters.
diff --git a/net/socket/socket_options.cc b/net/socket/socket_options.cc index 9b26aa2d..9589110 100644 --- a/net/socket/socket_options.cc +++ b/net/socket/socket_options.cc
@@ -9,21 +9,21 @@ #include "build/build_config.h" #include "net/base/net_errors.h" -#if defined(OS_POSIX) +#if defined(OS_WIN) +#include <winsock2.h> +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <netinet/in.h> #include <netinet/tcp.h> #include <sys/socket.h> -#elif defined(OS_WIN) -#include <winsock2.h> #endif namespace net { int SetTCPNoDelay(SocketDescriptor fd, bool no_delay) { -#if defined(OS_POSIX) - int on = no_delay ? 1 : 0; -#elif defined(OS_WIN) +#if defined(OS_WIN) BOOL on = no_delay ? TRUE : FALSE; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + int on = no_delay ? 1 : 0; #endif int rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char*>(&on), sizeof(on)); @@ -44,10 +44,10 @@ // provided on Linux prior to 3.9. // // SO_REUSEPORT is provided in MacOS X and iOS. -#if defined(OS_POSIX) - int boolean_value = reuse ? 1 : 0; -#elif defined(OS_WIN) +#if defined(OS_WIN) BOOL boolean_value = reuse ? TRUE : FALSE; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + int boolean_value = reuse ? 1 : 0; #endif int rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&boolean_value), @@ -58,10 +58,10 @@ int SetSocketReceiveBufferSize(SocketDescriptor fd, int32_t size) { int rv = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&size), sizeof(size)); -#if defined(OS_POSIX) - int os_error = errno; -#elif defined(OS_WIN) +#if defined(OS_WIN) int os_error = WSAGetLastError(); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + int os_error = errno; #endif int net_error = (rv == -1) ? MapSystemError(os_error) : OK; DCHECK(!rv) << "Could not set socket receive buffer size: " << net_error; @@ -71,10 +71,10 @@ int SetSocketSendBufferSize(SocketDescriptor fd, int32_t size) { int rv = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&size), sizeof(size)); -#if defined(OS_POSIX) - int os_error = errno; -#elif defined(OS_WIN) +#if defined(OS_WIN) int os_error = WSAGetLastError(); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + int os_error = errno; #endif int net_error = (rv == -1) ? MapSystemError(os_error) : OK; DCHECK(!rv) << "Could not set socket receive buffer size: " << net_error;
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc index 10e2e45..cabd3b8 100644 --- a/net/socket/socket_posix.cc +++ b/net/socket/socket_posix.cc
@@ -348,6 +348,16 @@ return ERR_IO_PENDING; } +int SocketPosix::CancelReadIfReady() { + DCHECK(read_if_ready_callback_); + + bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); + DCHECK(ok); + + read_if_ready_callback_.Reset(); + return net::OK; +} + int SocketPosix::Write( IOBuffer* buf, int buf_len,
diff --git a/net/socket/socket_posix.h b/net/socket/socket_posix.h index 9e0dd95..ff7cbb6 100644 --- a/net/socket/socket_posix.h +++ b/net/socket/socket_posix.h
@@ -74,6 +74,7 @@ // reading. This method doesn't hold on to |buf|. // See socket.h for more information. int ReadIfReady(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); + int CancelReadIfReady(); int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback,
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 93ad63f..dfedd36 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -504,6 +504,12 @@ return helper_.AllReadDataConsumed(); } +void SequencedSocketData::CancelPendingRead() { + DCHECK_EQ(PENDING, read_state_); + + read_state_ = IDLE; +} + bool SequencedSocketData::AllWriteDataConsumed() const { return helper_.AllWriteDataConsumed(); } @@ -929,6 +935,14 @@ return ReadIfReadyImpl(buf, buf_len, std::move(callback)); } +int MockTCPClientSocket::CancelReadIfReady() { + DCHECK(pending_read_if_ready_callback_); + + pending_read_if_ready_callback_.Reset(); + data_->CancelPendingRead(); + return OK; +}; + int MockTCPClientSocket::Write( IOBuffer* buf, int buf_len, @@ -945,6 +959,11 @@ was_used_to_convey_data_ = true; + if (write_result.result == ERR_CONNECTION_CLOSED) { + // This MockWrite is just a marker to instruct us to set + // peer_closed_connection_. + peer_closed_connection_ = true; + } // ERR_IO_PENDING is a signal that the socket data will call back // asynchronously later. if (write_result.result == ERR_IO_PENDING) {
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 1ffc54e4..355d5dc4 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -220,6 +220,7 @@ virtual MockWriteResult OnWrite(const std::string& data) = 0; virtual bool AllReadDataConsumed() const = 0; virtual bool AllWriteDataConsumed() const = 0; + virtual void CancelPendingRead() {} virtual void OnEnableTCPFastOpenIfSupported(); @@ -416,6 +417,7 @@ bool AllWriteDataConsumed() const override; void OnEnableTCPFastOpenIfSupported() override; bool IsIdle() const override; + void CancelPendingRead() override; // An ASYNC read event with a return value of ERR_IO_PENDING will cause the // socket data to pause at that event, and advance no further, until Resume is @@ -658,6 +660,7 @@ int ReadIfReady(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; + int CancelReadIfReady() override; int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback,
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 41409fc..29634c5 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -1501,14 +1501,16 @@ host_and_port().host(), server_cert_verify_result_.verified_cert.get(), ocsp_response, sct_list, &ct_verify_result_.scts, net_log_); - SCTList verified_scts = + ct::SCTList verified_scts = ct::SCTsMatchingStatus(ct_verify_result_.scts, ct::SCT_STATUS_OK); ct_verify_result_.policy_compliance = policy_enforcer_->CheckCompliance( server_cert_verify_result_.verified_cert.get(), verified_scts, net_log_); if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV) { if (ct_verify_result_.policy_compliance != - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS) { + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS && + ct_verify_result_.policy_compliance != + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY) { server_cert_verify_result_.cert_status |= CERT_STATUS_CT_COMPLIANCE_FAILED; server_cert_verify_result_.cert_status &= ~CERT_STATUS_IS_EV;
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index 2013737..7ec62aa 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -199,7 +199,7 @@ std::unique_ptr<MockCertVerifier> cert_verifier_; std::unique_ptr<TransportSecurityState> transport_security_state_; MultiLogCTVerifier ct_verifier_; - CTPolicyEnforcer ct_policy_enforcer_; + DefaultCTPolicyEnforcer ct_policy_enforcer_; const std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; const scoped_refptr<SSLConfigService> ssl_config_service_; const std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index 31cef1d..d45a1051 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -93,7 +93,7 @@ ~MockCTPolicyEnforcer() override = default; ct::CTPolicyCompliance CheckCompliance( X509Certificate* cert, - const SCTList& verified_scts, + const ct::SCTList& verified_scts, const NetLogWithSource& net_log) override { return ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; }
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc index 93c1c00..61cffe20 100644 --- a/net/socket/tcp_client_socket.cc +++ b/net/socket/tcp_client_socket.cc
@@ -298,6 +298,10 @@ return ReadCommon(buf, buf_len, std::move(callback), /*read_if_ready=*/true); } +int TCPClientSocket::CancelReadIfReady() { + return socket_->CancelReadIfReady(); +} + int TCPClientSocket::Write( IOBuffer* buf, int buf_len,
diff --git a/net/socket/tcp_client_socket.h b/net/socket/tcp_client_socket.h index b7a9113..c2a229fc5 100644 --- a/net/socket/tcp_client_socket.h +++ b/net/socket/tcp_client_socket.h
@@ -77,6 +77,7 @@ int ReadIfReady(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; + int CancelReadIfReady() override; int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback,
diff --git a/net/socket/tcp_socket.h b/net/socket/tcp_socket.h index 34f1eba..04a4147 100644 --- a/net/socket/tcp_socket.h +++ b/net/socket/tcp_socket.h
@@ -11,7 +11,7 @@ #if defined(OS_WIN) #include "net/socket/tcp_socket_win.h" -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include "net/socket/tcp_socket_posix.h" #endif @@ -25,7 +25,7 @@ // before you know whether it is a client or server socket). #if defined(OS_WIN) typedef TCPSocketWin TCPSocket; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) typedef TCPSocketPosix TCPSocket; #endif
diff --git a/net/socket/tcp_socket_posix.cc b/net/socket/tcp_socket_posix.cc index fd9838e..12df91a5 100644 --- a/net/socket/tcp_socket_posix.cc +++ b/net/socket/tcp_socket_posix.cc
@@ -396,6 +396,12 @@ return rv; } +int TCPSocketPosix::CancelReadIfReady() { + DCHECK(socket_); + + return socket_->CancelReadIfReady(); +} + int TCPSocketPosix::Write( IOBuffer* buf, int buf_len,
diff --git a/net/socket/tcp_socket_posix.h b/net/socket/tcp_socket_posix.h index ac51718b..4512945f 100644 --- a/net/socket/tcp_socket_posix.h +++ b/net/socket/tcp_socket_posix.h
@@ -89,6 +89,7 @@ // Returns a net error code. int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); int ReadIfReady(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); + int CancelReadIfReady(); // Writes to the socket. // Returns a net error code.
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc index fa48dfb..5b97c310 100644 --- a/net/socket/tcp_socket_unittest.cc +++ b/net/socket/tcp_socket_unittest.cc
@@ -528,6 +528,62 @@ run_loop.Run(); } +// If a ReadIfReady is pending, it's legal to cancel it and start reading later. +TEST_F(TCPSocketTest, CancelPendingReadIfReady) { + ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4()); + + // Create a connected socket. + TestCompletionCallback connect_callback; + std::unique_ptr<TCPSocket> connecting_socket = + std::make_unique<TCPSocket>(nullptr, nullptr, NetLogSource()); + int result = connecting_socket->Open(ADDRESS_FAMILY_IPV4); + ASSERT_THAT(result, IsOk()); + int connect_result = + connecting_socket->Connect(local_address_, connect_callback.callback()); + + TestCompletionCallback accept_callback; + std::unique_ptr<TCPSocket> accepted_socket; + IPEndPoint accepted_address; + result = socket_.Accept(&accepted_socket, &accepted_address, + accept_callback.callback()); + ASSERT_THAT(accept_callback.GetResult(result), IsOk()); + ASSERT_TRUE(accepted_socket.get()); + ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk()); + + // Try to read from the socket, but never write anything to the other end. + base::RunLoop run_loop; + scoped_refptr<IOBufferWithDestructionCallback> read_buffer( + base::MakeRefCounted<IOBufferWithDestructionCallback>( + run_loop.QuitClosure())); + TestCompletionCallback read_callback; + EXPECT_EQ(ERR_IO_PENDING, connecting_socket->ReadIfReady( + read_buffer.get(), read_buffer->size(), + read_callback.callback())); + + // Now cancel the pending ReadIfReady(). + connecting_socket->CancelReadIfReady(); + + // Send data to |connecting_socket|. + const char kMsg[] = "hello!"; + scoped_refptr<StringIOBuffer> write_buffer = + base::MakeRefCounted<StringIOBuffer>(kMsg); + + TestCompletionCallback write_callback; + int write_result = accepted_socket->Write(write_buffer.get(), strlen(kMsg), + write_callback.callback(), + TRAFFIC_ANNOTATION_FOR_TESTS); + const int msg_size = strlen(kMsg); + ASSERT_EQ(msg_size, write_result); + + // Try reading again. ReadIfReady() should still succeed. + TestCompletionCallback read_callback2; + int read_result = connecting_socket->ReadIfReady( + read_buffer.get(), read_buffer->size(), read_callback2.callback()); + + ASSERT_EQ(msg_size, read_callback2.GetResult(read_result)); + ASSERT_EQ(0, memcmp(&kMsg, read_buffer->data(), msg_size)); +} + // These tests require kernel support for tcp_info struct, and so they are // enabled only on certain platforms. #if defined(TCP_INFO) || defined(OS_LINUX)
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index 747430d4..2edf932 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc
@@ -111,6 +111,9 @@ void WatchForRead(); void WatchForWrite(); + // Stops watching for read. + void StopWatchingForRead(); + // The TCPSocketWin is going away. void Detach(); @@ -212,6 +215,12 @@ write_watcher_.StartWatchingOnce(write_overlapped_.hEvent, &writer_); } +void TCPSocketWin::Core::StopWatchingForRead() { + DCHECK(!socket_->waiting_connect_); + + read_watcher_.StopWatching(); +} + void TCPSocketWin::Core::Detach() { // Stop watching the read watcher. A read won't be signalled after the Detach // call, since the socket has been closed, but it's possible the event was @@ -528,6 +537,17 @@ return ERR_IO_PENDING; } +int TCPSocketWin::CancelReadIfReady() { + DCHECK(read_callback_.is_null()); + DCHECK(!read_if_ready_callback_.is_null()); + DCHECK(waiting_read_); + + core_->StopWatchingForRead(); + read_if_ready_callback_.Reset(); + waiting_read_ = false; + return net::OK; +} + int TCPSocketWin::Write( IOBuffer* buf, int buf_len,
diff --git a/net/socket/tcp_socket_win.h b/net/socket/tcp_socket_win.h index 179b3c4..6b4594c 100644 --- a/net/socket/tcp_socket_win.h +++ b/net/socket/tcp_socket_win.h
@@ -69,6 +69,7 @@ // Full duplex mode (reading and writing at the same time) is supported. int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); int ReadIfReady(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); + int CancelReadIfReady(); int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback,
diff --git a/net/socket/udp_socket.h b/net/socket/udp_socket.h index 1a0d4398..9f5f74c 100644 --- a/net/socket/udp_socket.h +++ b/net/socket/udp_socket.h
@@ -9,7 +9,7 @@ #if defined(OS_WIN) #include "net/socket/udp_socket_win.h" -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include "net/socket/udp_socket_posix.h" #endif @@ -37,7 +37,7 @@ // // address. #if defined(OS_WIN) typedef UDPSocketWin UDPSocket; -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) typedef UDPSocketPosix UDPSocket; #endif
diff --git a/net/spdy/chromium/spdy_test_util_common.cc b/net/spdy/chromium/spdy_test_util_common.cc index 5ec9387..6145d25 100644 --- a/net/spdy/chromium/spdy_test_util_common.cc +++ b/net/spdy/chromium/spdy_test_util_common.cc
@@ -311,7 +311,7 @@ channel_id_service(nullptr), transport_security_state(std::make_unique<TransportSecurityState>()), cert_transparency_verifier(std::make_unique<DoNothingCTVerifier>()), - ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>()), + ct_policy_enforcer(std::make_unique<DefaultCTPolicyEnforcer>()), proxy_resolution_service(std::move(proxy_resolution_service)), ssl_config_service(base::MakeRefCounted<SSLConfigServiceDefaults>()), socket_factory(std::make_unique<MockClientSocketFactory>()), @@ -413,27 +413,13 @@ return context; } -class AllowAnyCertCTPolicyEnforcer : public CTPolicyEnforcer { - public: - AllowAnyCertCTPolicyEnforcer() = default; - ~AllowAnyCertCTPolicyEnforcer() override = default; - - ct::CTPolicyCompliance CheckCompliance( - X509Certificate* cert, - const SCTList& verified_scts, - const NetLogWithSource& net_log) override { - return ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } -}; - SpdyURLRequestContext::SpdyURLRequestContext() : storage_(this) { storage_.set_host_resolver(std::make_unique<MockHostResolver>()); storage_.set_cert_verifier(std::make_unique<MockCertVerifier>()); storage_.set_transport_security_state( std::make_unique<TransportSecurityState>()); storage_.set_proxy_resolution_service(ProxyResolutionService::CreateDirect()); - storage_.set_ct_policy_enforcer( - std::make_unique<AllowAnyCertCTPolicyEnforcer>()); + storage_.set_ct_policy_enforcer(std::make_unique<DefaultCTPolicyEnforcer>()); storage_.set_cert_transparency_verifier( std::make_unique<DoNothingCTVerifier>()); storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc index 1ab610c..3e9e6850 100644 --- a/net/tools/quic/quic_client_bin.cc +++ b/net/tools/quic/quic_client_bin.cc
@@ -49,6 +49,7 @@ #include "net/cert/cert_verifier.h" #include "net/cert/ct_known_logs.h" #include "net/cert/ct_log_verifier.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cert/multi_log_ct_verifier.h" #include "net/http/transport_security_state.h" #include "net/quic/chromium/crypto/proof_verifier_chromium.h" @@ -67,7 +68,6 @@ #include "net/tools/quic/synchronous_host_resolver.h" using net::CertVerifier; -using net::CTPolicyEnforcer; using net::CTVerifier; using net::MultiLogCTVerifier; using net::ProofVerifier; @@ -269,7 +269,8 @@ new TransportSecurityState); std::unique_ptr<MultiLogCTVerifier> ct_verifier(new MultiLogCTVerifier()); ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); - std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer()); + std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer( + new net::DefaultCTPolicyEnforcer()); std::unique_ptr<ProofVerifier> proof_verifier; if (line->HasSwitch("disable-certificate-verification")) { proof_verifier = net::QuicMakeUnique<FakeProofVerifier>();
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc index 91fdf87..d807a0e2 100644 --- a/net/tools/quic/quic_simple_client_bin.cc +++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -50,6 +50,7 @@ #include "net/cert/cert_verifier.h" #include "net/cert/ct_known_logs.h" #include "net/cert/ct_log_verifier.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cert/multi_log_ct_verifier.h" #include "net/http/transport_security_state.h" #include "net/quic/chromium/crypto/proof_verifier_chromium.h" @@ -67,7 +68,6 @@ #include "url/gurl.h" using net::CertVerifier; -using net::CTPolicyEnforcer; using net::CTVerifier; using net::MultiLogCTVerifier; using net::ProofVerifier; @@ -267,7 +267,8 @@ new TransportSecurityState); std::unique_ptr<MultiLogCTVerifier> ct_verifier(new MultiLogCTVerifier()); ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); - std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer()); + std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer( + new net::DefaultCTPolicyEnforcer()); std::unique_ptr<ProofVerifier> proof_verifier; if (line->HasSwitch("disable-certificate-verification")) { proof_verifier.reset(new FakeProofVerifier());
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 26ee4ca..cb4a829 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -496,7 +496,8 @@ if (ct_policy_enforcer_) { storage->set_ct_policy_enforcer(std::move(ct_policy_enforcer_)); } else { - storage->set_ct_policy_enforcer(std::make_unique<CTPolicyEnforcer>()); + storage->set_ct_policy_enforcer( + std::make_unique<DefaultCTPolicyEnforcer>()); } if (throttling_enabled_) {
diff --git a/net/url_request/url_request_file_dir_job.cc b/net/url_request/url_request_file_dir_job.cc index 1d44ad6..5610f8e 100644 --- a/net/url_request/url_request_file_dir_job.cc +++ b/net/url_request/url_request_file_dir_job.cc
@@ -14,12 +14,13 @@ #include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "build/build_config.h" #include "net/base/directory_listing.h" #include "net/base/io_buffer.h" #include "net/url_request/url_request_status.h" #include "url/gurl.h" -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) #include <sys/stat.h> #endif @@ -102,7 +103,7 @@ #if defined(OS_WIN) const base::string16& title = dir_path_.value(); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // TODO(jungshik): Add SysNativeMBToUTF16 to sys_string_conversions. // On Mac, need to add NFKC->NFC conversion either here or in file_path. // On Linux, the file system encoding is not defined, but we assume that @@ -131,7 +132,7 @@ filename.value() != base::FilePath::kParentDirectory) { #if defined(OS_WIN) std::string raw_bytes; // Empty on Windows means UTF-8 encoded name. -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) // TODO(jungshik): The same issue as for the directory name. const std::string& raw_bytes = filename.value(); #endif
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 8106e65f..46b5d68 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -86,7 +86,7 @@ } if (!ct_policy_enforcer()) { context_storage_.set_ct_policy_enforcer( - std::make_unique<CTPolicyEnforcer>()); + std::make_unique<DefaultCTPolicyEnforcer>()); } if (!ssl_config_service()) context_storage_.set_ssl_config_service(new SSLConfigServiceDefaults());
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 04301d5..d14529b 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h
@@ -27,6 +27,7 @@ #include "net/base/network_delegate_impl.h" #include "net/base/request_priority.h" #include "net/cert/cert_verifier.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cookies/cookie_monster.h" #include "net/disk_cache/disk_cache.h" #include "net/ftp/ftp_network_layer.h"
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 464ae90..b3a71959 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -7216,7 +7216,7 @@ ct::CTPolicyCompliance CheckCompliance( X509Certificate* cert, - const SCTList& verified_scts, + const ct::SCTList& verified_scts, const NetLogWithSource& net_log) override { return default_result_; } @@ -10779,8 +10779,7 @@ } void SetUp() override { - context_.SetCTPolicyEnforcer( - std::make_unique<AllowAnyCertCTPolicyEnforcer>()); + context_.SetCTPolicyEnforcer(std::make_unique<DefaultCTPolicyEnforcer>()); SetupContext(); context_.Init(); @@ -10847,18 +10846,6 @@ } protected: - class AllowAnyCertCTPolicyEnforcer : public CTPolicyEnforcer { - public: - AllowAnyCertCTPolicyEnforcer() = default; - ~AllowAnyCertCTPolicyEnforcer() override = default; - - ct::CTPolicyCompliance CheckCompliance( - X509Certificate* cert, - const SCTList& verified_scts, - const NetLogWithSource& net_log) override { - return ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } - }; // SetupContext configures the URLRequestContext that will be used for making // connetions to testserver. This can be overridden in test subclasses for // different behaviour.
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc index b03d4cc..709534745 100644 --- a/remoting/protocol/ssl_hmac_channel_authenticator.cc +++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc
@@ -95,20 +95,6 @@ } }; -// A CTPolicyEnforcer that accepts all certificates. -class IgnoresCTPolicyEnforcer : public net::CTPolicyEnforcer { - public: - IgnoresCTPolicyEnforcer() = default; - ~IgnoresCTPolicyEnforcer() override = default; - - net::ct::CTPolicyCompliance CheckCompliance( - net::X509Certificate* cert, - const net::SCTList& verified_scts, - const net::NetLogWithSource& net_log) override { - return net::ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; - } -}; - // Implements net::StreamSocket interface on top of P2PStreamSocket to be passed // to net::SSLClientSocket and net::SSLServerSocket. class NetStreamSocketAdapter : public net::StreamSocket { @@ -300,7 +286,7 @@ transport_security_state_.reset(new net::TransportSecurityState); cert_verifier_.reset(new FailingCertVerifier); ct_verifier_.reset(new net::DoNothingCTVerifier); - ct_policy_enforcer_.reset(new IgnoresCTPolicyEnforcer); + ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer); net::SSLConfig ssl_config; // Certificate verification and revocation checking are not needed
diff --git a/remoting/signaling/xmpp_signal_strategy.cc b/remoting/signaling/xmpp_signal_strategy.cc index 1f09bf4..734a679 100644 --- a/remoting/signaling/xmpp_signal_strategy.cc +++ b/remoting/signaling/xmpp_signal_strategy.cc
@@ -344,7 +344,7 @@ cert_verifier_ = net::CertVerifier::CreateDefault(); transport_security_state_.reset(new net::TransportSecurityState()); cert_transparency_verifier_.reset(new net::MultiLogCTVerifier()); - ct_policy_enforcer_.reset(new net::CTPolicyEnforcer()); + ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer()); net::SSLClientSocketContext context; context.cert_verifier = cert_verifier_.get(); context.transport_security_state = transport_security_state_.get();
diff --git a/sandbox/win/src/process_mitigations_win32k_unittest.cc b/sandbox/win/src/process_mitigations_win32k_unittest.cc index 48adf00..4e60300 100644 --- a/sandbox/win/src/process_mitigations_win32k_unittest.cc +++ b/sandbox/win/src/process_mitigations_win32k_unittest.cc
@@ -629,12 +629,21 @@ EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(test_policy_command.c_str())); } +// Flaky in Debug. https://crbug.com/840335 +#if !defined(NDEBUG) +#define MAYBE_CheckWin8LockDownSuccess DISABLED_CheckWin8LockDownSuccess +#define MAYBE_CheckWin8Redirection DISABLED_CheckWin8Redirection +#else +#define MAYBE_CheckWin8LockDownSuccess CheckWin8LockDownSuccess +#define MAYBE_CheckWin8Redirection CheckWin8Redirection +#endif + // This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation // along with the policy to fake user32 and gdi32 initialization successfully // launches the target process. // The test process itself links against user32/gdi32. -// Flaky. https://crbug.com/840335 -TEST(ProcessMitigationsWin32kTest, DISABLED_CheckWin8LockDownSuccess) { + +TEST(ProcessMitigationsWin32kTest, MAYBE_CheckWin8LockDownSuccess) { if (base::win::GetVersion() < base::win::VERSION_WIN8) return; @@ -661,7 +670,7 @@ // This test validates the even though we're running under win32k lockdown // we can use the IPC redirection to enumerate the list of monitors. // Flaky. https://crbug.com/840335 -TEST(ProcessMitigationsWin32kTest, DISABLED_CheckWin8Redirection) { +TEST(ProcessMitigationsWin32kTest, MAYBE_CheckWin8Redirection) { if (base::win::GetVersion() < base::win::VERSION_WIN8) return;
diff --git a/services/metrics/public/cpp/ukm_entry_builder_base.cc b/services/metrics/public/cpp/ukm_entry_builder_base.cc index 9dc82637..6685a58 100644 --- a/services/metrics/public/cpp/ukm_entry_builder_base.cc +++ b/services/metrics/public/cpp/ukm_entry_builder_base.cc
@@ -23,7 +23,7 @@ void UkmEntryBuilderBase::SetMetricInternal(uint64_t metric_hash, int64_t value) { - entry_->metrics.emplace_back(mojom::UkmMetric::New(metric_hash, value)); + entry_->metrics.emplace(metric_hash, value); } void UkmEntryBuilderBase::Record(UkmRecorder* recorder) {
diff --git a/services/metrics/public/mojom/ukm_interface.mojom b/services/metrics/public/mojom/ukm_interface.mojom index 7a1b4fc..1d81731 100644 --- a/services/metrics/public/mojom/ukm_interface.mojom +++ b/services/metrics/public/mojom/ukm_interface.mojom
@@ -6,15 +6,10 @@ import "url/mojom/url.mojom"; -struct UkmMetric { - uint64 metric_hash; - int64 value; -}; - struct UkmEntry { int64 source_id; uint64 event_hash; - array<UkmMetric> metrics; + map<uint64,int64> metrics; }; interface UkmRecorderInterface {
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index 2d7fe8ec..9e3885a 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -80,6 +80,8 @@ "throttling/throttling_network_transaction_factory.h", "throttling/throttling_upload_data_stream.cc", "throttling/throttling_upload_data_stream.h", + "tls_client_socket.cc", + "tls_client_socket.h", "udp_socket.cc", "udp_socket.h", "upload_progress_tracker.cc", @@ -172,6 +174,7 @@ "test_chunked_data_pipe_getter.cc", "test_chunked_data_pipe_getter.h", "throttling/throttling_controller_unittest.cc", + "tls_client_socket_unittest.cc", "udp_socket_unittest.cc", "upload_progress_tracker_unittest.cc", "url_loader_unittest.cc", @@ -179,6 +182,7 @@ if (!is_ios) { sources += [ + "network_context_cert_transparency_unittest.cc", "proxy_resolver_factory_mojo_unittest.cc", "websocket_throttler_unittest.cc", ] @@ -188,6 +192,7 @@ ":network_service", ":test_support", "//base", + "//components/certificate_transparency", "//components/network_session_configurator/browser", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", @@ -205,6 +210,8 @@ testonly = true sources = [ + "mojo_socket_test_util.cc", + "mojo_socket_test_util.h", "test/test_data_pipe_getter.cc", "test/test_data_pipe_getter.h", "test/test_network_context.h",
diff --git a/services/network/cross_origin_read_blocking.cc b/services/network/cross_origin_read_blocking.cc index d63e63e6..eef5fc4 100644 --- a/services/network/cross_origin_read_blocking.cc +++ b/services/network/cross_origin_read_blocking.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include <algorithm> #include <string> #include <unordered_set> @@ -92,79 +93,45 @@ // kMaybe. // - Returns kNo otherwise. // -// Mutates |data| to advance past the comment when returning kYes. -// -// Additionally, if the body of the HTML comment (e.g. normally the kYes and -// kMaybe cases) contains javascript-like comments (e.g. |data| == "<!--/*-->"), -// then kNo will be returned (and |data| won't be mutated). This helps avoid -// CORB blocking of the html/js polyglots identified in -// https://crbug.com/839425. +// Mutates |data| to advance past the comment when returning kYes. Note that +// SingleLineHTMLCloseComment ECMAscript rule is taken into account which means +// that characters following an HTML comment are consumed up to the nearest line +// terminating character. SniffingResult MaybeSkipHtmlComment(StringPiece* data) { - static const StringPiece kBeginCommentSignature = "<!--"; - if (!data->starts_with(kBeginCommentSignature)) { - if (kBeginCommentSignature.starts_with(*data)) + constexpr StringPiece kStartString = "<!--"; + if (!data->starts_with(kStartString)) { + if (kStartString.starts_with(*data)) return CrossOriginReadBlocking::kMaybe; return CrossOriginReadBlocking::kNo; } - enum State { - kNothingSpecial, - kAfterDash, - kAfterDashDash, - kAfterSlash, - } state = kNothingSpecial; - for (size_t i = kBeginCommentSignature.length(); i < data->length(); i++) { - char c = (*data)[i]; - switch (state) { - case kNothingSpecial: - if (c == '-') - state = kAfterDash; - else if (c == '/') - state = kAfterSlash; - else - DCHECK_EQ(kNothingSpecial, state); - break; + constexpr StringPiece kEndString = "-->"; + size_t end_of_html_comment = data->find(kEndString, kStartString.length()); + if (end_of_html_comment == StringPiece::npos) + return CrossOriginReadBlocking::kMaybe; + end_of_html_comment += kEndString.length(); - case kAfterDash: - if (c == '-') - state = kAfterDashDash; - else if (c == '/') - state = kAfterSlash; - else - state = kNothingSpecial; - break; + // Skipping until the first line terminating character. See + // https://crbug.com/839945 for the motivation behind this. + // + // https://www.ecma-international.org/ecma-262/8.0/index.html#sec-line-terminators + // defines <LF>, <CR>, <LS> ::= "\u2028", <PS> ::= "\u2029". + // https://www.ecma-international.org/ecma-262/8.0/index.html#prod-LineTerminator + // defines LineTerminator ::= <LF> | <CR> | <LS> | <PS>. + DCHECK_LT(data->length(), base::StringPiece::npos); + size_t end_of_line = base::StringPiece::npos; + end_of_line = + std::min(end_of_line, data->find_first_of("\r\n", end_of_html_comment)); + end_of_line = + std::min(end_of_line, data->find("\u2028", end_of_html_comment)); + end_of_line = + std::min(end_of_line, data->find("\u2029", end_of_html_comment)); + if (end_of_line == base::StringPiece::npos) + return CrossOriginReadBlocking::kMaybe; - case kAfterDashDash: - if (c == '>') { - // Found the end of the HTML comment. - data->remove_prefix(i + 1); // Advance past the comment. - return CrossOriginReadBlocking::kYes; - } else if (c == '-') { - state = kAfterDashDash; - } else if (c == '/') { - state = kAfterSlash; - } else { - state = kNothingSpecial; - } - break; - - case kAfterSlash: - if (c == '/' || c == '*') { - // html/js polyglot - let's report that this is not HTML, to avoid - // blocking what may be a valid Javascript. - return CrossOriginReadBlocking::kNo; - } - if (c == '/') - state = kAfterSlash; - else if (c == '-') - state = kAfterDash; - else - state = kNothingSpecial; - break; - } - } - - return CrossOriginReadBlocking::kMaybe; + // Found real end of the combined HTML/JS comment. + data->remove_prefix(end_of_line); + return CrossOriginReadBlocking::kYes; } // Headers from
diff --git a/services/network/cross_origin_read_blocking_explainer.md b/services/network/cross_origin_read_blocking_explainer.md index 2ed45a0..dd10da7 100644 --- a/services/network/cross_origin_read_blocking_explainer.md +++ b/services/network/cross_origin_read_blocking_explainer.md
@@ -262,17 +262,29 @@ [normal HTML sniffing](https://mimesniff.spec.whatwg.org/#identifying-a-resource-with-an-unknown-mime-type)) presence of "`<!--`" string doesn't immediately confirm that the sniffed resource is a HTML document - the HTML comment still has to be followed by a valid HTML tag. -* Additionally if the HTML-style comment contains Javascript-style comments - (i.e. either "`/*`" or "`//`" substrings), - then CORB conservatively assumes that the resource is not a HTML document. - This helps avoid blocking html/javascript polyglots which have been observed - in use on real websites - see the example below: +* Additionally, after the end of a HTML comment, the CORB sniffer will skip all + characters until a line terminating character. This helps accomodate the + [`SingleLineHTMLCloseComment`](https://www.ecma-international.org/ecma-262/8.0/index.html#prod-annexB-SingleLineHTMLCloseComment) + rule which can consume + [`SingleLineCommentChars`](https://www.ecma-international.org/ecma-262/8.0/index.html#prod-SingleLineCommentChars) + _after_ the "`-->`" characters. + +Examples of html/javascript polyglots which have been observed +in use on real websites: ```js <!--/*--><html><body><script type="text/javascript"><!--//*/ var x = "This is both valid html and valid javascript"; //--></script></body></html> ``` +```js +<!-- comment --> <script type='text/javascript'> +//<![CDATA[ +var x = "This is both valid html and valid javascript"; +//]]>--></script> +``` + + ### Protecting XML XML, like JSON, is a widely used data exchange format, and like HTML, is a
diff --git a/services/network/cross_origin_read_blocking_unittest.cc b/services/network/cross_origin_read_blocking_unittest.cc index 68a1e39..e85db98 100644 --- a/services/network/cross_origin_read_blocking_unittest.cc +++ b/services/network/cross_origin_read_blocking_unittest.cc
@@ -58,18 +58,18 @@ // HTML comment followed by whitespace and valid HTML tags. EXPECT_EQ(SniffingResult::kYes, - CORB::SniffForHTML(" <!-- this is comment --> <html><body>")); + CORB::SniffForHTML(" <!-- this is comment -->\n<html><body>")); // HTML comment, whitespace, more HTML comments, HTML tags. EXPECT_EQ( SniffingResult::kYes, CORB::SniffForHTML( - "<!-- this is comment -->\n<!-- this is comment --><html><body>")); + "<!-- this is comment -->\n<!-- this is comment -->\n<html><body>")); // HTML comment followed by valid HTML tag. EXPECT_EQ( SniffingResult::kYes, - CORB::SniffForHTML("<!-- this is comment <!-- --><script></script>")); + CORB::SniffForHTML("<!-- this is comment <!-- -->\n<script></script>")); // Whitespace followed by valid Javascript. EXPECT_EQ(SniffingResult::kNo, @@ -79,7 +79,7 @@ EXPECT_EQ( SniffingResult::kNo, CORB::SniffForHTML( - " <!-- this is comment\n document.write(1);\n// -->window.open()")); + " <!-- this is comment\n document.write(1);\n// -->\nwindow.open()")); // HTML/Javascript polyglot should return kNo. EXPECT_EQ(SniffingResult::kNo, @@ -88,15 +88,25 @@ "var blah = 123;\n" "//--></script></body></html>")); - // Tests to cover more of the state machine inside MaybeSkipHtmlComment. - EXPECT_EQ(SniffingResult::kNo, CORB::SniffForHTML("<!-- -/* --><html>")); - EXPECT_EQ(SniffingResult::kNo, CORB::SniffForHTML("<!-- --/* --><html>")); - EXPECT_EQ(SniffingResult::kYes, CORB::SniffForHTML("<!----><html>")); + // Tests to cover more of MaybeSkipHtmlComment. + EXPECT_EQ(SniffingResult::kMaybe, CORB::SniffForHTML("<!-- -/* --><html>")); + EXPECT_EQ(SniffingResult::kMaybe, CORB::SniffForHTML("<!-- --/* --><html>")); + EXPECT_EQ(SniffingResult::kYes, CORB::SniffForHTML("<!-- -/* -->\n<html>")); + EXPECT_EQ(SniffingResult::kYes, CORB::SniffForHTML("<!-- --/* -->\n<html>")); + EXPECT_EQ(SniffingResult::kMaybe, CORB::SniffForHTML("<!----> <html>")); + EXPECT_EQ(SniffingResult::kYes, CORB::SniffForHTML("<!---->\n<html>")); + EXPECT_EQ(SniffingResult::kYes, CORB::SniffForHTML("<!---->\r<html>")); EXPECT_EQ(SniffingResult::kYes, - CORB::SniffForHTML("<!-- ---/--> <html><body>")); + CORB::SniffForHTML("<!-- ---/-->\n<html><body>")); + + // HTML spec only allows *ASCII* whitespace before the first html element. + // See also https://html.spec.whatwg.org/multipage/syntax.html and + // https://infra.spec.whatwg.org/#ascii-whitespace. + EXPECT_EQ(SniffingResult::kNo, CORB::SniffForHTML("<!---->\u2028<html>")); + EXPECT_EQ(SniffingResult::kNo, CORB::SniffForHTML("<!---->\u2029<html>")); // Commented out html tag followed by non-html (" x"). - StringPiece commented_out_html_tag_data("<!-- <html> <?xml> \n<html>--> x"); + StringPiece commented_out_html_tag_data("<!-- <html> <?xml> \n<html>-->\nx"); EXPECT_EQ(SniffingResult::kNo, CrossOriginReadBlocking::SniffForHTML(commented_out_html_tag_data)); @@ -115,7 +125,8 @@ EXPECT_EQ(SniffingResult::kMaybe, CORB::SniffForHTML("")); EXPECT_EQ(SniffingResult::kMaybe, CORB::SniffForHTML("<!")); EXPECT_EQ(SniffingResult::kMaybe, CORB::SniffForHTML("<!-- unterminated...")); - EXPECT_EQ(SniffingResult::kNo, CORB::SniffForHTML("<!-- /* js ")); + EXPECT_EQ(SniffingResult::kMaybe, + CORB::SniffForHTML("<!-- blah --> <html> no newline yet")); } TEST(CrossOriginReadBlockingTest, SniffForXML) {
diff --git a/services/network/mojo_socket_test_util.cc b/services/network/mojo_socket_test_util.cc new file mode 100644 index 0000000..2c583f2 --- /dev/null +++ b/services/network/mojo_socket_test_util.cc
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/mojo_socket_test_util.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { + +TestSocketObserver::TestSocketObserver() : binding_(this) {} + +TestSocketObserver::~TestSocketObserver() { + EXPECT_EQ(net::OK, read_error_); + EXPECT_EQ(net::OK, write_error_); +} + +mojom::SocketObserverPtr TestSocketObserver::GetObserverPtr() { + DCHECK(!binding_); + + mojom::SocketObserverPtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; +} + +int TestSocketObserver::WaitForReadError() { + read_loop_.Run(); + int error = read_error_; + read_error_ = net::OK; + return error; +} + +int TestSocketObserver::WaitForWriteError() { + write_loop_.Run(); + int error = write_error_; + write_error_ = net::OK; + return error; +} + +void TestSocketObserver::OnReadError(int net_error) { + read_error_ = net_error; + read_loop_.Quit(); +} + +void TestSocketObserver::OnWriteError(int net_error) { + write_error_ = net_error; + write_loop_.Quit(); +} + +} // namespace network
diff --git a/services/network/mojo_socket_test_util.h b/services/network/mojo_socket_test_util.h new file mode 100644 index 0000000..c045101 --- /dev/null +++ b/services/network/mojo_socket_test_util.h
@@ -0,0 +1,45 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_MOJO_SOCKET_TEST_UTIL_H_ +#define SERVICES_NETWORK_MOJO_SOCKET_TEST_UTIL_H_ + +#include "base/macros.h" +#include "base/run_loop.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "net/base/net_errors.h" +#include "services/network/public/mojom/tcp_socket.mojom.h" + +namespace network { + +// A mojom::SocketObserver implementation used in tests. +class TestSocketObserver : public mojom::SocketObserver { + public: + TestSocketObserver(); + ~TestSocketObserver() override; + + // Returns a mojo pointer. This can only be called once. + mojom::SocketObserverPtr GetObserverPtr(); + + // Waits for Read and Write error. Returns the error observed. + int WaitForReadError(); + int WaitForWriteError(); + + private: + // mojom::SocketObserver implementation. + void OnReadError(int net_error) override; + void OnWriteError(int net_error) override; + + int read_error_ = net::OK; + int write_error_ = net::OK; + base::RunLoop read_loop_; + base::RunLoop write_loop_; + mojo::Binding<mojom::SocketObserver> binding_; + + DISALLOW_COPY_AND_ASSIGN(TestSocketObserver); +}; + +} // namespace network + +#endif // SERVICES_NETWORK_MOJO_SOCKET_TEST_UTIL_H_
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 539af82..f0d7dbf8d 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -9,13 +9,20 @@ #include "base/command_line.h" #include "base/logging.h" +#include "base/memory/ref_counted.h" #include "base/message_loop/message_loop_current.h" #include "base/optional.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/task_scheduler/post_task.h" #include "base/task_scheduler/task_traits.h" +#include "build/build_config.h" +#include "components/certificate_transparency/chrome_ct_policy_enforcer.h" #include "components/certificate_transparency/ct_policy_manager.h" +#include "components/certificate_transparency/features.h" +#include "components/certificate_transparency/sth_distributor.h" +#include "components/certificate_transparency/sth_reporter.h" +#include "components/certificate_transparency/tree_state_tracker.h" #include "components/cookie_config/cookie_store_util.h" #include "components/network_session_configurator/browser/network_session_configurator.h" #include "components/network_session_configurator/common/network_switches.h" @@ -24,6 +31,9 @@ #include "components/prefs/pref_service.h" #include "components/prefs/pref_service_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" +#include "net/cert/cert_verifier.h" +#include "net/cert/ct_log_verifier.h" +#include "net/cert/multi_log_ct_verifier.h" #include "net/cookies/cookie_monster.h" #include "net/dns/host_resolver.h" #include "net/dns/mapped_host_resolver.h" @@ -210,8 +220,15 @@ url_request_context_owner_ = ApplyContextParamsToBuilder( builder.get(), params_.get(), network_service->quic_disabled(), network_service->net_log(), network_service->network_quality_estimator(), + network_service_->sth_reporter(), &ct_tree_tracker_, &user_agent_settings_); url_request_context_ = url_request_context_owner_.url_request_context.get(); + if (ct_tree_tracker_ && network_service_->sth_reporter()) { + url_request_context_->cert_transparency_verifier()->SetObserver( + ct_tree_tracker_.get()); + network_service_->sth_reporter()->RegisterObserver(ct_tree_tracker_.get()); + } + network_service_->RegisterNetworkContext(this); cookie_manager_ = std::make_unique<CookieManager>(url_request_context_->cookie_store()); @@ -249,6 +266,17 @@ url_request_context_->transport_security_state()->SetRequireCTDelegate( nullptr); } + + if (url_request_context_ && + url_request_context_->cert_transparency_verifier()) { + url_request_context_->cert_transparency_verifier()->SetObserver(nullptr); + } + + if (network_service_ && network_service_->sth_reporter() && + ct_tree_tracker_) { + network_service_->sth_reporter()->UnregisterObserver( + ct_tree_tracker_.get()); + } } std::unique_ptr<NetworkContext> NetworkContext::CreateForTesting() { @@ -415,13 +443,23 @@ } // |network_service_| may be nullptr in tests. - return ApplyContextParamsToBuilder( + auto result = ApplyContextParamsToBuilder( &builder, network_context_params, network_service_ ? network_service_->quic_disabled() : false, network_service_ ? network_service_->net_log() : nullptr, network_service_ ? network_service_->network_quality_estimator() : nullptr, - &user_agent_settings_); + network_service_ ? network_service_->sth_reporter() : nullptr, + &ct_tree_tracker_, &user_agent_settings_); + + if (ct_tree_tracker_ && network_service_ && + network_service_->sth_reporter()) { + result.url_request_context->cert_transparency_verifier()->SetObserver( + ct_tree_tracker_.get()); + network_service_->sth_reporter()->RegisterObserver(ct_tree_tracker_.get()); + } + + return result; } URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder( @@ -430,6 +468,9 @@ bool quic_disabled, net::NetLog* net_log, net::NetworkQualityEstimator* network_quality_estimator, + certificate_transparency::STHReporter* sth_reporter, + std::unique_ptr<certificate_transparency::TreeStateTracker>* + out_ct_tree_tracker, net::StaticHttpUserAgentSettings** out_http_user_agent_settings) { if (net_log) builder->set_net_log(net_log); @@ -534,6 +575,11 @@ base::FeatureList::IsEnabled(features::kNetworkErrorLogging)); #endif // BUILDFLAG(ENABLE_REPORTING) + if (network_context_params->enforce_chrome_ct_policy) { + builder->set_ct_policy_enforcer( + std::make_unique<certificate_transparency::ChromeCTPolicyEnforcer>()); + } + net::HttpNetworkSession::Params session_params; bool is_quic_force_disabled = false; if (quic_disabled) @@ -553,7 +599,38 @@ -> std::unique_ptr<net::HttpTransactionFactory> { return std::make_unique<ThrottlingNetworkTransactionFactory>(session); })); - return URLRequestContextOwner(std::move(pref_service), builder->Build()); + + std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs; + if (!network_context_params->ct_logs.empty()) { + for (const auto& log : network_context_params->ct_logs) { + scoped_refptr<const net::CTLogVerifier> log_verifier = + net::CTLogVerifier::Create(log->public_key, log->name, + log->dns_api_endpoint); + if (!log_verifier) { + // TODO: Signal bad configuration (such as bad key). + continue; + } + ct_logs.push_back(std::move(log_verifier)); + } + auto ct_verifier = std::make_unique<net::MultiLogCTVerifier>(); + ct_verifier->AddLogs(ct_logs); + builder->set_ct_verifier(std::move(ct_verifier)); + } + + auto result = + URLRequestContextOwner(std::move(pref_service), builder->Build()); + +#if !defined(OS_IOS) + if (base::FeatureList::IsEnabled(certificate_transparency::kCTLogAuditing) && + out_ct_tree_tracker && sth_reporter && !ct_logs.empty()) { + net::URLRequestContext* context = result.url_request_context.get(); + *out_ct_tree_tracker = + std::make_unique<certificate_transparency::TreeStateTracker>( + ct_logs, context->host_resolver(), net_log); + } +#endif + + return result; } void NetworkContext::DestroyURLLoaderFactory( @@ -755,7 +832,7 @@ const net::AddressList& remote_addr_list, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojom::TCPConnectedSocketRequest request, - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, CreateTCPConnectedSocketCallback callback) { socket_factory_->CreateTCPConnectedSocket( local_addr, remote_addr_list, @@ -803,6 +880,7 @@ // Throw away old version; since this is a a browser test, we don't // need to restore the old state. cache->SetHttpNetworkTransactionFactoryForTesting(std::move(factory)); + std::move(callback).Run(); }
diff --git a/services/network/network_context.h b/services/network/network_context.h index 0267145..02d19a5 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -41,7 +41,9 @@ namespace certificate_transparency { class CTPolicyManager; -} +class TreeStateTracker; +class STHReporter; +} // namespace certificate_transparency namespace network { class NetworkService; @@ -153,7 +155,7 @@ const net::AddressList& remote_addr_list, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojom::TCPConnectedSocketRequest request, - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, CreateTCPConnectedSocketCallback callback) override; void CreateWebSocket(mojom::WebSocketRequest request, int32_t process_id, @@ -185,6 +187,9 @@ bool quic_disabled, net::NetLog* net_log, net::NetworkQualityEstimator* network_quality_estimator, + certificate_transparency::STHReporter* sth_reporter, + std::unique_ptr<certificate_transparency::TreeStateTracker>* + out_tree_state_tracker, net::StaticHttpUserAgentSettings** out_http_user_agent_settings); // Destroys the specified URLLoaderFactory. Called by the URLLoaderFactory @@ -248,6 +253,7 @@ constexpr static bool enable_resource_scheduler_ = true; std::unique_ptr<certificate_transparency::CTPolicyManager> ct_policy_manager_; + std::unique_ptr<certificate_transparency::TreeStateTracker> ct_tree_tracker_; DISALLOW_COPY_AND_ASSIGN(NetworkContext); };
diff --git a/services/network/network_context_cert_transparency_unittest.cc b/services/network/network_context_cert_transparency_unittest.cc new file mode 100644 index 0000000..f294d5a1 --- /dev/null +++ b/services/network/network_context_cert_transparency_unittest.cc
@@ -0,0 +1,436 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> + +#include "base/base64.h" +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/memory/ref_counted.h" +#include "base/stl_util.h" +#include "base/strings/string_piece.h" +#include "base/test/gtest_util.h" +#include "base/test/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" +#include "components/certificate_transparency/features.h" +#include "components/certificate_transparency/single_tree_tracker.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "net/base/address_list.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" +#include "net/cert/cert_verify_result.h" +#include "net/cert/ct_known_logs.h" +#include "net/cert/ct_policy_status.h" +#include "net/cert/ct_serialization.h" +#include "net/cert/ct_verifier.h" +#include "net/cert/mock_cert_verifier.h" +#include "net/cert/signed_certificate_timestamp.h" +#include "net/cert/signed_tree_head.h" +#include "net/cert/x509_certificate.h" +#include "net/dns/host_cache.h" +#include "net/dns/host_resolver.h" +#include "net/proxy_resolution/proxy_config_with_annotation.h" +#include "net/test/cert_test_util.h" +#include "net/test/ct_test_util.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/test_data_directory.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "net/url_request/url_request_context.h" +#include "services/network/network_context.h" +#include "services/network/network_service.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/mojom/ct_log_info.mojom.h" +#include "services/network/public/mojom/network_service.mojom.h" +#include "services/network/public/mojom/proxy_config.mojom.h" +#include "services/network/test/test_url_loader_client.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { + +namespace { + +mojom::NetworkContextParamsPtr CreateContextParams() { + mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New(); + + // Use a fixed proxy config, to avoid dependencies on local network + // configuration. + params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect(); + + // Configure Certificate Transparency for the context. + // TODO(robpercival): https://crbug.com/839612 - Use test logs for + // integration tests rather than production logs. + const char kPilotKey[] = + "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86" + "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7d\xa8\x4b\x12\x29\x80\xa3" + "\x3d\xad\xd3\x5a\x77\xb8\xcc\xe2\x88\xb3\xa5\xfd\xf1\xd3\x0c\xcd\x18" + "\x0c\xe8\x41\x46\xe8\x81\x01\x1b\x15\xe1\x4b\xf1\x1b\x62\xdd\x36\x0a" + "\x08\x18\xba\xed\x0b\x35\x84\xd0\x9e\x40\x3c\x2d\x9e\x9b\x82\x65\xbd" + "\x1f\x04\x10\x41\x4c\xa0"; + const char kAviatorKey[] = + "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86" + "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd7\xf4\xcc\x69\xb2\xe4\x0e" + "\x90\xa3\x8a\xea\x5a\x70\x09\x4f\xef\x13\x62\xd0\x8d\x49\x60\xff\x1b" + "\x40\x50\x07\x0c\x6d\x71\x86\xda\x25\x49\x8d\x65\xe1\x08\x0d\x47\x34" + "\x6b\xbd\x27\xbc\x96\x21\x3e\x34\xf5\x87\x76\x31\xb1\x7f\x1d\xc9\x85" + "\x3b\x0d\xf7\x1f\x3f\xe9"; + const char kDigiCertKey[] = + "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86" + "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\x46\xc5\xbe\x1b\xbb\x82" + "\x40\x16\xe8\xc1\xd2\xac\x19\x69\x13\x59\xf8\xf8\x70\x85\x46\x40\xb9" + "\x38\xb0\x23\x82\xa8\x64\x4c\x7f\xbf\xbb\x34\x9f\x4a\x5f\x28\x8a\xcf" + "\x19\xc4\x00\xf6\x36\x06\x93\x65\xed\x4c\xf5\xa9\x21\x62\x5a\xd8\x91" + "\xeb\x38\x24\x40\xac\xe8"; + params->ct_logs.push_back(network::mojom::CTLogInfo::New( + std::string(kPilotKey, base::size(kPilotKey) - 1), "Google 'Pilot' Log", + "pilot.ct.invalid")); + params->ct_logs.push_back(network::mojom::CTLogInfo::New( + std::string(kAviatorKey, base::size(kAviatorKey) - 1), + "Google 'Aviator' Log", "aviator.ct.invalid")); + params->ct_logs.push_back(network::mojom::CTLogInfo::New( + std::string(kDigiCertKey, base::size(kDigiCertKey) - 1), + "DigiCert Log Server", "digicert.ct.invalid")); + + return params; +} + +// TODO(robpercival): https://crbug.com/839612 - Make it easier to use a test +// cert that is not so tightly-coupled to production logs and STHs. +scoped_refptr<net::X509Certificate> GetCTCertForTesting() { + base::ScopedAllowBlockingForTesting allow_blocking_for_loading_cert; + return net::CreateCertificateChainFromFile( + net::GetTestCertsDirectory(), "comodo-chain.pem", + net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE); +} + +// The number of valid SCTs in |GetCTCertForTesting| from logs configured in +// |CreateContextParams()|. +const int kNumSCTs = 3; + +// Decodes a base64-encoded "DigitallySigned" TLS struct into |*sig_out|. +// See https://tools.ietf.org/html/rfc5246#section-4.7. +// |sig_out| must not be null. +bool DecodeDigitallySigned(base::StringPiece base64_data, + net::ct::DigitallySigned* sig_out) { + std::string data; + if (!base::Base64Decode(base64_data, &data)) + return false; + + base::StringPiece data_ptr = data; + if (!net::ct::DecodeDigitallySigned(&data_ptr, sig_out)) + return false; + + return true; +} + +// Populates |*sth_out| with the given information. +// |sth_out| must not be null. +bool BuildSignedTreeHead(base::Time timestamp, + uint64_t tree_size, + base::StringPiece root_hash_base64, + base::StringPiece signature_base64, + base::StringPiece log_id_base64, + net::ct::SignedTreeHead* sth_out) { + sth_out->version = net::ct::SignedTreeHead::V1; + sth_out->timestamp = timestamp; + sth_out->tree_size = tree_size; + + std::string root_hash; + if (!base::Base64Decode(root_hash_base64, &root_hash)) { + return false; + } + root_hash.copy(sth_out->sha256_root_hash, net::ct::kSthRootHashLength); + + return DecodeDigitallySigned(signature_base64, &sth_out->signature) && + base::Base64Decode(log_id_base64, &sth_out->log_id); +} + +TEST(NetworkContextCertTransparencyAuditingDisabledTest, + SCTsAreNotCheckedForInclusion) { + base::test::ScopedTaskEnvironment scoped_task_environment( + base::test::ScopedTaskEnvironment::MainThreadType::IO); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + certificate_transparency::kCTLogAuditing); + + std::unique_ptr<NetworkService> network_service = + NetworkService::CreateForTesting(); + + // Override the CertVerifier, so that a 'real' cert can be simulated being + // returned by the net::TestServer. This should be done before creating the + // context. + net::MockCertVerifier mock_cert_verifier; + NetworkContext::SetCertVerifierForTesting(&mock_cert_verifier); + base::ScopedClosureRunner cleanup(base::BindOnce( + [] { NetworkContext::SetCertVerifierForTesting(nullptr); })); + + mojom::NetworkContextParamsPtr context_params = CreateContextParams(); + mojom::NetworkContextPtr network_context_ptr; + std::unique_ptr<NetworkContext> network_context = + std::make_unique<NetworkContext>(network_service.get(), + mojo::MakeRequest(&network_context_ptr), + std::move(context_params)); + + // Certificate Transparency should be configured, but there should be + // nothing listening for SCTs (such as the NetworkContext's ct_tree_tracker_). + ASSERT_TRUE( + network_context->url_request_context()->cert_transparency_verifier()); + EXPECT_FALSE(network_context->url_request_context() + ->cert_transparency_verifier() + ->GetObserver()); + + // Provide an STH from Google's Pilot log that can be used to prove + // inclusion for an SCT later in the test. + net::ct::SignedTreeHead pilot_sth; + ASSERT_TRUE(BuildSignedTreeHead( + base::Time::FromJsTime(1512419914170), 181871752, + "bvgljSy3Yg32Y6J8qL5WmUA3jn2WnOrEFDqxD0AxUvs=", + "BAMARjBEAiAwEXve2RBk3XkUR+6nACSETTgzKFaEeginxuj5U9BI/" + "wIgBPuQS5ACxsro6TtpY4bQyE6WlMdcSMiMd/SSGraOBOg=", + "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=", &pilot_sth)); + network_service->UpdateSignedTreeHead(pilot_sth); + + // Provide an STH from Google's Aviator log that is not recent enough to + // prove inclusion for an SCT later in the test. + net::ct::SignedTreeHead aviator_sth; + ASSERT_TRUE(BuildSignedTreeHead( + base::Time::FromJsTime(1442652106945), 8502329, + "bfG+gWZcHl9fqtNo0Z/uggs8E5YqGOtJQ0Z5zVZDRxI=", + "BAMARjBEAiA6elcNQoShmKLHj/" + "IA649UIbaQtWJEpj0Eot0q7G6fEgIgYChb7U6Reuvt0nO5PionH+3UciOxKV3Cy8/" + "eq59lSYY=", + "aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=", &aviator_sth)); + network_service->UpdateSignedTreeHead(aviator_sth); + + // Start a test server on "localhost" and configure connections to it to + // simulate using a real certificate. + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + ASSERT_TRUE(https_server.Start()); + + // Flush any pending tasks, in particular, any configuration updates to + // the network or DNS configuration. This is because SCTs are only checked + // if DNS was used and the network config has not changed, for privacy + // reasons. + scoped_task_environment.RunUntilIdle(); + + // Configure "localhost" to be treated as if it went through DNS. This + // modifies the HostCache directly to simulate it being cached, rather than + // indirecting through a scoped HostResolverProc, as queries that use + // HostResolverProcs are treated as SOURCE_UNKNOWN, rather than SOURCE_DNS. + net::AddressList address_list; + ASSERT_TRUE(https_server.GetAddressList(&address_list)); + + net::HostCache* host_cache = + network_context->url_request_context()->host_resolver()->GetHostCache(); + ASSERT_TRUE(host_cache); + host_cache->Set( + net::HostCache::Key("localhost", net::ADDRESS_FAMILY_UNSPECIFIED, 0), + net::HostCache::Entry(net::OK, address_list, + net::HostCache::Entry::SOURCE_DNS), + base::TimeTicks::Now(), base::TimeDelta()); + + // This certificate contains 3 SCTs and fulfills the Chrome CT policy. + // Simulate it being trusted by a known root, as otherwise CT is skipped for + // private roots. + net::CertVerifyResult verify_result; + verify_result.is_issued_by_known_root = true; + verify_result.cert_status = 0; + verify_result.verified_cert = GetCTCertForTesting(); + ASSERT_TRUE(verify_result.verified_cert); + mock_cert_verifier.AddResultForCert(https_server.GetCertificate(), + verify_result, net::OK); + + ResourceRequest request; + request.url = https_server.GetURL("localhost", "/"); + + mojom::URLLoaderFactoryPtr loader_factory; + network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), + 0); + + base::HistogramTester histograms; + mojom::URLLoaderPtr loader; + TestURLLoaderClient client; + loader_factory->CreateLoaderAndStart( + mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */, + 0 /* options */, request, client.CreateInterfacePtr(), + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); + + client.RunUntilResponseReceived(); + EXPECT_TRUE(client.has_received_response()); + EXPECT_TRUE(client.has_received_completion()); + + // Expect only a single connection. + ASSERT_EQ(histograms.GetBucketCount("Net.SSL_Connection_Error", net::OK), 1); + + // Expect 3 SCTs in this connection. + EXPECT_THAT(histograms.GetBucketCount( + "Net.CertificateTransparency.SCTsPerConnection", kNumSCTs), + 1); + + // Expect that the SCTs were embedded in the certificate. + EXPECT_THAT( + histograms.GetBucketCount( + "Net.CertificateTransparency.SCTOrigin", + static_cast<int>(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED)), + kNumSCTs); + + // No SCTs should be eligible for inclusion checking, as inclusion checking + // is disabled. + histograms.ExpectTotalCount( + "Net.CertificateTransparency.CanInclusionCheckSCT", 0); +} + +TEST(NetworkContextCertTransparencyAuditingEnabledTest, + SCTsAreCheckedForInclusion) { + base::test::ScopedTaskEnvironment scoped_task_environment( + base::test::ScopedTaskEnvironment::MainThreadType::IO); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + certificate_transparency::kCTLogAuditing); + + std::unique_ptr<NetworkService> network_service = + NetworkService::CreateForTesting(); + + // Override the CertVerifier, so that a 'real' cert can be simulated being + // returned by the net::TestServer. This should be done before creating the + // context. + net::MockCertVerifier mock_cert_verifier; + NetworkContext::SetCertVerifierForTesting(&mock_cert_verifier); + base::ScopedClosureRunner cleanup(base::BindOnce( + [] { NetworkContext::SetCertVerifierForTesting(nullptr); })); + + mojom::NetworkContextParamsPtr context_params = CreateContextParams(); + mojom::NetworkContextPtr network_context_ptr; + std::unique_ptr<NetworkContext> network_context = + std::make_unique<NetworkContext>(network_service.get(), + mojo::MakeRequest(&network_context_ptr), + std::move(context_params)); + + // Certificate Transparency should be configured, but there should be + // nothing listening for SCTs (such as the NetworkContext's ct_tree_tracker_). + ASSERT_TRUE( + network_context->url_request_context()->cert_transparency_verifier()); + EXPECT_TRUE(network_context->url_request_context() + ->cert_transparency_verifier() + ->GetObserver()); + + // Provide an STH from Google's Pilot log that can be used to prove + // inclusion for an SCT later in the test. + net::ct::SignedTreeHead pilot_sth; + ASSERT_TRUE(BuildSignedTreeHead( + base::Time::FromJsTime(1512419914170), 181871752, + "bvgljSy3Yg32Y6J8qL5WmUA3jn2WnOrEFDqxD0AxUvs=", + "BAMARjBEAiAwEXve2RBk3XkUR+6nACSETTgzKFaEeginxuj5U9BI/" + "wIgBPuQS5ACxsro6TtpY4bQyE6WlMdcSMiMd/SSGraOBOg=", + "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=", &pilot_sth)); + network_service->UpdateSignedTreeHead(pilot_sth); + + // Provide an STH from Google's Aviator log that is not recent enough to + // prove inclusion for an SCT later in the test. + net::ct::SignedTreeHead aviator_sth; + ASSERT_TRUE(BuildSignedTreeHead( + base::Time::FromJsTime(1442652106945), 8502329, + "bfG+gWZcHl9fqtNo0Z/uggs8E5YqGOtJQ0Z5zVZDRxI=", + "BAMARjBEAiA6elcNQoShmKLHj/" + "IA649UIbaQtWJEpj0Eot0q7G6fEgIgYChb7U6Reuvt0nO5PionH+3UciOxKV3Cy8/" + "eq59lSYY=", + "aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=", &aviator_sth)); + network_service->UpdateSignedTreeHead(aviator_sth); + + // Start a test server on "localhost" and configure connections to it to + // simulate using a real certificate. + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + ASSERT_TRUE(https_server.Start()); + + // Flush any pending tasks, in particular, any configuration updates to + // the network or DNS configuration. This is because SCTs are only checked + // if DNS was used and the network config has not changed, for privacy + // reasons. + scoped_task_environment.RunUntilIdle(); + + // Configure "localhost" to be treated as if it went through DNS. This + // modifies the HostCache directly to simulate it being cached, rather than + // indirecting through a scoped HostResolverProc, as queries that use + // HostResolverProcs are treated as SOURCE_UNKNOWN, rather than SOURCE_DNS. + net::AddressList address_list; + ASSERT_TRUE(https_server.GetAddressList(&address_list)); + + net::HostCache* host_cache = + network_context->url_request_context()->host_resolver()->GetHostCache(); + ASSERT_TRUE(host_cache); + host_cache->Set( + net::HostCache::Key("localhost", net::ADDRESS_FAMILY_UNSPECIFIED, 0), + net::HostCache::Entry(net::OK, address_list, + net::HostCache::Entry::SOURCE_DNS), + base::TimeTicks::Now(), base::TimeDelta()); + + // This certificate contains 3 SCTs and fulfills the Chrome CT policy. + // Simulate it being trusted by a known root, as otherwise CT is skipped for + // private roots. + net::CertVerifyResult verify_result; + verify_result.is_issued_by_known_root = true; + verify_result.cert_status = 0; + verify_result.verified_cert = GetCTCertForTesting(); + ASSERT_TRUE(verify_result.verified_cert); + mock_cert_verifier.AddResultForCert(https_server.GetCertificate(), + verify_result, net::OK); + + base::HistogramTester histograms; + + ResourceRequest request; + request.url = https_server.GetURL("localhost", "/"); + + mojom::URLLoaderFactoryPtr loader_factory; + network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), + 0); + + mojom::URLLoaderPtr loader; + TestURLLoaderClient client; + loader_factory->CreateLoaderAndStart( + mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */, + 0 /* options */, request, client.CreateInterfacePtr(), + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); + + client.RunUntilResponseReceived(); + EXPECT_TRUE(client.has_received_response()); + EXPECT_TRUE(client.has_received_completion()); + + // Expect only a single connection. + ASSERT_EQ(histograms.GetBucketCount("Net.SSL_Connection_Error", net::OK), 1); + + // Expect 3 SCTs in this connection. + EXPECT_THAT(histograms.GetBucketCount( + "Net.CertificateTransparency.SCTsPerConnection", kNumSCTs), + 1); + + // Expect that the SCTs were embedded in the certificate. + EXPECT_THAT( + histograms.GetBucketCount( + "Net.CertificateTransparency.SCTOrigin", + static_cast<int>(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED)), + kNumSCTs); + + // The Pilot SCT should be eligible for inclusion checking, because a recent + // enough Pilot STH is available. + histograms.ExpectBucketCount( + "Net.CertificateTransparency.CanInclusionCheckSCT", + certificate_transparency::CAN_BE_CHECKED, 1); + // The Aviator SCT should not be eligible for inclusion checking, because + // there is not a recent enough Aviator STH available. + histograms.ExpectBucketCount( + "Net.CertificateTransparency.CanInclusionCheckSCT", + certificate_transparency::NEWER_STH_REQUIRED, 1); + // The DigiCert SCT should not be eligible for inclusion checking, because + // there is no DigiCert STH available. + histograms.ExpectBucketCount( + "Net.CertificateTransparency.CanInclusionCheckSCT", + certificate_transparency::VALID_STH_REQUIRED, 1); +} + +} // namespace + +} // namespace network
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index ef667fb..2657d3e1 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -12,10 +12,15 @@ #include "base/memory/ptr_util.h" #include "base/metrics/field_trial_params.h" #include "base/task_scheduler/post_task.h" +#include "base/values.h" #include "build/build_config.h" +#include "components/certificate_transparency/sth_distributor.h" +#include "components/certificate_transparency/sth_observer.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/base/logging_network_change_observer.h" #include "net/base/network_change_notifier.h" +#include "net/cert/ct_log_response_parser.h" +#include "net/cert/signed_tree_head.h" #include "net/dns/host_resolver.h" #include "net/dns/mapped_host_resolver.h" #include "net/log/net_log.h" @@ -153,6 +158,8 @@ host_resolver_ = CreateHostResolver(); network_usage_accumulator_ = std::make_unique<NetworkUsageAccumulator>(); + sth_distributor_ = + std::make_unique<certificate_transparency::STHDistributor>(); } NetworkService::~NetworkService() { @@ -257,6 +264,14 @@ std::move(callback).Run(network_usage_accumulator_->GetTotalNetworkUsages()); } +void NetworkService::UpdateSignedTreeHead(const net::ct::SignedTreeHead& sth) { + sth_distributor_->NewSTHObserved(sth); +} + +certificate_transparency::STHReporter* NetworkService::sth_reporter() { + return sth_distributor_.get(); +} + void NetworkService::OnBindInterface( const service_manager::BindSourceInfo& source_info, const std::string& interface_name,
diff --git a/services/network/network_service.h b/services/network/network_service.h index cd76b69..f48fd50 100644 --- a/services/network/network_service.h +++ b/services/network/network_service.h
@@ -11,6 +11,7 @@ #include "base/component_export.h" #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "mojo/public/cpp/bindings/binding.h" #include "net/log/net_log.h" #include "services/network/keepalive_statistics_recorder.h" @@ -28,6 +29,11 @@ class URLRequestContext; } // namespace net +namespace certificate_transparency { +class STHDistributor; +class STHReporter; +} // namespace certificate_transparency + namespace network { class NetworkContext; @@ -102,6 +108,7 @@ mojom::NetworkChangeManagerRequest request) override; void GetTotalNetworkUsages( mojom::NetworkService::GetTotalNetworkUsagesCallback callback) override; + void UpdateSignedTreeHead(const net::ct::SignedTreeHead& sth) override; bool quic_disabled() const { return quic_disabled_; } bool HasRawHeadersAccess(uint32_t process_id) const; @@ -119,6 +126,8 @@ return network_usage_accumulator_.get(); } + certificate_transparency::STHReporter* sth_reporter(); + private: // service_manager::Service implementation. void OnBindInterface(const service_manager::BindSourceInfo& source_info, @@ -160,6 +169,8 @@ bool quic_disabled_ = false; + std::unique_ptr<certificate_transparency::STHDistributor> sth_distributor_; + DISALLOW_COPY_AND_ASSIGN(NetworkService); };
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn index f22f20b..5b1c347 100644 --- a/services/network/public/cpp/BUILD.gn +++ b/services/network/public/cpp/BUILD.gn
@@ -107,6 +107,7 @@ deps = [ "//base", "//ipc", + "//mojo/public/mojom/base", "//net", "//services/network/public/mojom:mojom_shared", ] @@ -129,10 +130,12 @@ "cors/cors_unittest.cc", "cors/preflight_cache_unittest.cc", "cors/preflight_result_unittest.cc", + "digitally_signed_mojom_traits_unittest.cc", "mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc", "mutable_partial_network_traffic_annotation_tag_mojom_traits_unittest.cc", "network_mojom_traits_unittest.cc", "proxy_config_mojom_traits_unittest.cc", + "signed_tree_head_mojom_traits_unittest.cc", "simple_url_loader_unittest.cc", ]
diff --git a/services/network/public/cpp/digitally_signed.typemap b/services/network/public/cpp/digitally_signed.typemap new file mode 100644 index 0000000..f18eaad --- /dev/null +++ b/services/network/public/cpp/digitally_signed.typemap
@@ -0,0 +1,19 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//services/network/public/mojom/digitally_signed.mojom" +public_headers = [ "//net/cert/signed_certificate_timestamp.h" ] +traits_headers = + [ "//services/network/public/cpp/digitally_signed_mojom_traits.h" ] +sources = [ + "//services/network/public/cpp/digitally_signed_mojom_traits.cc", +] +type_mappings = [ + "network.mojom.HashAlgorithm=net::ct::DigitallySigned::HashAlgorithm", + "network.mojom.SignatureAlgorithm=net::ct::DigitallySigned::SignatureAlgorithm", + "network.mojom.DigitallySigned=net::ct::DigitallySigned", +] +public_deps = [ + "//net", +]
diff --git a/services/network/public/cpp/digitally_signed_mojom_traits.cc b/services/network/public/cpp/digitally_signed_mojom_traits.cc new file mode 100644 index 0000000..b36efe6 --- /dev/null +++ b/services/network/public/cpp/digitally_signed_mojom_traits.cc
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/digitally_signed_mojom_traits.h" + +#include <vector> + +namespace mojo { + +// static +bool StructTraits<network::mojom::DigitallySignedDataView, + net::ct::DigitallySigned>:: + Read(network::mojom::DigitallySignedDataView data, + net::ct::DigitallySigned* out) { + std::vector<uint8_t> signature_data; + if (!data.ReadHashAlgorithm(&out->hash_algorithm) || + !data.ReadSignatureAlgorithm(&out->signature_algorithm) || + !data.ReadSignature(&signature_data)) { + return false; + } + if (signature_data.empty()) + return false; + out->signature_data.assign( + reinterpret_cast<const char*>(signature_data.data()), + signature_data.size()); + return true; +} + +} // namespace mojo
diff --git a/services/network/public/cpp/digitally_signed_mojom_traits.h b/services/network/public/cpp/digitally_signed_mojom_traits.h new file mode 100644 index 0000000..c01712a --- /dev/null +++ b/services/network/public/cpp/digitally_signed_mojom_traits.h
@@ -0,0 +1,133 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PUBLIC_CPP_DIGITALLY_SIGNED_MOJOM_TRAITS_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_DIGITALLY_SIGNED_MOJOM_TRAITS_H_ + +#include "base/containers/span.h" +#include "mojo/public/cpp/bindings/enum_traits.h" +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "net/cert/signed_certificate_timestamp.h" +#include "services/network/public/mojom/digitally_signed.mojom.h" + +namespace mojo { + +template <> +struct EnumTraits<network::mojom::HashAlgorithm, + net::ct::DigitallySigned::HashAlgorithm> { + static network::mojom::HashAlgorithm ToMojom( + net::ct::DigitallySigned::HashAlgorithm input) { + switch (input) { + case net::ct::DigitallySigned::HASH_ALGO_NONE: + return network::mojom::HashAlgorithm::HASH_ALGO_NONE; + case net::ct::DigitallySigned::HASH_ALGO_MD5: + return network::mojom::HashAlgorithm::HASH_ALGO_MD5; + case net::ct::DigitallySigned::HASH_ALGO_SHA1: + return network::mojom::HashAlgorithm::HASH_ALGO_SHA1; + case net::ct::DigitallySigned::HASH_ALGO_SHA224: + return network::mojom::HashAlgorithm::HASH_ALGO_SHA224; + case net::ct::DigitallySigned::HASH_ALGO_SHA256: + return network::mojom::HashAlgorithm::HASH_ALGO_SHA256; + case net::ct::DigitallySigned::HASH_ALGO_SHA384: + return network::mojom::HashAlgorithm::HASH_ALGO_SHA384; + case net::ct::DigitallySigned::HASH_ALGO_SHA512: + return network::mojom::HashAlgorithm::HASH_ALGO_SHA512; + } + NOTREACHED(); + return network::mojom::HashAlgorithm::HASH_ALGO_NONE; + } + + static bool FromMojom(network::mojom::HashAlgorithm input, + net::ct::DigitallySigned::HashAlgorithm* output) { + switch (input) { + case network::mojom::HashAlgorithm::HASH_ALGO_NONE: + *output = net::ct::DigitallySigned::HASH_ALGO_NONE; + return true; + case network::mojom::HashAlgorithm::HASH_ALGO_MD5: + *output = net::ct::DigitallySigned::HASH_ALGO_MD5; + return true; + case network::mojom::HashAlgorithm::HASH_ALGO_SHA1: + *output = net::ct::DigitallySigned::HASH_ALGO_SHA1; + return true; + case network::mojom::HashAlgorithm::HASH_ALGO_SHA224: + *output = net::ct::DigitallySigned::HASH_ALGO_SHA224; + return true; + case network::mojom::HashAlgorithm::HASH_ALGO_SHA256: + *output = net::ct::DigitallySigned::HASH_ALGO_SHA256; + return true; + case network::mojom::HashAlgorithm::HASH_ALGO_SHA384: + *output = net::ct::DigitallySigned::HASH_ALGO_SHA384; + return true; + case network::mojom::HashAlgorithm::HASH_ALGO_SHA512: + *output = net::ct::DigitallySigned::HASH_ALGO_SHA512; + return true; + } + NOTREACHED(); + return false; + } +}; + +template <> +struct EnumTraits<network::mojom::SignatureAlgorithm, + net::ct::DigitallySigned::SignatureAlgorithm> { + static network::mojom::SignatureAlgorithm ToMojom( + net::ct::DigitallySigned::SignatureAlgorithm input) { + switch (input) { + case net::ct::DigitallySigned::SIG_ALGO_ANONYMOUS: + return network::mojom::SignatureAlgorithm::SIG_ALGO_ANONYMOUS; + case net::ct::DigitallySigned::SIG_ALGO_RSA: + return network::mojom::SignatureAlgorithm::SIG_ALGO_RSA; + case net::ct::DigitallySigned::SIG_ALGO_DSA: + return network::mojom::SignatureAlgorithm::SIG_ALGO_DSA; + case net::ct::DigitallySigned::SIG_ALGO_ECDSA: + return network::mojom::SignatureAlgorithm::SIG_ALGO_ECDSA; + } + NOTREACHED(); + return network::mojom::SignatureAlgorithm::SIG_ALGO_ANONYMOUS; + } + + static bool FromMojom(network::mojom::SignatureAlgorithm input, + net::ct::DigitallySigned::SignatureAlgorithm* output) { + switch (input) { + case network::mojom::SignatureAlgorithm::SIG_ALGO_ANONYMOUS: + *output = net::ct::DigitallySigned::SIG_ALGO_ANONYMOUS; + return true; + case network::mojom::SignatureAlgorithm::SIG_ALGO_RSA: + *output = net::ct::DigitallySigned::SIG_ALGO_RSA; + return true; + case network::mojom::SignatureAlgorithm::SIG_ALGO_DSA: + *output = net::ct::DigitallySigned::SIG_ALGO_DSA; + return true; + case network::mojom::SignatureAlgorithm::SIG_ALGO_ECDSA: + *output = net::ct::DigitallySigned::SIG_ALGO_ECDSA; + return true; + } + NOTREACHED(); + return false; + } +}; + +template <> +struct StructTraits<network::mojom::DigitallySignedDataView, + net::ct::DigitallySigned> { + static net::ct::DigitallySigned::HashAlgorithm hash_algorithm( + const net::ct::DigitallySigned& obj) { + return obj.hash_algorithm; + } + static net::ct::DigitallySigned::SignatureAlgorithm signature_algorithm( + const net::ct::DigitallySigned& obj) { + return obj.signature_algorithm; + } + static base::span<const uint8_t> signature( + const net::ct::DigitallySigned& obj) { + return base::as_bytes(base::make_span(obj.signature_data)); + } + + static bool Read(network::mojom::DigitallySignedDataView obj, + net::ct::DigitallySigned* out); +}; + +} // namespace mojo + +#endif // SERVICES_NETWORK_PUBLIC_CPP_DIGITALLY_SIGNED_MOJOM_TRAITS_H_
diff --git a/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc b/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc new file mode 100644 index 0000000..7272e5e --- /dev/null +++ b/services/network/public/cpp/digitally_signed_mojom_traits_unittest.cc
@@ -0,0 +1,69 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/digitally_signed_mojom_traits.h" + +#include "base/test/gtest_util.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "net/cert/signed_certificate_timestamp.h" +#include "services/network/public/mojom/digitally_signed.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { +namespace { + +TEST(DigitallySignedTraitsTest, Roundtrips) { + for (auto sig_alg : {net::ct::DigitallySigned::SIG_ALGO_ANONYMOUS, + net::ct::DigitallySigned::SIG_ALGO_RSA, + net::ct::DigitallySigned::SIG_ALGO_DSA, + net::ct::DigitallySigned::SIG_ALGO_ECDSA}) { + for (auto hash_alg : {net::ct::DigitallySigned::HASH_ALGO_NONE, + net::ct::DigitallySigned::HASH_ALGO_MD5, + net::ct::DigitallySigned::HASH_ALGO_SHA1, + net::ct::DigitallySigned::HASH_ALGO_SHA224, + net::ct::DigitallySigned::HASH_ALGO_SHA256, + net::ct::DigitallySigned::HASH_ALGO_SHA384, + net::ct::DigitallySigned::HASH_ALGO_SHA512}) { + net::ct::DigitallySigned original; + original.hash_algorithm = hash_alg; + original.signature_algorithm = sig_alg; + original.signature_data.assign(5, static_cast<char>(hash_alg)); + + net::ct::DigitallySigned copied; + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>( + &original, &copied)) + << "with hash " << hash_alg << " and sig " << sig_alg; + EXPECT_EQ(original.hash_algorithm, copied.hash_algorithm); + EXPECT_EQ(original.signature_algorithm, copied.signature_algorithm); + EXPECT_EQ(original.signature_data, copied.signature_data); + } + } +} + +TEST(DigitallySignedTraitsTest, EmptySignatureRejected) { + net::ct::DigitallySigned original; + original.hash_algorithm = net::ct::DigitallySigned::HASH_ALGO_SHA256; + original.signature_algorithm = net::ct::DigitallySigned::SIG_ALGO_ECDSA; + original.signature_data.clear(); + + net::ct::DigitallySigned copied; + EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>( + &original, &copied)); +} + +TEST(DigitallySignedTraitsTest, OutOfBoundsEnumsRejected) { + net::ct::DigitallySigned original; + original.hash_algorithm = + static_cast<net::ct::DigitallySigned::HashAlgorithm>(-1); + original.signature_algorithm = net::ct::DigitallySigned::SIG_ALGO_ECDSA; + original.signature_data.assign(32, '\x01'); + + net::ct::DigitallySigned copied; + EXPECT_DCHECK_DEATH( + mojo::test::SerializeAndDeserialize<mojom::DigitallySigned>(&original, + &copied)); +} + +} // namespace +} // namespace network
diff --git a/services/network/public/cpp/signed_tree_head.typemap b/services/network/public/cpp/signed_tree_head.typemap new file mode 100644 index 0000000..92dbaee --- /dev/null +++ b/services/network/public/cpp/signed_tree_head.typemap
@@ -0,0 +1,18 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//services/network/public/mojom/signed_tree_head.mojom" +public_headers = [ "//net/cert/signed_tree_head.h" ] +traits_headers = + [ "//services/network/public/cpp/signed_tree_head_mojom_traits.h" ] +sources = [ + "//services/network/public/cpp/signed_tree_head_mojom_traits.cc", +] +type_mappings = [ + "network.mojom.SignedTreeHead=net::ct::SignedTreeHead", + "network.mojom.SignedTreeHeadVersion=net::ct::SignedTreeHead::Version", +] +public_deps = [ + "//net", +]
diff --git a/services/network/public/cpp/signed_tree_head_mojom_traits.cc b/services/network/public/cpp/signed_tree_head_mojom_traits.cc new file mode 100644 index 0000000..9195950 --- /dev/null +++ b/services/network/public/cpp/signed_tree_head_mojom_traits.cc
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/signed_tree_head_mojom_traits.h" + +#include <memory> +#include <vector> + +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "services/network/public/cpp/digitally_signed_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits< + network::mojom::SignedTreeHeadDataView, + net::ct::SignedTreeHead>::Read(network::mojom::SignedTreeHeadDataView data, + net::ct::SignedTreeHead* out) { + std::vector<uint8_t> sha256_root_hash; + if (!data.ReadVersion(&out->version) || + !data.ReadTimestamp(&out->timestamp) || + !data.ReadSignature(&out->signature) || !data.ReadLogId(&out->log_id) || + !data.ReadSha256RootHash(&sha256_root_hash)) { + return false; + } + if (out->log_id.empty()) { + return false; + } + + out->tree_size = data.tree_size(); + + // The Mojo bindings should have validated the size constraint as part of + // ReadSha256RootHash(). + DCHECK_EQ(sha256_root_hash.size(), sizeof(out->sha256_root_hash)); + memcpy(out->sha256_root_hash, sha256_root_hash.data(), + sizeof(out->sha256_root_hash)); + + return true; +} + +} // namespace mojo
diff --git a/services/network/public/cpp/signed_tree_head_mojom_traits.h b/services/network/public/cpp/signed_tree_head_mojom_traits.h new file mode 100644 index 0000000..f38cf4c7 --- /dev/null +++ b/services/network/public/cpp/signed_tree_head_mojom_traits.h
@@ -0,0 +1,75 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PUBLIC_CPP_SIGNED_TREE_HEAD_MOJOM_TRAITS_H_ +#define SERVICES_NETWORK_PUBLIC_CPP_SIGNED_TREE_HEAD_MOJOM_TRAITS_H_ + +#include "base/containers/span.h" +#include "base/strings/string_piece.h" +#include "base/time/time.h" +#include "mojo/public/cpp/bindings/enum_traits.h" +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "net/cert/signed_tree_head.h" +#include "services/network/public/mojom/digitally_signed.mojom.h" +#include "services/network/public/mojom/signed_tree_head.mojom.h" + +namespace mojo { + +template <> +struct EnumTraits<network::mojom::SignedTreeHeadVersion, + net::ct::SignedTreeHead::Version> { + static network::mojom::SignedTreeHeadVersion ToMojom( + net::ct::SignedTreeHead::Version input) { + switch (input) { + case net::ct::SignedTreeHead::V1: + return network::mojom::SignedTreeHeadVersion::V1; + } + NOTREACHED(); + return network::mojom::SignedTreeHeadVersion::kMaxValue; + } + + static bool FromMojom(network::mojom::SignedTreeHeadVersion input, + net::ct::SignedTreeHead::Version* output) { + switch (input) { + case network::mojom::SignedTreeHeadVersion::V1: + *output = net::ct::SignedTreeHead::V1; + return true; + } + NOTREACHED(); + return false; + } +}; + +template <> +struct StructTraits<network::mojom::SignedTreeHeadDataView, + net::ct::SignedTreeHead> { + static net::ct::SignedTreeHead::Version version( + const net::ct::SignedTreeHead& sth) { + return sth.version; + } + static base::Time timestamp(const net::ct::SignedTreeHead& sth) { + return sth.timestamp; + } + static uint64_t tree_size(const net::ct::SignedTreeHead& sth) { + return sth.tree_size; + } + static base::span<const uint8_t> sha256_root_hash( + const net::ct::SignedTreeHead& sth) { + return base::as_bytes(base::make_span(sth.sha256_root_hash)); + } + static const net::ct::DigitallySigned& signature( + const net::ct::SignedTreeHead& sth) { + return sth.signature; + } + static base::StringPiece log_id(const net::ct::SignedTreeHead& sth) { + return sth.log_id; + } + + static bool Read(network::mojom::SignedTreeHeadDataView obj, + net::ct::SignedTreeHead* out); +}; + +} // namespace mojo + +#endif // SERVICES_NETWORK_PUBLIC_CPP_SIGNED_TREE_HEAD_MOJOM_TRAITS_H_
diff --git a/services/network/public/cpp/signed_tree_head_mojom_traits_unittest.cc b/services/network/public/cpp/signed_tree_head_mojom_traits_unittest.cc new file mode 100644 index 0000000..3742b832 --- /dev/null +++ b/services/network/public/cpp/signed_tree_head_mojom_traits_unittest.cc
@@ -0,0 +1,64 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/signed_tree_head_mojom_traits.h" + +#include "base/time/time.h" +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "net/cert/signed_certificate_timestamp.h" +#include "net/cert/signed_tree_head.h" +#include "net/test/ct_test_util.h" +#include "services/network/public/cpp/digitally_signed_mojom_traits.h" +#include "services/network/public/mojom/signed_tree_head.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { +namespace { + +TEST(SignedTreeHeadTraitsTest, Roundtrips) { + net::ct::SignedTreeHead original; + net::ct::SignedTreeHead copied; + + // First try with a populated STH. + ASSERT_TRUE(net::ct::GetSampleSignedTreeHead(&original)); + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( + &original, &copied)); + EXPECT_EQ(original, copied); + + // Then try an STH for an empty tree. + ASSERT_TRUE(net::ct::GetSampleEmptySignedTreeHead(&original)); + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( + &original, &copied)); + EXPECT_EQ(original, copied); + + // Then try a syntactically-valid but semantically-bad STH. + ASSERT_TRUE(net::ct::GetBadEmptySignedTreeHead(&original)); + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( + &original, &copied)); + EXPECT_EQ(original, copied); +} + +TEST(SignedTreeHeadTraitsTest, RequiresLogId) { + net::ct::SignedTreeHead original; + ASSERT_TRUE(net::ct::GetSampleSignedTreeHead(&original)); + original.log_id.clear(); + + net::ct::SignedTreeHead copied; + EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( + &original, &copied)); +} + +TEST(SignedTreeHeadTraitsTest, RequiresValidDigitallySigned) { + net::ct::SignedTreeHead original; + ASSERT_TRUE(net::ct::GetSampleSignedTreeHead(&original)); + original.signature.signature_data.clear(); + + net::ct::SignedTreeHead copied; + EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( + &original, &copied)); +} + +} // namespace +} // namespace network
diff --git a/services/network/public/cpp/typemaps.gni b/services/network/public/cpp/typemaps.gni index 48f0b228..515e5e9 100644 --- a/services/network/public/cpp/typemaps.gni +++ b/services/network/public/cpp/typemaps.gni
@@ -5,6 +5,7 @@ typemaps = [ "//services/network/public/cpp/cookie_manager.typemap", "//services/network/public/cpp/cors_error_status.typemap", + "//services/network/public/cpp/digitally_signed.typemap", "//services/network/public/cpp/http_request_headers.typemap", "//services/network/public/cpp/mutable_network_traffic_annotation_tag.typemap", "//services/network/public/cpp/mutable_partial_network_traffic_annotation_tag.typemap", @@ -12,6 +13,7 @@ "//services/network/public/cpp/network_types.typemap", "//services/network/public/cpp/proxy_config.typemap", "//services/network/public/cpp/proxy_config_with_annotation.typemap", + "//services/network/public/cpp/signed_tree_head.typemap", "//services/network/public/cpp/url_loader_completion_status.typemap", "//services/network/public/cpp/url_request.typemap", "//services/network/public/cpp/url_request_redirect_info.typemap",
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index 3822279..534ad7b93 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -75,6 +75,8 @@ sources = [ "cookie_manager.mojom", "cors.mojom", + "ct_log_info.mojom", + "digitally_signed.mojom", "fetch_api.mojom", "http_request_headers.mojom", "network_change_manager.mojom", @@ -86,7 +88,9 @@ "proxy_config_with_annotation.mojom", "request_context_frame_type.mojom", "restricted_cookie_manager.mojom", + "signed_tree_head.mojom", "tcp_socket.mojom", + "tls_socket.mojom", "url_loader.mojom", "url_loader_factory.mojom", ]
diff --git a/services/network/public/mojom/ct_log_info.mojom b/services/network/public/mojom/ct_log_info.mojom new file mode 100644 index 0000000..f4c26f7 --- /dev/null +++ b/services/network/public/mojom/ct_log_info.mojom
@@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module network.mojom; + +// A single Certificate Transparency Log configuration. +struct CTLogInfo { + // The DER-encoded SubjectPublicKeyInfo of the log. + // TODO(rsleevi): Convert this to array<uint8> when net::CTLogVerifier uses + // base::span<> + string public_key; + + // The human-readable, log-supplied log name. Note that this will not be + // translated. + string name; + + // The DNS API endpoint for the log. + // This will be used as the parent domain for all queries about the log. + // See https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md + string dns_api_endpoint; +};
diff --git a/services/network/public/mojom/digitally_signed.mojom b/services/network/public/mojom/digitally_signed.mojom new file mode 100644 index 0000000..c1263443 --- /dev/null +++ b/services/network/public/mojom/digitally_signed.mojom
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +module network.mojom; + +// Mirror of net::ct::DigitallySigned::HashAlgorithm +enum HashAlgorithm { + HASH_ALGO_NONE = 0, + HASH_ALGO_MD5 = 1, + HASH_ALGO_SHA1 = 2, + HASH_ALGO_SHA224 = 3, + HASH_ALGO_SHA256 = 4, + HASH_ALGO_SHA384 = 5, + HASH_ALGO_SHA512 = 6 +}; + +// Mirror of net::ct::DigitallySigned::SignatureAlgorithm +enum SignatureAlgorithm { + SIG_ALGO_ANONYMOUS = 0, + SIG_ALGO_RSA = 1, + SIG_ALGO_DSA = 2, + SIG_ALGO_ECDSA = 3 +}; + +// Mirror of net::ct::DigitallySigned +struct DigitallySigned { + HashAlgorithm hash_algorithm; + SignatureAlgorithm signature_algorithm; + array<uint8> signature; +};
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom index d643a72..72b64f0 100644 --- a/services/network/public/mojom/network_service.mojom +++ b/services/network/public/mojom/network_service.mojom
@@ -11,6 +11,7 @@ import "net/interfaces/address_list.mojom"; import "net/interfaces/ip_endpoint.mojom"; import "services/network/public/mojom/cookie_manager.mojom"; +import "services/network/public/mojom/ct_log_info.mojom"; import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom"; import "services/network/public/mojom/network_change_manager.mojom"; import "services/network/public/mojom/proxy_config.mojom"; @@ -19,6 +20,7 @@ import "services/network/public/mojom/udp_socket.mojom"; import "services/network/public/mojom/url_loader.mojom"; import "services/network/public/mojom/network_param.mojom"; +import "services/network/public/mojom/signed_tree_head.mojom"; import "services/network/public/mojom/url_loader_factory.mojom"; import "services/network/public/mojom/websocket.mojom"; import "services/proxy_resolver/public/mojom/proxy_resolver.mojom"; @@ -90,6 +92,14 @@ // Must be false if built without FTP support. bool enable_ftp_url_support = false; + // True if the "Certificate Transparency in Chrome" policy (see + // https://github.com/chromium/ct-policy/blob/master/ct_policy.md) should + // be enforced for certificates and connections. + // + // See //net/docs/certificate-transparency.md before setting this flag to + // true. + bool enforce_chrome_ct_policy = false; + // Enables HTTP/0.9 on ports other than 80 for HTTP and 443 for HTTPS. bool http_09_on_non_default_ports_enabled = false; @@ -129,6 +139,11 @@ // The GSSAPI library name. // Only used on (OS_POSIX && !OS_ANDROID) platform. string gssapi_library_name; + + // The Certificate Transparency logs that are known to the client. SCTs from + // these logs will be extracted and verified; other SCTs will be treated as + // unrecognized. + array<CTLogInfo> ct_logs; }; struct NetworkConditions { @@ -348,7 +363,7 @@ net.interfaces.AddressList remote_addr_list, MutableNetworkTrafficAnnotationTag traffic_annotation, TCPConnectedSocket& socket, - TCPConnectedSocketObserver? observer) + SocketObserver? observer) => (int32 result, handle<data_pipe_consumer>? receive_stream, handle<data_pipe_producer>? send_stream); @@ -470,4 +485,9 @@ // Gets the accumulated network usage since the start/restart of the service. GetTotalNetworkUsages() => (array<NetworkUsage> total_network_usages); + + // Update Signed Tree Heads (STH) used in the handling of Certificate + // Transparency. Broadcast to each NetworkContext using the NetworkService. + // NetworkContextes ignore STHs from unrecognized logs. + UpdateSignedTreeHead(SignedTreeHead signed_tree_head); };
diff --git a/services/network/public/mojom/signed_tree_head.mojom b/services/network/public/mojom/signed_tree_head.mojom new file mode 100644 index 0000000..6296dc6 --- /dev/null +++ b/services/network/public/mojom/signed_tree_head.mojom
@@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +module network.mojom; + +import "mojo/public/mojom/base/time.mojom"; +import "services/network/public/mojom/digitally_signed.mojom"; + +// Mirror of net::ct::SignedTreeHead::Version +enum SignedTreeHeadVersion { + // The Version enum in RFC 6962, Section 3.2. + V1 = 0, +}; + +// Mirror of net::ct::SignedTreeHead. +// These fields are defined in Section 3.5 and Section 4.3 of RFC 6962. +struct SignedTreeHead { + SignedTreeHeadVersion version; + mojo_base.mojom.Time timestamp; + uint64 tree_size; + array<uint8, 32> sha256_root_hash; + DigitallySigned signature; + + // Added in RFC6962-bis, Appendix A, but useful with RFC 6962 to track + // which log a given STH is associated with. + string log_id; +};
diff --git a/services/network/public/mojom/tcp_socket.mojom b/services/network/public/mojom/tcp_socket.mojom index 3606f47..9359e8b2 100644 --- a/services/network/public/mojom/tcp_socket.mojom +++ b/services/network/public/mojom/tcp_socket.mojom
@@ -5,10 +5,13 @@ module network.mojom; import "net/interfaces/ip_endpoint.mojom"; +import "services/network/public/mojom/tls_socket.mojom"; +import "services/network/public/mojom/network_param.mojom"; +import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom"; // Represents a connected TCP socket. Writes and Reads are through the data // pipes supplied upon construction. Consumer should use -// TCPConnectedSocketObserver interface to get notified about any error occurred +// SocketObserver interface to get notified about any error occurred // during reading or writing to data pipes. Consumer can close the socket by // destroying the interface pointer. interface TCPConnectedSocket { @@ -16,13 +19,28 @@ // net::OK and |local_addr| contains the local address of the socket. On // failure, |local_addr| is null and |net_error| is a net error code. GetLocalAddress() => (int32 net_error, net.interfaces.IPEndPoint? local_addr); + + // Upgrades a TCP socket to a TLS client socket. + // IMPORTANT: Caller needs close the previous send and receive pipes before + // this method can complete asynchronously. + // + // On success, |net_error| is net::OK. Caller is to use |send_stream| to send + // data and |receive_stream| to receive data over the connection. On failure, + // |result| is a network error code. + UpgradeToTLS(HostPortPair host_port_pair, + MutableNetworkTrafficAnnotationTag traffic_annotation, + TLSClientSocket& request, + SocketObserver? observer) + => (int32 net_error, + handle<data_pipe_consumer>? receive_stream, + handle<data_pipe_producer>? send_stream); }; -// Interface to listen for network connection error on a TCPConnectedSocket. -// Because data pipe doesn't surface any network connection error, if a network -// error happens during a read or a write, consumer can find out about it by -// implementing this interface. -interface TCPConnectedSocketObserver { +// Interface to listen for network connection error on a TCPConnectedSocket or +// a TLSClientSocket. Because data pipe doesn't surface any network connection +// error, if a network error happens during a read or a write, consumer can find +// out about it by implementing this interface. +interface SocketObserver { // Called when an error occurs during reading from the network. The producer // side of |receive_stream| will be closed. OnReadError(int32 net_error); @@ -45,7 +63,7 @@ // |backlog| is a number that is specified when requesting TCPServerSocket. If // more than |backlog| number of Accept()s are outstanding, // net::ERR_INSUFFICIENT_RESOUCES will be returned. - Accept(TCPConnectedSocketObserver? observer) + Accept(SocketObserver? observer) => (int32 net_error, net.interfaces.IPEndPoint? remote_addr, TCPConnectedSocket? connected_socket,
diff --git a/services/network/public/mojom/tls_socket.mojom b/services/network/public/mojom/tls_socket.mojom new file mode 100644 index 0000000..131edc2 --- /dev/null +++ b/services/network/public/mojom/tls_socket.mojom
@@ -0,0 +1,15 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module network.mojom; + +import "net/interfaces/ip_endpoint.mojom"; + +// Represents a connected TLS client socket. Writes and Reads are through the +// data pipes supplied upon construction. Consumer should use SocketObserver +// interface to get notified about any error occurred during reading or writing +// to data pipes. Consumer can close the socket by destroying the interface +// pointer. +interface TLSClientSocket { +};
diff --git a/services/network/socket_data_pump.cc b/services/network/socket_data_pump.cc index 5157ca77..d0e70a4 100644 --- a/services/network/socket_data_pump.cc +++ b/services/network/socket_data_pump.cc
@@ -16,20 +16,23 @@ #include "net/log/net_log.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" +#include "services/network/tls_client_socket.h" namespace network { SocketDataPump::SocketDataPump( - mojom::TCPConnectedSocketObserverPtr observer, net::StreamSocket* socket, + Delegate* delegate, mojo::ScopedDataPipeProducerHandle receive_pipe_handle, mojo::ScopedDataPipeConsumerHandle send_pipe_handle, const net::NetworkTrafficAnnotationTag& traffic_annotation) - : observer_(std::move(observer)), - socket_(socket), + : socket_(socket), + delegate_(delegate), receive_stream_(std::move(receive_pipe_handle)), receive_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), + receive_stream_close_watcher_(FROM_HERE, + mojo::SimpleWatcher::ArmingPolicy::MANUAL), send_stream_(std::move(send_pipe_handle)), send_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), @@ -45,6 +48,10 @@ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, base::BindRepeating(&SocketDataPump::OnReceiveStreamWritable, base::Unretained(this))); + receive_stream_close_watcher_.Watch( + receive_stream_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, + base::BindRepeating(&SocketDataPump::OnReceiveStreamClosed, + base::Unretained(this))); ReceiveMore(); SendMore(); } @@ -53,11 +60,11 @@ void SocketDataPump::ReceiveMore() { DCHECK(receive_stream_.is_valid()); - DCHECK(!pending_receive_buffer_); uint32_t num_bytes = 0; + scoped_refptr<NetToMojoPendingBuffer> pending_receive_buffer; MojoResult result = NetToMojoPendingBuffer::BeginWrite( - &receive_stream_, &pending_receive_buffer_, &num_bytes); + &receive_stream_, &pending_receive_buffer, &num_bytes); if (result == MOJO_RESULT_SHOULD_WAIT) { receive_stream_watcher_.ArmOrNotify(); return; @@ -66,22 +73,36 @@ ShutdownReceive(); return; } - DCHECK(pending_receive_buffer_); + DCHECK(pending_receive_buffer); scoped_refptr<net::IOBuffer> buf = - base::MakeRefCounted<NetToMojoIOBuffer>(pending_receive_buffer_.get()); + base::MakeRefCounted<NetToMojoIOBuffer>(pending_receive_buffer.get()); // Use WeakPtr here because |this| doesn't outlive |socket_|. - int read_result = - socket_->Read(buf.get(), base::saturated_cast<int>(num_bytes), - base::BindRepeating(&SocketDataPump::OnNetworkReadCompleted, - weak_factory_.GetWeakPtr())); - if (read_result == net::ERR_IO_PENDING) + int read_result = socket_->ReadIfReady( + buf.get(), base::saturated_cast<int>(num_bytes), + base::BindRepeating(&SocketDataPump::OnNetworkReadIfReadyCompleted, + weak_factory_.GetWeakPtr())); + receive_stream_ = + pending_receive_buffer->Complete(read_result >= 0 ? read_result : 0); + if (read_result == net::ERR_IO_PENDING) { + read_if_ready_pending_ = true; + receive_stream_close_watcher_.ArmOrNotify(); return; - OnNetworkReadCompleted(read_result); + } + // Handle EOF. + if (read_result == net::OK) { + ShutdownReceive(); + return; + } + OnNetworkReadIfReadyCompleted(read_result); +} + +void SocketDataPump::OnReceiveStreamClosed(MojoResult result) { + ShutdownReceive(); + return; } void SocketDataPump::OnReceiveStreamWritable(MojoResult result) { DCHECK(receive_stream_.is_valid()); - DCHECK(!pending_receive_buffer_); if (result != MOJO_RESULT_OK) { ShutdownReceive(); @@ -90,17 +111,17 @@ ReceiveMore(); } -void SocketDataPump::OnNetworkReadCompleted(int result) { - DCHECK(!receive_stream_.is_valid()); - DCHECK(pending_receive_buffer_); +void SocketDataPump::OnNetworkReadIfReadyCompleted(int result) { + DCHECK(receive_stream_.is_valid()); + if (read_if_ready_pending_) { + DCHECK_GE(net::OK, result); + read_if_ready_pending_ = false; + } - if (result < 0 && observer_) - observer_->OnReadError(result); + if (result < 0 && delegate_) + delegate_->OnNetworkReadError(result); - receive_stream_ = pending_receive_buffer_->Complete(result >= 0 ? result : 0); - pending_receive_buffer_ = nullptr; - - if (result <= 0) { + if (result < 0) { ShutdownReceive(); return; } @@ -109,11 +130,16 @@ void SocketDataPump::ShutdownReceive() { DCHECK(receive_stream_.is_valid()); - DCHECK(!pending_receive_buffer_); receive_stream_watcher_.Cancel(); - pending_receive_buffer_ = nullptr; + receive_stream_close_watcher_.Cancel(); receive_stream_.reset(); + if (read_if_ready_pending_) { + int result = socket_->CancelReadIfReady(); + DCHECK_EQ(net::OK, result); + read_if_ready_pending_ = false; + } + MaybeNotifyDelegate(); } void SocketDataPump::SendMore() { @@ -161,8 +187,8 @@ DCHECK(pending_send_buffer_); DCHECK(!send_stream_.is_valid()); - if (result < 0 && observer_) - observer_->OnWriteError(result); + if (result < 0 && delegate_) + delegate_->OnNetworkWriteError(result); // Partial write is possible. pending_send_buffer_->CompleteRead(result >= 0 ? result : 0); @@ -183,6 +209,13 @@ send_stream_watcher_.Cancel(); pending_send_buffer_ = nullptr; send_stream_.reset(); + MaybeNotifyDelegate(); +} + +void SocketDataPump::MaybeNotifyDelegate() { + if (!delegate_ || send_stream_.is_valid() || receive_stream_.is_valid()) + return; + delegate_->OnShutdown(); } } // namespace network
diff --git a/services/network/socket_data_pump.h b/services/network/socket_data_pump.h index 6a4c550..6b36a21 100644 --- a/services/network/socket_data_pump.h +++ b/services/network/socket_data_pump.h
@@ -31,27 +31,49 @@ // pipe. Specifically, it (1) reads from the network socket and writes to a mojo // producer pipe, and (2) reads from a mojo consumer pipe and writes to the // network socket. On network read/write errors, it (3) also notifies the -// mojom::TCPConnectedSocketObserverPtr appropriately. +// mojom::SocketObserverPtr appropriately. class COMPONENT_EXPORT(NETWORK_SERVICE) SocketDataPump { public: + // Interface to notify a consumer that about network errors and whether both + // data pipes have been shut down from the client side. + class Delegate { + public: + Delegate() {} + ~Delegate() {} + + // Called when SocketDataPump detects a network read error. + virtual void OnNetworkReadError(int net_error) = 0; + + // Called when SocketDataPump detects a network write error. + virtual void OnNetworkWriteError(int net_error) = 0; + + // Called when SocketDataPump detects both send and receive pipes have shut + // down. + virtual void OnShutdown() = 0; + }; + // Constructs a data pump that pumps data between |socket| and mojo data // pipe handles. Data are read from |send_pipe_handle| and sent to |socket|. // Data are read from |socket| and written to |receive_pipe_handle|. // |traffic_annotation| is attached to all writes to |socket|. Note that // |socket| must outlive |this|. - SocketDataPump(mojom::TCPConnectedSocketObserverPtr observer, - net::StreamSocket* socket, + SocketDataPump(net::StreamSocket* socket, + Delegate* delegate, mojo::ScopedDataPipeProducerHandle receive_pipe_handle, mojo::ScopedDataPipeConsumerHandle send_pipe_handle, const net::NetworkTrafficAnnotationTag& traffic_annotation); ~SocketDataPump(); private: + // Maybe notifies |delegate_| of the shutdown if both pipes are closed. + void MaybeNotifyDelegate(); + // "Receiving" in this context means reading from |socket_| and writing to // the Mojo |receive_stream_|. void ReceiveMore(); void OnReceiveStreamWritable(MojoResult result); - void OnNetworkReadCompleted(int result); + void OnReceiveStreamClosed(MojoResult result); + void OnNetworkReadIfReadyCompleted(int result); void ShutdownReceive(); // "Writing" is reading from the Mojo |send_stream_| and writing to the @@ -61,9 +83,8 @@ void OnNetworkWriteCompleted(int result); void ShutdownSend(); - mojom::TCPConnectedSocketObserverPtr observer_; - - net::StreamSocket* socket_; + net::StreamSocket* const socket_; + Delegate* const delegate_; // The *stream handles will be null when there's a pending read from |socket_| // to |pending_receive_buffer_|, or while there is a pending write from @@ -75,8 +96,13 @@ // For reading from the network and writing to Mojo pipe. mojo::ScopedDataPipeProducerHandle receive_stream_; - scoped_refptr<NetToMojoPendingBuffer> pending_receive_buffer_; mojo::SimpleWatcher receive_stream_watcher_; + // A separate watcher is needed to observe |receive_stream_|'s close event, so + // that when the client shuts down their end of the pipe for + // TCPConnectedSocket::UpgradeToTLS() during the waiting of the async callback + // of ReadIfReady, |this| can be notified of the shutdown. + mojo::SimpleWatcher receive_stream_close_watcher_; + bool read_if_ready_pending_ = false; // For reading from the Mojo pipe and writing to the network. mojo::ScopedDataPipeConsumerHandle send_stream_;
diff --git a/services/network/socket_data_pump_unittest.cc b/services/network/socket_data_pump_unittest.cc index b2f28b1..208449e 100644 --- a/services/network/socket_data_pump_unittest.cc +++ b/services/network/socket_data_pump_unittest.cc
@@ -19,6 +19,7 @@ #include "net/socket/socket_test_util.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request_test_util.h" +#include "services/network/mojo_socket_test_util.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/udp_socket.mojom.h" #include "services/network/socket_factory.h" @@ -28,25 +29,13 @@ namespace network { -namespace { - -class TestSocketObserver : public mojom::TCPConnectedSocketObserver { +// Test delegate to wait on network read/write errors. +class TestSocketDataPumpDelegate : public SocketDataPump::Delegate { public: - TestSocketObserver() : binding_(this) {} - ~TestSocketObserver() override { - EXPECT_EQ(net::OK, read_error_); - EXPECT_EQ(net::OK, write_error_); - } + TestSocketDataPumpDelegate() {} + ~TestSocketDataPumpDelegate() {} - // Returns a mojo pointer. This can only be called once. - mojom::TCPConnectedSocketObserverPtr GetObserverPtr() { - DCHECK(!binding_); - mojom::TCPConnectedSocketObserverPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; - } - - // Waits for Read and Write error. Returns the error observed. + // Waits for read error. Returns the error observed. int WaitForReadError() { read_loop_.Run(); int error = read_error_; @@ -54,6 +43,7 @@ return error; } + // Waits for write error. Returns the error observed. int WaitForWriteError() { write_loop_.Run(); int error = write_error_; @@ -61,29 +51,29 @@ return error; } + // Waits for shutdown. + void WaitForShutdown() { shutdown_loop_.Run(); } + private: - // mojom::TCPConnectedSocketObserver implementation. - void OnReadError(int net_error) override { - read_error_ = net_error; + void OnNetworkReadError(int error) override { + read_error_ = error; read_loop_.Quit(); } - - void OnWriteError(int net_error) override { - write_error_ = net_error; + void OnNetworkWriteError(int error) override { + write_error_ = error; write_loop_.Quit(); } + void OnShutdown() override { shutdown_loop_.Quit(); } int read_error_ = net::OK; int write_error_ = net::OK; base::RunLoop read_loop_; base::RunLoop write_loop_; - mojo::Binding<mojom::TCPConnectedSocketObserver> binding_; + base::RunLoop shutdown_loop_; - DISALLOW_COPY_AND_ASSIGN(TestSocketObserver); + DISALLOW_COPY_AND_ASSIGN(TestSocketDataPumpDelegate); }; -} // namespace - class SocketDataPumpTest : public testing::Test, public ::testing::WithParamInterface<net::IoMode> { public: @@ -96,6 +86,7 @@ // to populate the read/write data of the mock socket. void Init(net::StaticSocketDataProvider* data_provider) { mock_client_socket_factory_.AddSocketDataProvider(data_provider); + mock_client_socket_factory_.set_enable_read_if_ready(true); mojo::DataPipe send_pipe; mojo::DataPipe receive_pipe; receive_handle_ = std::move(receive_pipe.consumer_handle); @@ -109,8 +100,7 @@ result = callback.WaitForResult(); EXPECT_EQ(net::OK, result); data_pump_ = std::make_unique<SocketDataPump>( - test_observer_.GetObserverPtr(), socket_.get(), - std::move(receive_pipe.producer_handle), + socket_.get(), delegate(), std::move(receive_pipe.producer_handle), std::move(send_pipe.consumer_handle), TRAFFIC_ANNOTATION_FOR_TESTS); } @@ -134,7 +124,7 @@ return received_contents; } - TestSocketObserver* observer() { return &test_observer_; } + TestSocketDataPumpDelegate* delegate() { return &test_delegate_; } mojo::ScopedDataPipeConsumerHandle receive_handle_; mojo::ScopedDataPipeProducerHandle send_handle_; @@ -142,7 +132,7 @@ private: base::test::ScopedTaskEnvironment scoped_task_environment_; net::MockClientSocketFactory mock_client_socket_factory_; - TestSocketObserver test_observer_; + TestSocketDataPumpDelegate test_delegate_; std::unique_ptr<net::StreamSocket> socket_; std::unique_ptr<SocketDataPump> data_pump_; @@ -253,7 +243,7 @@ net::StaticSocketDataProvider data_provider(reads, writes); Init(&data_provider); EXPECT_EQ("", Read(&receive_handle_, 1)); - EXPECT_EQ(net::ERR_FAILED, observer()->WaitForReadError()); + EXPECT_EQ(net::ERR_FAILED, delegate()->WaitForReadError()); // Writes can proceed even though there is a read error. uint32_t num_bytes = strlen(kTestMsg); EXPECT_EQ(MOJO_RESULT_OK, send_handle_->WriteData(&kTestMsg, &num_bytes, @@ -277,7 +267,7 @@ EXPECT_EQ(MOJO_RESULT_OK, send_handle_->WriteData(&kTestMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); EXPECT_EQ(strlen(kTestMsg), num_bytes); - EXPECT_EQ(net::ERR_FAILED, observer()->WaitForWriteError()); + EXPECT_EQ(net::ERR_FAILED, delegate()->WaitForWriteError()); // Reads can proceed even though there is a read error. EXPECT_EQ(kTestMsg, Read(&receive_handle_, strlen(kTestMsg))); @@ -286,4 +276,15 @@ EXPECT_TRUE(data_provider.AllWriteDataConsumed()); } +TEST_P(SocketDataPumpTest, PipesShutdown) { + net::IoMode mode = GetParam(); + net::MockRead reads[] = {net::MockRead(mode, net::OK)}; + net::StaticSocketDataProvider data_provider(reads, + base::span<net::MockWrite>()); + Init(&data_provider); + send_handle_.reset(); + receive_handle_.reset(); + delegate()->WaitForShutdown(); +} + } // namespace network
diff --git a/services/network/socket_factory.cc b/services/network/socket_factory.cc index bd6cbbc4..7e667b6 100644 --- a/services/network/socket_factory.cc +++ b/services/network/socket_factory.cc
@@ -4,28 +4,44 @@ #include "services/network/socket_factory.h" +#include <string> #include <utility> #include "base/optional.h" +#include "mojo/public/cpp/bindings/binding.h" #include "net/base/completion_once_callback.h" #include "net/base/net_errors.h" #include "net/log/net_log.h" #include "net/socket/client_socket_factory.h" +#include "net/socket/client_socket_handle.h" +#include "net/ssl/ssl_config.h" +#include "net/ssl/ssl_config_service.h" #include "net/url_request/url_request_context.h" #include "services/network/tcp_connected_socket.h" +#include "services/network/tls_client_socket.h" + #include "services/network/udp_socket.h" namespace network { SocketFactory::SocketFactory(net::NetLog* net_log, net::URLRequestContext* url_request_context) - : net_log_(net_log) { + : net_log_(net_log), + ssl_client_socket_context_( + url_request_context->cert_verifier(), + nullptr, /* TODO(rkn): ChannelIDService is not thread safe. */ + url_request_context->transport_security_state(), + url_request_context->cert_transparency_verifier(), + url_request_context->ct_policy_enforcer(), + std::string() /* TODO(rsleevi): Ensure a proper unique shard. */), + client_socket_factory_(nullptr), + ssl_config_service_(url_request_context->ssl_config_service()) { if (url_request_context->GetNetworkSessionContext()) { client_socket_factory_ = url_request_context->GetNetworkSessionContext()->client_socket_factory; - } else { - client_socket_factory_ = nullptr; } + if (!client_socket_factory_) + client_socket_factory_ = net::ClientSocketFactory::GetDefaultFactory(); } SocketFactory::~SocketFactory() {} @@ -60,10 +76,10 @@ const net::AddressList& remote_addr_list, const net::NetworkTrafficAnnotationTag& traffic_annotation, mojom::TCPConnectedSocketRequest request, - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, mojom::NetworkContext::CreateTCPConnectedSocketCallback callback) { auto socket = std::make_unique<TCPConnectedSocket>( - std::move(observer), net_log_, client_socket_factory_, + std::move(observer), net_log_, this, client_socket_factory_, traffic_annotation); TCPConnectedSocket* socket_raw = socket.get(); tcp_connected_socket_bindings_.AddBinding(std::move(socket), @@ -71,6 +87,25 @@ socket_raw->Connect(local_addr, remote_addr_list, std::move(callback)); } +void SocketFactory::CreateTLSClientSocket( + const net::HostPortPair& host_port_pair, + mojom::TLSClientSocketRequest request, + std::unique_ptr<net::ClientSocketHandle> tcp_socket, + mojom::SocketObserverPtr observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + mojom::TCPConnectedSocket::UpgradeToTLSCallback callback) { + auto socket = std::make_unique<TLSClientSocket>( + std::move(request), std::move(observer), + static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation)); + TLSClientSocket* socket_raw = socket.get(); + tls_socket_bindings_.AddBinding(std::move(socket), std::move(request)); + net::SSLConfig ssl_config; + ssl_config_service_->GetSSLConfig(&ssl_config); + socket_raw->Connect(host_port_pair, ssl_config, std::move(tcp_socket), + ssl_client_socket_context_, client_socket_factory_, + std::move(callback)); +} + void SocketFactory::OnAccept(std::unique_ptr<TCPConnectedSocket> socket, mojom::TCPConnectedSocketRequest request) { tcp_connected_socket_bindings_.AddBinding(std::move(socket),
diff --git a/services/network/socket_factory.h b/services/network/socket_factory.h index d1e6bc86..6d23f4af 100644 --- a/services/network/socket_factory.h +++ b/services/network/socket_factory.h
@@ -11,27 +11,30 @@ #include "base/component_export.h" #include "base/macros.h" #include "mojo/public/cpp/bindings/strong_binding_set.h" +#include "net/socket/ssl_client_socket.h" #include "net/socket/tcp_socket.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/tcp_socket.mojom.h" +#include "services/network/public/mojom/tls_socket.mojom.h" #include "services/network/public/mojom/udp_socket.mojom.h" +#include "services/network/tcp_connected_socket.h" #include "services/network/tcp_server_socket.h" namespace net { +class ClientSocketHandle; class ClientSocketFactory; class NetLog; +class SSLConfigService; } // namespace net namespace network { -class UDPSocket; -class TCPConnectedSocket; - -// Helper class that handles UDPSocketRequest. It takes care of destroying the -// UDPSocket implementation instances when mojo pipes are broken. +// Helper class that handles socket requests. It takes care of destroying +// socket implementation instances when mojo pipes are broken. class COMPONENT_EXPORT(NETWORK_SERVICE) SocketFactory - : public TCPServerSocket::Delegate { + : public TCPServerSocket::Delegate, + public TCPConnectedSocket::Delegate { public: // Constructs a SocketFactory. If |net_log| is non-null, it is used to // log NetLog events when logging is enabled. |net_log| used to must outlive @@ -53,7 +56,7 @@ const net::AddressList& remote_addr_list, const net::NetworkTrafficAnnotationTag& traffic_annotation, mojom::TCPConnectedSocketRequest request, - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, mojom::NetworkContext::CreateTCPConnectedSocketCallback callback); private: @@ -61,12 +64,24 @@ void OnAccept(std::unique_ptr<TCPConnectedSocket> socket, mojom::TCPConnectedSocketRequest request) override; - net::NetLog* net_log_; + // TCPConnectedSocket::Delegate implementation: + void CreateTLSClientSocket( + const net::HostPortPair& host_port_pair, + mojom::TLSClientSocketRequest request, + std::unique_ptr<net::ClientSocketHandle> tcp_socket, + mojom::SocketObserverPtr observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + mojom::TCPConnectedSocket::UpgradeToTLSCallback callback) override; + + net::NetLog* const net_log_; + const net::SSLClientSocketContext ssl_client_socket_context_; net::ClientSocketFactory* client_socket_factory_; + scoped_refptr<net::SSLConfigService> ssl_config_service_; mojo::StrongBindingSet<mojom::UDPSocket> udp_socket_bindings_; mojo::StrongBindingSet<mojom::TCPServerSocket> tcp_server_socket_bindings_; mojo::StrongBindingSet<mojom::TCPConnectedSocket> tcp_connected_socket_bindings_; + mojo::StrongBindingSet<mojom::TLSClientSocket> tls_socket_bindings_; DISALLOW_COPY_AND_ASSIGN(SocketFactory); };
diff --git a/services/network/tcp_connected_socket.cc b/services/network/tcp_connected_socket.cc index 23b9ce78..ee9d57b0 100644 --- a/services/network/tcp_connected_socket.cc +++ b/services/network/tcp_connected_socket.cc
@@ -13,35 +13,40 @@ #include "net/base/net_errors.h" #include "net/log/net_log.h" #include "net/socket/client_socket_factory.h" +#include "net/socket/client_socket_handle.h" +#include "services/network/tls_client_socket.h" namespace network { TCPConnectedSocket::TCPConnectedSocket( - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, net::NetLog* net_log, + Delegate* delegate, net::ClientSocketFactory* client_socket_factory, const net::NetworkTrafficAnnotationTag& traffic_annotation) : observer_(std::move(observer)), net_log_(net_log), - client_socket_factory_(client_socket_factory == nullptr - ? net::ClientSocketFactory::GetDefaultFactory() - : client_socket_factory), + delegate_(delegate), + client_socket_factory_(client_socket_factory), traffic_annotation_(traffic_annotation) {} TCPConnectedSocket::TCPConnectedSocket( - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, std::unique_ptr<net::StreamSocket> socket, mojo::ScopedDataPipeProducerHandle receive_pipe_handle, mojo::ScopedDataPipeConsumerHandle send_pipe_handle, const net::NetworkTrafficAnnotationTag& traffic_annotation) - : net_log_(nullptr), + : observer_(std::move(observer)), + net_log_(nullptr), + delegate_(nullptr), client_socket_factory_(nullptr), socket_(std::move(socket)), traffic_annotation_(traffic_annotation) { socket_data_pump_ = std::make_unique<SocketDataPump>( - std::move(observer), socket_.get(), std::move(receive_pipe_handle), + socket_.get(), this /*delegate*/, std::move(receive_pipe_handle), std::move(send_pipe_handle), traffic_annotation); } + TCPConnectedSocket::~TCPConnectedSocket() {} void TCPConnectedSocket::Connect( @@ -80,6 +85,35 @@ std::move(callback).Run(result, local_addr); } +void TCPConnectedSocket::UpgradeToTLS( + const net::HostPortPair& host_port_pair, + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, + mojom::TLSClientSocketRequest request, + mojom::SocketObserverPtr observer, + UpgradeToTLSCallback callback) { + // Wait for data pipes to be closed by the client before doing the upgrade. + if (socket_data_pump_) { + pending_upgrade_to_tls_callback_ = base::BindOnce( + &TCPConnectedSocket::UpgradeToTLS, base::Unretained(this), + host_port_pair, traffic_annotation, std::move(request), + std::move(observer), std::move(callback)); + return; + } + if (!socket_ || !socket_->IsConnected()) { + std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, + mojo::ScopedDataPipeConsumerHandle(), + mojo::ScopedDataPipeProducerHandle()); + return; + } + auto socket_handle = std::make_unique<net::ClientSocketHandle>(); + socket_handle->SetSocket(std::move(socket_)); + delegate_->CreateTLSClientSocket( + host_port_pair, std::move(request), std::move(socket_handle), + std::move(observer), + static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation), + std::move(callback)); +} + void TCPConnectedSocket::OnConnectCompleted(int result) { DCHECK(!connect_callback_.is_null()); DCHECK(!socket_data_pump_); @@ -92,14 +126,28 @@ } mojo::DataPipe send_pipe; mojo::DataPipe receive_pipe; - socket_data_pump_ = std::make_unique<SocketDataPump>( - std::move(observer_), socket_.get(), - std::move(receive_pipe.producer_handle), + socket_.get(), this /*delegate*/, std::move(receive_pipe.producer_handle), std::move(send_pipe.consumer_handle), traffic_annotation_); std::move(connect_callback_) .Run(net::OK, std::move(receive_pipe.consumer_handle), std::move(send_pipe.producer_handle)); } +void TCPConnectedSocket::OnNetworkReadError(int net_error) { + if (observer_) + observer_->OnReadError(net_error); +} + +void TCPConnectedSocket::OnNetworkWriteError(int net_error) { + if (observer_) + observer_->OnWriteError(net_error); +} + +void TCPConnectedSocket::OnShutdown() { + socket_data_pump_ = nullptr; + if (!pending_upgrade_to_tls_callback_.is_null()) + std::move(pending_upgrade_to_tls_callback_).Run(); +} + } // namespace network
diff --git a/services/network/tcp_connected_socket.h b/services/network/tcp_connected_socket.h index e7057a89..f20c212 100644 --- a/services/network/tcp_connected_socket.h +++ b/services/network/tcp_connected_socket.h
@@ -25,24 +25,38 @@ #include "services/network/socket_data_pump.h" namespace net { -class ClientSocketFactory; class NetLog; class StreamSocket; class ClientSocketFactory; +class ClientSocketHandle; } // namespace net namespace network { class COMPONENT_EXPORT(NETWORK_SERVICE) TCPConnectedSocket - : public mojom::TCPConnectedSocket { + : public mojom::TCPConnectedSocket, + public SocketDataPump::Delegate { public: + // Interface to handle a mojom::TLSClientSocketRequest. + class Delegate { + public: + // Handles a mojom::TLSClientSocketRequest. + virtual void CreateTLSClientSocket( + const net::HostPortPair& host_port_pair, + mojom::TLSClientSocketRequest request, + std::unique_ptr<net::ClientSocketHandle> tcp_socket, + mojom::SocketObserverPtr observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + mojom::TCPConnectedSocket::UpgradeToTLSCallback callback) = 0; + }; TCPConnectedSocket( - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, net::NetLog* net_log, + Delegate* delegate, net::ClientSocketFactory* client_socket_factory, const net::NetworkTrafficAnnotationTag& traffic_annotation); TCPConnectedSocket( - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, std::unique_ptr<net::StreamSocket> socket, mojo::ScopedDataPipeProducerHandle receive_pipe_handle, mojo::ScopedDataPipeConsumerHandle send_pipe_handle, @@ -56,22 +70,37 @@ // mojom::TCPConnectedSocket implementation. void GetLocalAddress(GetLocalAddressCallback callback) override; + void UpgradeToTLS( + const net::HostPortPair& host_port_pair, + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, + mojom::TLSClientSocketRequest request, + mojom::SocketObserverPtr observer, + UpgradeToTLSCallback callback) override; + private: // Invoked when net::TCPClientSocket::Connect() completes. void OnConnectCompleted(int net_result); - mojom::TCPConnectedSocketObserverPtr observer_; + // SocketDataPump::Delegate implementation. + void OnNetworkReadError(int net_error) override; + void OnNetworkWriteError(int net_error) override; + void OnShutdown() override; - net::NetLog* net_log_; - net::ClientSocketFactory* client_socket_factory_; + const mojom::SocketObserverPtr observer_; + + net::NetLog* const net_log_; + Delegate* const delegate_; + net::ClientSocketFactory* const client_socket_factory_; std::unique_ptr<net::StreamSocket> socket_; mojom::NetworkContext::CreateTCPConnectedSocketCallback connect_callback_; + base::OnceClosure pending_upgrade_to_tls_callback_; + std::unique_ptr<SocketDataPump> socket_data_pump_; - net::NetworkTrafficAnnotationTag traffic_annotation_; + const net::NetworkTrafficAnnotationTag traffic_annotation_; DISALLOW_COPY_AND_ASSIGN(TCPConnectedSocket); };
diff --git a/services/network/tcp_server_socket.cc b/services/network/tcp_server_socket.cc index a326f18..9c8dfb3 100644 --- a/services/network/tcp_server_socket.cc +++ b/services/network/tcp_server_socket.cc
@@ -45,7 +45,7 @@ return net_error; } -void TCPServerSocket::Accept(mojom::TCPConnectedSocketObserverPtr observer, +void TCPServerSocket::Accept(mojom::SocketObserverPtr observer, AcceptCallback callback) { if (pending_accepts_queue_.size() >= static_cast<size_t>(backlog_)) { std::move(callback).Run(net::ERR_INSUFFICIENT_RESOURCES, base::nullopt, @@ -77,9 +77,8 @@ socket_ = std::move(socket); } -TCPServerSocket::PendingAccept::PendingAccept( - AcceptCallback callback, - mojom::TCPConnectedSocketObserverPtr observer) +TCPServerSocket::PendingAccept::PendingAccept(AcceptCallback callback, + mojom::SocketObserverPtr observer) : callback(std::move(callback)), observer(std::move(observer)) {} TCPServerSocket::PendingAccept::~PendingAccept() {}
diff --git a/services/network/tcp_server_socket.h b/services/network/tcp_server_socket.h index 0a46c10..e15223e9 100644 --- a/services/network/tcp_server_socket.h +++ b/services/network/tcp_server_socket.h
@@ -54,7 +54,7 @@ net::IPEndPoint* local_addr_out); // TCPServerSocket implementation. - void Accept(mojom::TCPConnectedSocketObserverPtr observer, + void Accept(mojom::SocketObserverPtr observer, AcceptCallback callback) override; void GetLocalAddress(GetLocalAddressCallback callback) override; @@ -63,19 +63,18 @@ private: struct PendingAccept { - PendingAccept(AcceptCallback callback, - mojom::TCPConnectedSocketObserverPtr observer); + PendingAccept(AcceptCallback callback, mojom::SocketObserverPtr observer); ~PendingAccept(); AcceptCallback callback; - mojom::TCPConnectedSocketObserverPtr observer; + mojom::SocketObserverPtr observer; }; // Invoked when socket_->Accept() completes. void OnAcceptCompleted(int result); // Process the next Accept() from |pending_accepts_queue_|. void ProcessNextAccept(); - Delegate* delegate_; + Delegate* const delegate_; std::unique_ptr<net::ServerSocket> socket_; int backlog_; std::vector<std::unique_ptr<PendingAccept>> pending_accepts_queue_;
diff --git a/services/network/tcp_socket_unittest.cc b/services/network/tcp_socket_unittest.cc index e9e130d..f09b4561 100644 --- a/services/network/tcp_socket_unittest.cc +++ b/services/network/tcp_socket_unittest.cc
@@ -24,6 +24,7 @@ #include "net/socket/socket_test_util.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request_test_util.h" +#include "services/network/mojo_socket_test_util.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/udp_socket.mojom.h" #include "services/network/socket_factory.h" @@ -99,6 +100,7 @@ auto mock_socket = std::make_unique<net::MockTCPClientSocket>( net::AddressList(), nullptr /*netlog*/, data_providers_[next_data_provider_index_++].get()); + mock_socket->set_enable_read_if_ready(true); EXPECT_EQ(net::OK, mock_socket->Connect(base::DoNothing())); return std::move(mock_socket); } @@ -112,59 +114,6 @@ size_t next_data_provider_index_ = 0; }; -class TestTCPConnectedSocketObserver - : public mojom::TCPConnectedSocketObserver { - public: - TestTCPConnectedSocketObserver() : binding_(this) {} - ~TestTCPConnectedSocketObserver() override { - EXPECT_EQ(net::OK, read_error_); - EXPECT_EQ(net::OK, write_error_); - } - - // Returns a mojo pointer. This can only be called once. - mojom::TCPConnectedSocketObserverPtr GetObserverPtr() { - DCHECK(!binding_); - mojom::TCPConnectedSocketObserverPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; - } - - // Waits for Read and Write error. Returns the error observed. - int WaitForReadError() { - read_loop_.Run(); - int error = read_error_; - read_error_ = net::OK; - return error; - } - - int WaitForWriteError() { - write_loop_.Run(); - int error = write_error_; - write_error_ = net::OK; - return error; - } - - private: - // mojom::TCPConnectedSocketObserver implementation. - void OnReadError(int net_error) override { - read_error_ = net_error; - read_loop_.Quit(); - } - - void OnWriteError(int net_error) override { - write_error_ = net_error; - write_loop_.Quit(); - } - - int read_error_ = net::OK; - int write_error_ = net::OK; - base::RunLoop read_loop_; - base::RunLoop write_loop_; - mojo::Binding<mojom::TCPConnectedSocketObserver> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestTCPConnectedSocketObserver); -}; - // A server implemented using mojom::TCPServerSocket. It owns the server socket // pointer and as well as client connections. SendData() and StartReading() // operate on the newest client connection. @@ -343,7 +292,7 @@ int CreateTCPConnectedSocketSync( mojom::TCPConnectedSocketRequest request, - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, const base::Optional<net::IPEndPoint>& local_addr, const net::IPEndPoint& remote_addr, mojo::ScopedDataPipeConsumerHandle* receive_pipe_handle_out, @@ -371,13 +320,13 @@ return net_error; } - TestTCPConnectedSocketObserver* observer() { return &test_observer_; } + TestSocketObserver* observer() { return &test_observer_; } private: base::test::ScopedTaskEnvironment scoped_task_environment_; net::TestURLRequestContext url_request_context_; std::unique_ptr<SocketFactory> factory_; - TestTCPConnectedSocketObserver test_observer_; + TestSocketObserver test_observer_; mojo::StrongBindingSet<mojom::TCPServerSocket> tcp_server_socket_bindings_; mojo::StrongBindingSet<mojom::TCPConnectedSocket> tcp_connected_socket_bindings_; @@ -648,7 +597,10 @@ : public TCPSocketTest, public ::testing::WithParamInterface<net::IoMode> { public: - void SetUp() override { Init(&mock_client_socket_factory_); } + void SetUp() override { + mock_client_socket_factory_.set_enable_read_if_ready(true); + Init(&mock_client_socket_factory_); + } net::MockClientSocketFactory mock_client_socket_factory_; }; @@ -729,7 +681,7 @@ } // Tests that TCPServerSocket::Accept() is used with a non-null -// TCPConnectedSocketObserver and that the observer is invoked when a read error +// SocketObserver and that the observer is invoked when a read error // occurs. TEST_P(TCPSocketWithMockSocketTest, ServerAcceptWithObserverReadError) { net::IoMode mode = GetParam(); @@ -781,9 +733,8 @@ EXPECT_EQ(net::ERR_TIMED_OUT, observer()->WaitForReadError()); } -// Tests that TCPServerSocket::Accept() is used with a non-null -// TCPConnectedSocketObserver and that the observer is invoked when a write -// error occurs. +// Tests that TCPServerSocket::Accept() is used with a non-null SocketObserver +// and that the observer is invoked when a write error occurs. TEST_P(TCPSocketWithMockSocketTest, ServerAcceptWithObserverWriteError) { net::IoMode mode = GetParam(); const net::MockRead kReads[] = {net::MockRead(net::SYNCHRONOUS, net::OK)}; @@ -990,10 +941,14 @@ mojom::TCPConnectedSocketPtr client_socket; net::IoMode mode = GetParam(); const char kTestMsg[] = "hello!"; - net::MockRead reads[] = {net::MockRead(mode, kTestMsg, strlen(kTestMsg), 0), - net::MockRead(mode, net::OK)}; - net::MockWrite writes[] = {net::MockWrite(mode, net::ERR_FAILED)}; - net::StaticSocketDataProvider data_provider(reads, writes); + // The first MockRead needs to complete asynchronously because otherwise it + // can't be paused to happen after the MockWrite. + net::MockRead reads[] = { + net::MockRead(net::ASYNC, kTestMsg, strlen(kTestMsg), 1), + net::MockRead(mode, net::OK, 2)}; + net::MockWrite writes[] = {net::MockWrite(mode, net::ERR_FAILED, 0)}; + net::SequencedSocketData data_provider(reads, writes); + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); data_provider.set_connect_data( net::MockConnect(net::SYNCHRONOUS, net::OK, server_addr));
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index 6ffebe6..a55b4489 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h
@@ -80,7 +80,7 @@ const net::AddressList& remote_addr_list, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojom::TCPConnectedSocketRequest socket, - mojom::TCPConnectedSocketObserverPtr observer, + mojom::SocketObserverPtr observer, CreateTCPConnectedSocketCallback callback) override {} void CreateWebSocket(mojom::WebSocketRequest request, int32_t process_id,
diff --git a/services/network/tls_client_socket.cc b/services/network/tls_client_socket.cc new file mode 100644 index 0000000..54b7815 --- /dev/null +++ b/services/network/tls_client_socket.cc
@@ -0,0 +1,79 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/tls_client_socket.h" + +#include <utility> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "net/base/net_errors.h" +#include "net/socket/client_socket_factory.h" +#include "net/socket/client_socket_handle.h" +#include "net/socket/ssl_client_socket.h" +#include "net/ssl/ssl_config.h" +#include "net/ssl/ssl_config_service.h" + +namespace network { + +TLSClientSocket::TLSClientSocket( + mojom::TLSClientSocketRequest request, + mojom::SocketObserverPtr observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation) + : observer_(std::move(observer)), traffic_annotation_(traffic_annotation) {} + +TLSClientSocket::~TLSClientSocket() {} + +void TLSClientSocket::Connect( + const net::HostPortPair& host_port_pair, + const net::SSLConfig& ssl_config, + std::unique_ptr<net::ClientSocketHandle> tcp_socket, + const net::SSLClientSocketContext& ssl_client_socket_context, + net::ClientSocketFactory* socket_factory, + mojom::TCPConnectedSocket::UpgradeToTLSCallback callback) { + connect_callback_ = std::move(callback); + socket_ = socket_factory->CreateSSLClientSocket(std::move(tcp_socket), + host_port_pair, ssl_config, + ssl_client_socket_context); + int result = socket_->Connect(base::BindRepeating( + &TLSClientSocket::OnTLSConnectCompleted, base::Unretained(this))); + if (result != net::ERR_IO_PENDING) + OnTLSConnectCompleted(result); +} + +void TLSClientSocket::OnTLSConnectCompleted(int result) { + DCHECK(!connect_callback_.is_null()); + + if (result != net::OK) { + socket_ = nullptr; + std::move(connect_callback_) + .Run(result, mojo::ScopedDataPipeConsumerHandle(), + mojo::ScopedDataPipeProducerHandle()); + return; + } + mojo::DataPipe send_pipe; + mojo::DataPipe receive_pipe; + socket_data_pump_ = std::make_unique<SocketDataPump>( + socket_.get(), this /*delegate*/, std::move(receive_pipe.producer_handle), + std::move(send_pipe.consumer_handle), traffic_annotation_); + std::move(connect_callback_) + .Run(net::OK, std::move(receive_pipe.consumer_handle), + std::move(send_pipe.producer_handle)); +} + +void TLSClientSocket::OnNetworkReadError(int net_error) { + if (observer_) + observer_->OnReadError(net_error); +} + +void TLSClientSocket::OnNetworkWriteError(int net_error) { + if (observer_) + observer_->OnWriteError(net_error); +} + +void TLSClientSocket::OnShutdown() { + // Do nothing. +} + +} // namespace network
diff --git a/services/network/tls_client_socket.h b/services/network/tls_client_socket.h new file mode 100644 index 0000000..b5ee7779 --- /dev/null +++ b/services/network/tls_client_socket.h
@@ -0,0 +1,64 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_TLS_CLIENT_SOCKET_H_ +#define SERVICES_NETWORK_TLS_CLIENT_SOCKET_H_ + +#include <memory> + +#include "base/component_export.h" +#include "base/macros.h" +#include "net/base/address_family.h" +#include "net/interfaces/address_family.mojom.h" +#include "net/interfaces/ip_endpoint.mojom.h" +#include "net/socket/ssl_client_socket.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/mojom/tcp_socket.mojom.h" +#include "services/network/public/mojom/tls_socket.mojom.h" +#include "services/network/socket_data_pump.h" + +namespace net { +class SSLClientSocket; +class ClientSocketHandle; +class ClientSocketFactory; +} // namespace net + +namespace network { + +class COMPONENT_EXPORT(NETWORK_SERVICE) TLSClientSocket + : public mojom::TLSClientSocket, + public SocketDataPump::Delegate { + public: + TLSClientSocket(mojom::TLSClientSocketRequest request, + mojom::SocketObserverPtr observer, + const net::NetworkTrafficAnnotationTag& traffic_annotation); + ~TLSClientSocket() override; + + void Connect(const net::HostPortPair& host_port_pair, + const net::SSLConfig& ssl_config, + std::unique_ptr<net::ClientSocketHandle> tcp_socket, + const net::SSLClientSocketContext& ssl_client_socket_context, + net::ClientSocketFactory* socket_factory, + mojom::TCPConnectedSocket::UpgradeToTLSCallback callback); + + private: + void OnTLSConnectCompleted(int result); + + // SocketDataPump::Delegate implementation. + void OnNetworkReadError(int net_error) override; + void OnNetworkWriteError(int net_error) override; + void OnShutdown() override; + + const mojom::SocketObserverPtr observer_; + std::unique_ptr<SocketDataPump> socket_data_pump_; + std::unique_ptr<net::SSLClientSocket> socket_; + mojom::TCPConnectedSocket::UpgradeToTLSCallback connect_callback_; + const net::NetworkTrafficAnnotationTag traffic_annotation_; + + DISALLOW_COPY_AND_ASSIGN(TLSClientSocket); +}; + +} // namespace network + +#endif // SERVICES_NETWORK_TLS_CLIENT_SOCKET_H_
diff --git a/services/network/tls_client_socket_unittest.cc b/services/network/tls_client_socket_unittest.cc new file mode 100644 index 0000000..d10a3a32 --- /dev/null +++ b/services/network/tls_client_socket_unittest.cc
@@ -0,0 +1,817 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include <string> +#include <utility> +#include <vector> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread.h" +#include "net/base/completion_callback.h" +#include "net/base/completion_once_callback.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/socket/server_socket.h" +#include "net/socket/socket_test_util.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" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "net/url_request/url_request_test_util.h" +#include "services/network/mojo_socket_test_util.h" +#include "services/network/public/mojom/network_service.mojom.h" +#include "services/network/socket_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { + +namespace { + +// Message sent over the tcp connection. +const char kMsg[] = "please start tls!"; +const size_t kMsgSize = strlen(kMsg); + +// Message sent over the tls connection. +const char kSecretMsg[] = "here is secret."; +const size_t kSecretMsgSize = strlen(kSecretMsg); + +class TLSClientSocketTestBase { + public: + TLSClientSocketTestBase() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO), + url_request_context_(true) {} + ~TLSClientSocketTestBase() {} + + protected: + // Initializes the test fixture. If |use_mock_sockets|, mock client socket + // factory will be used. + void Init(bool use_mock_sockets) { + if (use_mock_sockets) { + mock_client_socket_factory_.set_enable_read_if_ready(true); + url_request_context_.set_client_socket_factory( + &mock_client_socket_factory_); + } + url_request_context_.Init(); + factory_ = std::make_unique<SocketFactory>(nullptr /*net_log*/, + &url_request_context_); + } + + // Reads |num_bytes| from |handle| or reads until an error occurs. Returns the + // bytes read as a string. + std::string Read(mojo::ScopedDataPipeConsumerHandle* handle, + size_t num_bytes) { + std::string received_contents; + while (received_contents.size() < num_bytes) { + base::RunLoop().RunUntilIdle(); + std::vector<char> buffer(num_bytes); + uint32_t read_size = static_cast<uint32_t>(num_bytes); + MojoResult result = handle->get().ReadData(buffer.data(), &read_size, + MOJO_READ_DATA_FLAG_NONE); + if (result == MOJO_RESULT_SHOULD_WAIT) + continue; + if (result != MOJO_RESULT_OK) + return received_contents; + received_contents.append(buffer.data(), read_size); + } + return received_contents; + } + + int CreateTCPConnectedSocketSync(mojom::TCPConnectedSocketRequest request, + const net::IPEndPoint& remote_addr) { + net::AddressList remote_addr_list(remote_addr); + base::RunLoop run_loop; + int net_error = net::ERR_FAILED; + factory_->CreateTCPConnectedSocket( + base::nullopt /* local_addr */, remote_addr_list, + TRAFFIC_ANNOTATION_FOR_TESTS, std::move(request), + pre_tls_observer()->GetObserverPtr(), + base::BindLambdaForTesting( + [&](int result, + mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, + mojo::ScopedDataPipeProducerHandle send_pipe_handle) { + net_error = result; + pre_tls_recv_handle_ = std::move(receive_pipe_handle); + pre_tls_send_handle_ = std::move(send_pipe_handle); + run_loop.Quit(); + })); + run_loop.Run(); + return net_error; + } + + void UpgradeToTLS(mojom::TCPConnectedSocket* client_socket, + const net::HostPortPair& host_port_pair, + mojom::TLSClientSocketRequest request, + net::CompletionOnceCallback callback) { + client_socket->UpgradeToTLS( + host_port_pair, + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS), + std::move(request), post_tls_observer()->GetObserverPtr(), + base::BindOnce( + [](net::CompletionOnceCallback cb, + mojo::ScopedDataPipeConsumerHandle* consumer_handle, + mojo::ScopedDataPipeProducerHandle* producer_handle, int result, + mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, + mojo::ScopedDataPipeProducerHandle send_pipe_handle) { + *consumer_handle = std::move(receive_pipe_handle); + *producer_handle = std::move(send_pipe_handle); + std::move(cb).Run(result); + }, + std::move(callback), &post_tls_recv_handle_, + &post_tls_send_handle_)); + } + + TestSocketObserver* pre_tls_observer() { return &pre_tls_observer_; } + TestSocketObserver* post_tls_observer() { return &post_tls_observer_; } + + mojo::ScopedDataPipeConsumerHandle* pre_tls_recv_handle() { + return &pre_tls_recv_handle_; + } + + mojo::ScopedDataPipeProducerHandle* pre_tls_send_handle() { + return &pre_tls_send_handle_; + } + + mojo::ScopedDataPipeConsumerHandle* post_tls_recv_handle() { + return &post_tls_recv_handle_; + } + + mojo::ScopedDataPipeProducerHandle* post_tls_send_handle() { + return &post_tls_send_handle_; + } + + net::MockClientSocketFactory* mock_client_socket_factory() { + return &mock_client_socket_factory_; + } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + + // Mojo data handles obtained from CreateTCPConnectedSocket. + mojo::ScopedDataPipeConsumerHandle pre_tls_recv_handle_; + mojo::ScopedDataPipeProducerHandle pre_tls_send_handle_; + + // Mojo data handles obtained from UpgradeToTLS. + mojo::ScopedDataPipeConsumerHandle post_tls_recv_handle_; + mojo::ScopedDataPipeProducerHandle post_tls_send_handle_; + + net::TestURLRequestContext url_request_context_; + net::MockClientSocketFactory mock_client_socket_factory_; + std::unique_ptr<SocketFactory> factory_; + TestSocketObserver pre_tls_observer_; + TestSocketObserver post_tls_observer_; + mojo::StrongBindingSet<mojom::TCPServerSocket> tcp_server_socket_bindings_; + mojo::StrongBindingSet<mojom::TCPConnectedSocket> + tcp_connected_socket_bindings_; + + DISALLOW_COPY_AND_ASSIGN(TLSClientSocketTestBase); +}; + +} // namespace +class TLSClientSocketTest : public TLSClientSocketTestBase, + public testing::Test { + public: + TLSClientSocketTest() : TLSClientSocketTestBase() { + Init(true /* use_mock_sockets */); + } + + ~TLSClientSocketTest() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TLSClientSocketTest); +}; + +// Basic test to call UpgradeToTLS, and then read/write after UpgradeToTLS is +// successful. +TEST_F(TLSClientSocketTest, UpgradeToTLS) { + const net::MockRead kReads[] = {net::MockRead(net::ASYNC, kMsg, kMsgSize, 1), + net::MockRead(net::SYNCHRONOUS, net::OK, 2)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kMsg, kMsgSize, 0)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + uint32_t num_bytes = strlen(kMsg); + EXPECT_EQ(MOJO_RESULT_OK, post_tls_send_handle()->get().WriteData( + &kMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kMsg, Read(post_tls_recv_handle(), kMsgSize)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Same as the UpgradeToTLS test above, except this test calls +// base::RunLoop().RunUntilIdle() after destroying the pre-tls data pipes. +TEST_F(TLSClientSocketTest, ClosePipesRunUntilIdleAndUpgradeToTLS) { + const net::MockRead kReads[] = {net::MockRead(net::ASYNC, kMsg, kMsgSize, 1), + net::MockRead(net::SYNCHRONOUS, net::OK, 2)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kMsg, kMsgSize, 0)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + + // Call RunUntilIdle() to test the case that pipes are closed before + // UpgradeToTLS. + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + base::RunLoop().RunUntilIdle(); + + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + uint32_t num_bytes = strlen(kMsg); + EXPECT_EQ(MOJO_RESULT_OK, post_tls_send_handle()->get().WriteData( + &kMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kMsg, Read(post_tls_recv_handle(), kMsgSize)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Calling UpgradeToTLS on the same TCPConnectedSocketPtr is illegal and should +// receive an error. +TEST_F(TLSClientSocketTest, UpgradeToTLSTwice) { + const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 0)}; + net::SequencedSocketData data_provider(kReads, base::span<net::MockWrite>()); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + + // First UpgradeToTLS should complete successfully. + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + + // Second time UpgradeToTLS is called, it should fail. + mojom::TLSClientSocketPtr tls_socket2; + base::RunLoop run_loop; + int net_error = net::ERR_FAILED; + client_socket->UpgradeToTLS( + host_port_pair, + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS), + mojo::MakeRequest(&tls_socket2), nullptr /*observer */, + base::BindLambdaForTesting( + [&](int result, + mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, + mojo::ScopedDataPipeProducerHandle send_pipe_handle) { + net_error = result; + run_loop.Quit(); + })); + run_loop.Run(); + ASSERT_EQ(net::ERR_SOCKET_NOT_CONNECTED, net_error); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Same as the UpgradeToTLS test, except this also reads and writes to the tcp +// connection before UpgradeToTLS is called. +TEST_F(TLSClientSocketTest, ReadWriteBeforeUpgradeToTLS) { + const net::MockRead kReads[] = { + net::MockRead(net::SYNCHRONOUS, kMsg, kMsgSize, 0), + net::MockRead(net::ASYNC, kSecretMsg, kSecretMsgSize, 3), + net::MockRead(net::SYNCHRONOUS, net::OK, 4)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kMsg, kMsgSize, 1), + net::MockWrite(net::SYNCHRONOUS, kSecretMsg, kSecretMsgSize, 2), + }; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + EXPECT_EQ(kMsg, Read(pre_tls_recv_handle(), kMsgSize)); + + uint32_t num_bytes = kMsgSize; + EXPECT_EQ(MOJO_RESULT_OK, pre_tls_send_handle()->get().WriteData( + &kMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + num_bytes = strlen(kSecretMsg); + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kSecretMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kSecretMsg, Read(post_tls_recv_handle(), kSecretMsgSize)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that a read error is encountered after UpgradeToTLS completes +// successfully. +TEST_F(TLSClientSocketTest, ReadErrorAfterUpgradeToTLS) { + const net::MockRead kReads[] = { + net::MockRead(net::ASYNC, kSecretMsg, kSecretMsgSize, 1), + net::MockRead(net::SYNCHRONOUS, net::ERR_CONNECTION_CLOSED, 2)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kSecretMsg, kSecretMsgSize, 0)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + uint32_t num_bytes = strlen(kSecretMsg); + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kSecretMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kSecretMsg, Read(post_tls_recv_handle(), kSecretMsgSize)); + EXPECT_EQ(net::ERR_CONNECTION_CLOSED, + post_tls_observer()->WaitForReadError()); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that a read error is encountered after UpgradeToTLS completes +// successfully. +TEST_F(TLSClientSocketTest, WriteErrorAfterUpgradeToTLS) { + const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 0)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, net::ERR_CONNECTION_CLOSED, 1)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + uint32_t num_bytes = strlen(kSecretMsg); + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kSecretMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(net::ERR_CONNECTION_CLOSED, + post_tls_observer()->WaitForWriteError()); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that reading from the pre-tls data pipe is okay even after UpgradeToTLS +// is called. +TEST_F(TLSClientSocketTest, ReadFromPreTlsDataPipeAfterUpgradeToTLS) { + const net::MockRead kReads[] = { + net::MockRead(net::ASYNC, kMsg, kMsgSize, 0), + net::MockRead(net::ASYNC, kSecretMsg, kSecretMsgSize, 2), + net::MockRead(net::SYNCHRONOUS, net::OK, 3)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kSecretMsg, kSecretMsgSize, 1)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(kMsg, Read(pre_tls_recv_handle(), kMsgSize)); + + // Reset pre-tls receive pipe now and UpgradeToTLS should complete. + pre_tls_recv_handle()->reset(); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + uint32_t num_bytes = strlen(kSecretMsg); + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kSecretMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kSecretMsg, Read(post_tls_recv_handle(), kSecretMsgSize)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that writing to the pre-tls data pipe is okay even after UpgradeToTLS +// is called. +TEST_F(TLSClientSocketTest, WriteToPreTlsDataPipeAfterUpgradeToTLS) { + const net::MockRead kReads[] = { + net::MockRead(net::ASYNC, kSecretMsg, kSecretMsgSize, 2), + net::MockRead(net::SYNCHRONOUS, net::OK, 3)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kMsg, kMsgSize, 0), + net::MockWrite(net::SYNCHRONOUS, kSecretMsg, kSecretMsgSize, 1)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + base::RunLoop().RunUntilIdle(); + + uint32_t num_bytes = strlen(kMsg); + EXPECT_EQ(MOJO_RESULT_OK, pre_tls_send_handle()->get().WriteData( + &kMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + + // Reset pre-tls send pipe now and UpgradeToTLS should complete. + pre_tls_send_handle()->reset(); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + num_bytes = strlen(kSecretMsg); + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kSecretMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kSecretMsg, Read(post_tls_recv_handle(), kSecretMsgSize)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that reading from and writing to pre-tls data pipe is okay even after +// UpgradeToTLS is called. +TEST_F(TLSClientSocketTest, ReadAndWritePreTlsDataPipeAfterUpgradeToTLS) { + const net::MockRead kReads[] = { + net::MockRead(net::ASYNC, kMsg, kMsgSize, 0), + net::MockRead(net::ASYNC, kSecretMsg, kSecretMsgSize, 3), + net::MockRead(net::SYNCHRONOUS, net::OK, 4)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, kMsg, kMsgSize, 1), + net::MockWrite(net::SYNCHRONOUS, kSecretMsg, kSecretMsgSize, 2)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + base::RunLoop run_loop; + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + EXPECT_EQ(kMsg, Read(pre_tls_recv_handle(), kMsgSize)); + uint32_t num_bytes = strlen(kMsg); + EXPECT_EQ(MOJO_RESULT_OK, pre_tls_send_handle()->get().WriteData( + &kMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + + // Reset pre-tls pipes now and UpgradeToTLS should complete. + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + num_bytes = strlen(kSecretMsg); + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kSecretMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kSecretMsg, Read(post_tls_recv_handle(), kSecretMsgSize)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that a read error is encountered before UpgradeToTLS completes. +TEST_F(TLSClientSocketTest, ReadErrorBeforeUpgradeToTLS) { + const net::MockRead kReads[] = { + net::MockRead(net::ASYNC, kMsg, kMsgSize, 0), + net::MockRead(net::SYNCHRONOUS, net::ERR_CONNECTION_CLOSED, 1)}; + net::SequencedSocketData data_provider(kReads, base::span<net::MockWrite>()); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + + EXPECT_EQ(kMsg, Read(pre_tls_recv_handle(), kMsgSize)); + EXPECT_EQ(net::ERR_CONNECTION_CLOSED, pre_tls_observer()->WaitForReadError()); + + // Reset pre-tls receive pipe now and UpgradeToTLS should complete. + pre_tls_recv_handle()->reset(); + ASSERT_EQ(net::ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult()); + client_socket.reset(); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +// Tests that a write error is encountered before UpgradeToTLS completes. +TEST_F(TLSClientSocketTest, WriteErrorBeforeUpgradeToTLS) { + const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 1)}; + const net::MockWrite kWrites[] = { + net::MockWrite(net::SYNCHRONOUS, net::ERR_CONNECTION_CLOSED, 0)}; + net::SequencedSocketData data_provider(kReads, kWrites); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + uint32_t num_bytes = strlen(kMsg); + EXPECT_EQ(MOJO_RESULT_OK, pre_tls_send_handle()->get().WriteData( + &kMsg, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + + EXPECT_EQ(net::ERR_CONNECTION_CLOSED, + pre_tls_observer()->WaitForWriteError()); + // Reset pre-tls send pipe now and UpgradeToTLS should complete. + pre_tls_send_handle()->reset(); + ASSERT_EQ(net::ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult()); + client_socket.reset(); + + base::RunLoop().RunUntilIdle(); + // Write failed before the mock read can be consumed. + EXPECT_FALSE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +class TLSClientSocketParameterizedTest + : public TLSClientSocketTestBase, + public testing::TestWithParam<net::IoMode> { + public: + TLSClientSocketParameterizedTest() : TLSClientSocketTestBase() { + Init(true /* use_mock_sockets*/); + } + + ~TLSClientSocketParameterizedTest() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TLSClientSocketParameterizedTest); +}; + +INSTANTIATE_TEST_CASE_P(/* no prefix */, + TLSClientSocketParameterizedTest, + testing::Values(net::SYNCHRONOUS, net::ASYNC)); + +TEST_P(TLSClientSocketParameterizedTest, MultipleWriteToTLSSocket) { + const int kNumIterations = 3; + std::vector<net::MockRead> reads; + std::vector<net::MockWrite> writes; + int sequence_number = 0; + net::IoMode mode = GetParam(); + for (int j = 0; j < kNumIterations; ++j) { + for (size_t i = 0; i < kSecretMsgSize; ++i) { + writes.push_back( + net::MockWrite(mode, &kSecretMsg[i], 1, sequence_number++)); + } + for (size_t i = 0; i < kSecretMsgSize; ++i) { + reads.push_back( + net::MockRead(net::ASYNC, &kSecretMsg[i], 1, sequence_number++)); + } + if (j == kNumIterations - 1) { + reads.push_back(net::MockRead(mode, net::OK, sequence_number++)); + } + } + net::SequencedSocketData data_provider(reads, writes); + data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK)); + mock_client_socket_factory()->AddSocketDataProvider(&data_provider); + net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); + mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + net::HostPortPair host_port_pair("example.org", 443); + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), host_port_pair, + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + // Loop kNumIterations times to test that writes can follow reads, and reads + // can follow writes. + for (int j = 0; j < kNumIterations; ++j) { + // Write multiple times. + for (size_t i = 0; i < kSecretMsgSize; ++i) { + uint32_t num_bytes = 1; + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData( + &kSecretMsg[i], &num_bytes, MOJO_WRITE_DATA_FLAG_NONE)); + // Flush the 1 byte write. + base::RunLoop().RunUntilIdle(); + } + // Reading kSecretMsgSize should coalesce the 1-byte mock reads. + EXPECT_EQ(kSecretMsg, Read(post_tls_recv_handle(), kSecretMsgSize)); + } + EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_TRUE(data_provider.AllReadDataConsumed()); + EXPECT_TRUE(data_provider.AllWriteDataConsumed()); +} + +class TLSClientSocketTestWithEmbeddedTestServer + : public TLSClientSocketTestBase, + public testing::Test { + public: + TLSClientSocketTestWithEmbeddedTestServer() : TLSClientSocketTestBase() { + Init(false /* use_mock_sockets */); + } + + ~TLSClientSocketTestWithEmbeddedTestServer() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TLSClientSocketTestWithEmbeddedTestServer); +}; + +TEST_F(TLSClientSocketTestWithEmbeddedTestServer, Basic) { + net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS); + server.RegisterRequestHandler( + base::BindRepeating([](const net::test_server::HttpRequest& request) { + if (base::StartsWith(request.relative_url, "/secret", + base::CompareCase::INSENSITIVE_ASCII)) { + return std::unique_ptr<net::test_server::HttpResponse>( + new net::test_server::RawHttpResponse("HTTP/1.1 200 OK", + "Hello There!")); + } + return std::unique_ptr<net::test_server::HttpResponse>(); + })); + server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); + ASSERT_TRUE(server.Start()); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), server.port()); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), server.host_port_pair(), + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::OK, callback.WaitForResult()); + client_socket.reset(); + + const char kTestMsg[] = "GET /secret HTTP/1.1\r\n\r\n"; + uint32_t num_bytes = strlen(kTestMsg); + const char kResponse[] = "HTTP/1.1 200 OK\n\n"; + EXPECT_EQ(MOJO_RESULT_OK, + post_tls_send_handle()->get().WriteData(&kTestMsg, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(kResponse, Read(post_tls_recv_handle(), strlen(kResponse))); +} + +TEST_F(TLSClientSocketTestWithEmbeddedTestServer, ServerCertError) { + net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS); + server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME); + ASSERT_TRUE(server.Start()); + + mojom::TCPConnectedSocketPtr client_socket; + net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), server.port()); + EXPECT_EQ(net::OK, CreateTCPConnectedSocketSync( + mojo::MakeRequest(&client_socket), server_addr)); + + pre_tls_recv_handle()->reset(); + pre_tls_send_handle()->reset(); + net::TestCompletionCallback callback; + mojom::TLSClientSocketPtr tls_socket; + UpgradeToTLS(client_socket.get(), server.host_port_pair(), + mojo::MakeRequest(&tls_socket), callback.callback()); + ASSERT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, callback.WaitForResult()); +} + +} // namespace network
diff --git a/services/network/url_request_context_builder_mojo.cc b/services/network/url_request_context_builder_mojo.cc index 122176e..a4e4c48 100644 --- a/services/network/url_request_context_builder_mojo.cc +++ b/services/network/url_request_context_builder_mojo.cc
@@ -39,6 +39,8 @@ net::NetworkQualityEstimator* network_quality_estimator) { return NetworkContext::ApplyContextParamsToBuilder( this, params, quic_disabled, net_log, network_quality_estimator, + nullptr, /* sth_distributor */ + nullptr, /* out_ct_tree_tracker */ nullptr /* out_static_user_agent_settings */); }
diff --git a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h index f45eb16..97fbbe3b 100644 --- a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h
@@ -36,6 +36,12 @@ void SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low) override; void SetPID(int64_t pid) override; + // Private implementation properties. + void set_private_footprint_kb(uint64_t private_footprint_kb) { + private_footprint_kb_ = private_footprint_kb; + } + uint64_t private_footprint_kb() const { return private_footprint_kb_; } + std::set<FrameCoordinationUnitImpl*> GetFrameCoordinationUnits() const; std::set<PageCoordinationUnitImpl*> GetAssociatedPageCoordinationUnits() const; @@ -50,6 +56,8 @@ bool AddFrame(FrameCoordinationUnitImpl* frame_cu); bool RemoveFrame(FrameCoordinationUnitImpl* frame_cu); + uint64_t private_footprint_kb_ = 0u; + std::set<FrameCoordinationUnitImpl*> frame_coordination_units_; DISALLOW_COPY_AND_ASSIGN(ProcessCoordinationUnitImpl);
diff --git a/services/resource_coordinator/coordination_unit/system_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/system_coordination_unit_impl.cc index 464a43d..acd8a00 100644 --- a/services/resource_coordinator/coordination_unit/system_coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/system_coordination_unit_impl.cc
@@ -29,7 +29,8 @@ ProcessCoordinationUnitImpl::GetAllProcessCoordinationUnits(); for (const auto& measurement : measurement_batch->measurements) { - for (ProcessCoordinationUnitImpl* process : processes) { + for (auto it = processes.begin(); it != processes.end(); ++it) { + ProcessCoordinationUnitImpl* process = *it; int64_t process_pid; // TODO(siggi): This seems pretty silly - we're going O(N^2) in processes // here, and going through a relatively expensive accessor for the @@ -37,12 +38,21 @@ if (process->GetProperty(mojom::PropertyType::kPID, &process_pid) && static_cast<base::ProcessId>(process_pid) == measurement->pid) { process->SetCPUUsage(measurement->cpu_usage); + process->set_private_footprint_kb(measurement->private_footprint_kb); + // Remove found processes. + processes.erase(it); break; } } } + // Clear processes we didn't get data for. + for (ProcessCoordinationUnitImpl* process : processes) { + process->SetCPUUsage(0.0); + process->set_private_footprint_kb(0); + } + // Fire the end update signal. OnProcessCPUUsageReady(); }
diff --git a/services/resource_coordinator/coordination_unit/system_coordination_unit_impl_unittest.cc b/services/resource_coordinator/coordination_unit/system_coordination_unit_impl_unittest.cc index b9082a12..bf07279 100644 --- a/services/resource_coordinator/coordination_unit/system_coordination_unit_impl_unittest.cc +++ b/services/resource_coordinator/coordination_unit/system_coordination_unit_impl_unittest.cc
@@ -110,10 +110,34 @@ EXPECT_TRUE(cu_graph.process->GetProperty(mojom::PropertyType::kCPUUsage, &cpu_usage)); EXPECT_EQ(1000, cpu_usage); + EXPECT_EQ(1u, cu_graph.process->private_footprint_kb()); EXPECT_TRUE(cu_graph.other_process->GetProperty( mojom::PropertyType::kCPUUsage, &cpu_usage)); EXPECT_EQ(2000, cpu_usage); + EXPECT_EQ(2u, cu_graph.other_process->private_footprint_kb()); + + // Now test that a measurement batch that leaves out a process clears the + // properties of that process. + batch = mojom::ProcessResourceMeasurementBatch::New(); + mojom::ProcessResourceMeasurementPtr measurement = + mojom::ProcessResourceMeasurement::New(); + measurement->pid = 1; + measurement->cpu_usage = 30.0; + measurement->private_footprint_kb = 30u; + batch->measurements.push_back(std::move(measurement)); + + cu_graph.system->DistributeMeasurementBatch(std::move(batch)); + + EXPECT_TRUE(cu_graph.process->GetProperty(mojom::PropertyType::kCPUUsage, + &cpu_usage)); + EXPECT_EQ(30000, cpu_usage); + EXPECT_EQ(30u, cu_graph.process->private_footprint_kb()); + + EXPECT_TRUE(cu_graph.other_process->GetProperty( + mojom::PropertyType::kCPUUsage, &cpu_usage)); + EXPECT_EQ(0, cpu_usage); + EXPECT_EQ(0u, cu_graph.other_process->private_footprint_kb()); } } // namespace resource_coordinator
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc index e3a37d0..3c8ccb9 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
@@ -6,6 +6,7 @@ #include <stdint.h> #include <memory> +#include "base/debug/elf_reader_linux.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/format_macros.h" @@ -15,6 +16,9 @@ #include "build/build_config.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" +// Symbol with virtual address of the start of ELF header of the current binary. +extern char __ehdr_start; + namespace memory_instrumentation { namespace { @@ -64,8 +68,9 @@ if (sscanf(header_line, "%" SCNx64 "-%" SCNx64 " %4c %*s %*s %*s%4095[^\n]\n", ®ion->start_address, &end_addr, protection_flags, - mapped_file) != 4) + mapped_file) != 4) { return false; + } if (end_addr > region->start_address) { region->size_in_bytes = end_addr - region->start_address; @@ -93,6 +98,19 @@ base::TrimWhitespaceASCII(region->mapped_file, base::TRIM_ALL, ®ion->mapped_file); + // Build ID is needed to symbolize heap profiles, and is generated only on + // official builds. Build ID is only added for the current library (chrome) + // since it is racy to read other libraries which can be unmapped any time. +#if defined(OFFICIAL_BUILD) + uintptr_t addr = reinterpret_cast<uintptr_t>(&ParseSmapsHeader); + if (addr >= region->start_address && addr < end_addr) { + base::Optional<std::string> buildid = + base::debug::ReadElfBuildId(&__ehdr_start); + if (buildid) + region->module_debugid = buildid.value(); + } +#endif // defined(OFFICIAL_BUILD) + return res; }
diff --git a/services/service_manager/public/cpp/standalone_service/main.cc b/services/service_manager/public/cpp/standalone_service/main.cc index 61c3b47..9f3e10a 100644 --- a/services/service_manager/public/cpp/standalone_service/main.cc +++ b/services/service_manager/public/cpp/standalone_service/main.cc
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/process/launch.h" #include "base/task_scheduler/task_scheduler.h" +#include "build/build_config.h" #include "services/service_manager/public/cpp/standalone_service/standalone_service.h" #include "services/service_manager/public/cpp/standalone_service/switches.h" #include "services/service_manager/public/mojom/service.mojom.h" @@ -40,7 +41,7 @@ base::AtExitManager at_exit; base::CommandLine::Init(argc, argv); -#if !defined(OFFICIAL_BIULD) && defined(OS_WIN) +#if !defined(OFFICIAL_BUILD) && defined(OS_WIN) base::RouteStdioToConsole(false); #endif
diff --git a/services/ui/public/interfaces/window_manager.mojom b/services/ui/public/interfaces/window_manager.mojom index 0704695..c774956 100644 --- a/services/ui/public/interfaces/window_manager.mojom +++ b/services/ui/public/interfaces/window_manager.mojom
@@ -169,6 +169,9 @@ // The window's title. Maps to aura::client::kTitleKey. Type: mojom::String const string kWindowTitle_Property = "prop:window-title"; + // A boolean determining whether to show the window's title. + const string kWindowTitleShown_Property = "prop:window-title-shown"; + // End long lived properties. ------------------------------------------------ // Called immediately when the WindowManager is obtained.
diff --git a/services/ui/service.h b/services/ui/service.h index be2dc70..2e46cd2 100644 --- a/services/ui/service.h +++ b/services/ui/service.h
@@ -75,6 +75,8 @@ class Service : public service_manager::Service, public ws::WindowServerDelegate { public: + // TODO(jamescook): Audit these. Some may be unused after the elimination of + // "mus" mode. struct InitParams { InitParams(); ~InitParams();
diff --git a/services/ui/ws2/BUILD.gn b/services/ui/ws2/BUILD.gn index ea5a19cb..f3a792a7 100644 --- a/services/ui/ws2/BUILD.gn +++ b/services/ui/ws2/BUILD.gn
@@ -10,32 +10,30 @@ import("//services/service_manager/public/tools/test/service_test.gni") component("lib") { + public = [ + "gpu_support.h", + "ids.h", + "window_service.h", + "window_service_client.h", + "window_service_client_binding.h", + "window_service_delegate.h", + "window_tree_factory.h", + ] sources = [ "client_change.cc", "client_change.h", "client_change_tracker.cc", "client_change_tracker.h", - - # TODO: client_root should be internal and moved to a different target. "client_root.cc", "client_root.h", - "gpu_support.h", - "ids.h", - - # TODO: window_data should be internal and moved to a different target. - "window_data.cc", - "window_data.h", + "client_window.cc", + "client_window.h", "window_host_frame_sink_client.cc", "window_host_frame_sink_client.h", "window_service.cc", - "window_service.h", "window_service_client.cc", - "window_service_client.h", "window_service_client_binding.cc", - "window_service_client_binding.h", - "window_service_delegate.h", "window_tree_factory.cc", - "window_tree_factory.h", ] public_deps = [
diff --git a/services/ui/ws2/client_root.cc b/services/ui/ws2/client_root.cc index 9cf879b..83c06cf 100644 --- a/services/ui/ws2/client_root.cc +++ b/services/ui/ws2/client_root.cc
@@ -6,7 +6,7 @@ #include "services/ui/ws2/client_change.h" #include "services/ui/ws2/client_change_tracker.h" -#include "services/ui/ws2/window_data.h" +#include "services/ui/ws2/client_window.h" #include "services/ui/ws2/window_service_client.h" #include "ui/aura/mus/client_surface_embedder.h" #include "ui/aura/window.h" @@ -21,7 +21,7 @@ : window_service_client_(window_service_client), window_(window), is_top_level_(is_top_level) { - WindowData::GetMayBeNull(window)->set_embedded_window_service_client( + ClientWindow::GetMayBeNull(window)->set_embedded_window_service_client( window_service_client); window_->AddObserver(this); // TODO: wire up gfx::Insets() correctly below. See usage in @@ -36,14 +36,14 @@ } ClientRoot::~ClientRoot() { - WindowData::GetMayBeNull(window_)->set_embedded_window_service_client( + ClientWindow::GetMayBeNull(window_)->set_embedded_window_service_client( nullptr); window_->RemoveObserver(this); } void ClientRoot::FrameSinkIdChanged() { window_->SetEmbedFrameSinkId( - WindowData::GetMayBeNull(window_)->frame_sink_id()); + ClientWindow::GetMayBeNull(window_)->frame_sink_id()); UpdatePrimarySurfaceId(); }
diff --git a/services/ui/ws2/window_data.cc b/services/ui/ws2/client_window.cc similarity index 66% rename from services/ui/ws2/window_data.cc rename to services/ui/ws2/client_window.cc index 228b95b46..c605ab2 100644 --- a/services/ui/ws2/window_data.cc +++ b/services/ui/ws2/client_window.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "services/ui/ws2/window_data.h" +#include "services/ui/ws2/client_window.h" #include "components/viz/host/host_frame_sink_manager.h" #include "services/ui/ws2/window_host_frame_sink_client.h" @@ -10,35 +10,35 @@ #include "ui/aura/window.h" #include "ui/compositor/compositor.h" -DEFINE_UI_CLASS_PROPERTY_TYPE(ui::ws2::WindowData*); +DEFINE_UI_CLASS_PROPERTY_TYPE(ui::ws2::ClientWindow*); namespace ui { namespace ws2 { namespace { -DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ui::ws2::WindowData, - kWindowDataKey, +DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ui::ws2::ClientWindow, + kClientWindowKey, nullptr); } // namespace -WindowData::~WindowData() = default; +ClientWindow::~ClientWindow() = default; // static -WindowData* WindowData::Create(aura::Window* window, - WindowServiceClient* client, - const viz::FrameSinkId& frame_sink_id) { +ClientWindow* ClientWindow::Create(aura::Window* window, + WindowServiceClient* client, + const viz::FrameSinkId& frame_sink_id) { DCHECK(!GetMayBeNull(window)); // Owned by |window|. - WindowData* data = new WindowData(window, client, frame_sink_id); - window->SetProperty(kWindowDataKey, data); - return data; + ClientWindow* client_window = new ClientWindow(window, client, frame_sink_id); + window->SetProperty(kClientWindowKey, client_window); + return client_window; } // static -const WindowData* WindowData::GetMayBeNull(const aura::Window* window) { - return window->GetProperty(kWindowDataKey); +const ClientWindow* ClientWindow::GetMayBeNull(const aura::Window* window) { + return window->GetProperty(kClientWindowKey); } -void WindowData::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) { +void ClientWindow::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) { frame_sink_id_ = frame_sink_id; viz::HostFrameSinkManager* host_frame_sink_manager = aura::Env::GetInstance() @@ -61,7 +61,7 @@ window_host_frame_sink_client_->OnFrameSinkIdChanged(); } -void WindowData::AttachCompositorFrameSink( +void ClientWindow::AttachCompositorFrameSink( viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, viz::mojom::CompositorFrameSinkClientPtr client) { viz::HostFrameSinkManager* host_frame_sink_manager = @@ -72,9 +72,9 @@ frame_sink_id_, std::move(compositor_frame_sink), std::move(client)); } -WindowData::WindowData(aura::Window* window, - WindowServiceClient* client, - const viz::FrameSinkId& frame_sink_id) +ClientWindow::ClientWindow(aura::Window* window, + WindowServiceClient* client, + const viz::FrameSinkId& frame_sink_id) : window_(window), owning_window_service_client_(client), frame_sink_id_(frame_sink_id) {}
diff --git a/services/ui/ws2/window_data.h b/services/ui/ws2/client_window.h similarity index 75% rename from services/ui/ws2/window_data.h rename to services/ui/ws2/client_window.h index f71943a..e2996ac 100644 --- a/services/ui/ws2/window_data.h +++ b/services/ui/ws2/client_window.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 SERVICES_UI_WS2_WINDOW_DATA_H_ -#define SERVICES_UI_WS2_WINDOW_DATA_H_ +#ifndef SERVICES_UI_WS2_CLIENT_WINDOW_H_ +#define SERVICES_UI_WS2_CLIENT_WINDOW_H_ #include "base/component_export.h" #include "base/macros.h" @@ -22,24 +22,24 @@ class WindowServiceClient; // Tracks any state associated with an aura::Window for the WindowService. -// WindowData is created for every window created at the request of a client, +// ClientWindow is created for every window created at the request of a client, // including the root window of ClientRoots. -class COMPONENT_EXPORT(WINDOW_SERVICE) WindowData { +class COMPONENT_EXPORT(WINDOW_SERVICE) ClientWindow { public: - ~WindowData(); + ~ClientWindow(); - // Creates a new WindowData. The lifetime of the WindowData is tied to that - // of the Window (the Window ends up owning the WindowData). - static WindowData* Create(aura::Window* window, - WindowServiceClient* client, - const viz::FrameSinkId& frame_sink_id); + // Creates a new ClientWindow. The lifetime of the ClientWindow is tied to + // that of the Window (the Window ends up owning the ClientWindow). + static ClientWindow* Create(aura::Window* window, + WindowServiceClient* client, + const viz::FrameSinkId& frame_sink_id); - // Returns the WindowData associated with a window, null if not created yet. - static WindowData* GetMayBeNull(aura::Window* window) { - return const_cast<WindowData*>( + // Returns the ClientWindow associated with a window, null if not created yet. + static ClientWindow* GetMayBeNull(aura::Window* window) { + return const_cast<ClientWindow*>( GetMayBeNull(const_cast<const aura::Window*>(window))); } - static const WindowData* GetMayBeNull(const aura::Window* window); + static const ClientWindow* GetMayBeNull(const aura::Window* window); WindowServiceClient* owning_window_service_client() { return owning_window_service_client_; @@ -66,9 +66,9 @@ viz::mojom::CompositorFrameSinkClientPtr client); private: - WindowData(aura::Window*, - WindowServiceClient* client, - const viz::FrameSinkId& frame_sink_id); + ClientWindow(aura::Window*, + WindowServiceClient* client, + const viz::FrameSinkId& frame_sink_id); aura::Window* window_; @@ -99,10 +99,10 @@ // window. std::unique_ptr<WindowHostFrameSinkClient> window_host_frame_sink_client_; - DISALLOW_COPY_AND_ASSIGN(WindowData); + DISALLOW_COPY_AND_ASSIGN(ClientWindow); }; } // namespace ws2 } // namespace ui -#endif // SERVICES_UI_WS2_WINDOW_DATA_H_ +#endif // SERVICES_UI_WS2_CLIENT_WINDOW_H_
diff --git a/services/ui/ws2/window_host_frame_sink_client.cc b/services/ui/ws2/window_host_frame_sink_client.cc index b7dd830..df2196e8 100644 --- a/services/ui/ws2/window_host_frame_sink_client.cc +++ b/services/ui/ws2/window_host_frame_sink_client.cc
@@ -5,7 +5,6 @@ #include "services/ui/ws2/window_host_frame_sink_client.h" #include "base/logging.h" -#include "services/ui/ws2/window_data.h" #include "ui/aura/mus/client_surface_embedder.h" namespace ui {
diff --git a/services/ui/ws2/window_service.cc b/services/ui/ws2/window_service.cc index cc624d2..e40f3fb 100644 --- a/services/ui/ws2/window_service.cc +++ b/services/ui/ws2/window_service.cc
@@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/single_thread_task_runner.h" +#include "services/ui/ws2/client_window.h" #include "services/ui/ws2/gpu_support.h" -#include "services/ui/ws2/window_data.h" #include "services/ui/ws2/window_service_client.h" #include "services/ui/ws2/window_service_delegate.h" #include "services/ui/ws2/window_tree_factory.h" @@ -26,16 +26,16 @@ WindowService::~WindowService() {} -WindowData* WindowService::GetWindowDataForWindowCreateIfNecessary( +ClientWindow* WindowService::GetClientWindowForWindowCreateIfNecessary( aura::Window* window) { - WindowData* data = WindowData::GetMayBeNull(window); - if (data) - return data; + ClientWindow* client_window = ClientWindow::GetMayBeNull(window); + if (client_window) + return client_window; const viz::FrameSinkId frame_sink_id = ClientWindowId(kWindowServerClientId, next_window_id_++); CHECK_NE(0u, next_window_id_); - return WindowData::Create(window, nullptr, frame_sink_id); + return ClientWindow::Create(window, nullptr, frame_sink_id); } std::unique_ptr<WindowServiceClient> WindowService::CreateWindowServiceClient(
diff --git a/services/ui/ws2/window_service.h b/services/ui/ws2/window_service.h index 1e9789d0..ed4e72bf 100644 --- a/services/ui/ws2/window_service.h +++ b/services/ui/ws2/window_service.h
@@ -29,8 +29,8 @@ namespace ws2 { +class ClientWindow; class GpuSupport; -class WindowData; class WindowServiceClient; class WindowServiceDelegate; class WindowTreeFactory; @@ -47,8 +47,8 @@ std::unique_ptr<GpuSupport> gpu_support); ~WindowService() override; - // Gets the WindowData for |window|, creating if necessary. - WindowData* GetWindowDataForWindowCreateIfNecessary(aura::Window* window); + // Gets the ClientWindow for |window|, creating if necessary. + ClientWindow* GetClientWindowForWindowCreateIfNecessary(aura::Window* window); // Creates a new WindowServiceClient, caller must call one of the Init() // functions on the returned object.
diff --git a/services/ui/ws2/window_service_client.cc b/services/ui/ws2/window_service_client.cc index 237a520..1dc7efe 100644 --- a/services/ui/ws2/window_service_client.cc +++ b/services/ui/ws2/window_service_client.cc
@@ -12,7 +12,7 @@ #include "services/ui/ws2/client_change.h" #include "services/ui/ws2/client_change_tracker.h" #include "services/ui/ws2/client_root.h" -#include "services/ui/ws2/window_data.h" +#include "services/ui/ws2/client_window.h" #include "services/ui/ws2/window_service.h" #include "services/ui/ws2/window_service_client_binding.h" #include "services/ui/ws2/window_service_delegate.h" @@ -40,10 +40,10 @@ void WindowServiceClient::InitForEmbed(aura::Window* root, mojom::WindowTreePtr window_tree_ptr) { - // Force WindowData to be created for |root|. - WindowData* window_data = - window_service_->GetWindowDataForWindowCreateIfNecessary(root); - const ClientWindowId client_window_id = window_data->frame_sink_id(); + // Force ClientWindow to be created for |root|. + ClientWindow* client_window = + window_service_->GetClientWindowForWindowCreateIfNecessary(root); + const ClientWindowId client_window_id = client_window->frame_sink_id(); AddWindowToKnownWindows(root, client_window_id); CreateClientRoot(root, std::move(window_tree_ptr)); @@ -78,9 +78,9 @@ mojom::WindowTreePtr window_tree) { OnWillBecomeClientRootWindow(window); - WindowData* window_data = WindowData::GetMayBeNull(window); - DCHECK(window_data); - const ClientWindowId client_window_id = window_data->frame_sink_id(); + ClientWindow* client_window = ClientWindow::GetMayBeNull(window); + DCHECK(client_window); + const ClientWindowId client_window_id = client_window->frame_sink_id(); const bool for_embed = window_tree.is_bound(); @@ -103,7 +103,7 @@ // Reset the frame sink id locally (after calling OnEmbed()). This is // needed so that the id used by the client matches the id used locally. - window_data->SetFrameSinkId(ClientWindowId(client_id_, 0)); + client_window->SetFrameSinkId(ClientWindowId(client_id_, 0)); } // TODO(sky): centralize FrameSinkId management. @@ -114,7 +114,7 @@ // TODO(sky): centralize FrameSinkId management. window_tree_client_->OnFrameSinkIdAllocated( ClientWindowIdToTransportId(client_window_id), - window_data->frame_sink_id()); + client_window->frame_sink_id()); } return client_root; @@ -159,16 +159,16 @@ if (reason == DeleteClientRootReason::kUnembed) { // Notify the owner of the window it no longer has a client embedded in it. - WindowData* window_data = WindowData::GetMayBeNull(window); - if (window_data->owning_window_service_client() && - window_data->owning_window_service_client() != this) { - // ClientRoots always trigger creation of a WindowData, so |window_data| - // must exist at this point. - DCHECK(window_data); - window_data->owning_window_service_client() + ClientWindow* client_window = ClientWindow::GetMayBeNull(window); + if (client_window->owning_window_service_client() && + client_window->owning_window_service_client() != this) { + // ClientRoots always trigger creation of a ClientWindow, so + // |client_window| must exist at this point. + DCHECK(client_window); + client_window->owning_window_service_client() ->window_tree_client_->OnEmbeddedAppDisconnected( - window_data->owning_window_service_client()->TransportIdForWindow( - window)); + client_window->owning_window_service_client() + ->TransportIdForWindow(window)); } } } @@ -215,10 +215,10 @@ bool WindowServiceClient::IsWindowRootOfAnotherClient( aura::Window* window) const { - WindowData* window_data = WindowData::GetMayBeNull(window); - return window_data && - window_data->embedded_window_service_client() != nullptr && - window_data->embedded_window_service_client() != this; + ClientWindow* client_window = ClientWindow::GetMayBeNull(window); + return client_window && + client_window->embedded_window_service_client() != nullptr && + client_window->embedded_window_service_client() != this; } aura::Window* WindowServiceClient::AddClientCreatedWindow( @@ -226,7 +226,7 @@ std::unique_ptr<aura::Window> window_ptr) { aura::Window* window = window_ptr.get(); client_created_windows_.insert(std::move(window_ptr)); - WindowData::Create(window, this, id); + ClientWindow::Create(window, this, id); AddWindowToKnownWindows(window, id); return window; } @@ -320,31 +320,31 @@ parent = nullptr; if (!IsWindowKnown(transient_parent)) transient_parent = nullptr; - mojom::WindowDataPtr window_data(mojom::WindowData::New()); - window_data->parent_id = + mojom::WindowDataPtr client_window(mojom::WindowData::New()); + client_window->parent_id = parent ? TransportIdForWindow(parent) : kInvalidTransportId; - window_data->window_id = + client_window->window_id = window ? TransportIdForWindow(window) : kInvalidTransportId; - window_data->transient_parent_id = + client_window->transient_parent_id = transient_parent ? TransportIdForWindow(transient_parent) : kInvalidTransportId; - window_data->bounds = window->bounds(); + client_window->bounds = window->bounds(); // TODO: use property mapping. - window_data->visible = window->TargetVisibility(); - return window_data; + client_window->visible = window->TargetVisibility(); + return client_window; } void WindowServiceClient::OnWillBecomeClientRootWindow(aura::Window* window) { DCHECK(window); // Only one client may be embedded in a window at a time. - WindowData* window_data = - window_service_->GetWindowDataForWindowCreateIfNecessary(window); - if (window_data->embedded_window_service_client()) { - window_data->embedded_window_service_client()->DeleteClientRootWithRoot( + ClientWindow* client_window = + window_service_->GetClientWindowForWindowCreateIfNecessary(window); + if (client_window->embedded_window_service_client()) { + client_window->embedded_window_service_client()->DeleteClientRootWithRoot( window); - DCHECK(!window_data->embedded_window_service_client()); + DCHECK(!client_window->embedded_window_service_client()); } // Because a new client is being embedded all existing children are removed. @@ -670,7 +670,7 @@ top_level_ptr->set_owned_by_parent(false); aura::Window* top_level = AddClientCreatedWindow(client_window_id, std::move(top_level_ptr)); - WindowData::GetMayBeNull(top_level)->SetFrameSinkId(client_window_id); + ClientWindow::GetMayBeNull(top_level)->SetFrameSinkId(client_window_id); const int64_t display_id = display::Screen::GetScreen()->GetDisplayNearestWindow(top_level).id(); // This passes null for the mojom::WindowTreePtr because the client has @@ -775,19 +775,20 @@ DVLOG(1) << "AttachCompositorFrameSink failed (invalid window id)"; return; } - WindowData* window_data = WindowData::GetMayBeNull(window); + ClientWindow* client_window = ClientWindow::GetMayBeNull(window); // If this isn't called on the root, then only allow it if there is not // another client embedded in the window. - const bool allow = IsClientRootWindow(window) || - (IsClientCreatedWindow(window) && - window_data->embedded_window_service_client() == nullptr); + const bool allow = + IsClientRootWindow(window) || + (IsClientCreatedWindow(window) && + client_window->embedded_window_service_client() == nullptr); if (!allow) { DVLOG(1) << "AttachCompositorFrameSink failed (policy disallowed)"; return; } - window_data->AttachCompositorFrameSink(std::move(compositor_frame_sink), - std::move(client)); + client_window->AttachCompositorFrameSink(std::move(compositor_frame_sink), + std::move(client)); } void WindowServiceClient::AddWindow(uint32_t change_id,
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 1cca5c9..f45a941 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -73,6 +73,11 @@ "SKIA_DLL", "GR_GL_IGNORE_ES3_MSAA=0", ] + if (is_win) { + defines += [ "SKCMS_API=__declspec(dllexport)" ] + } else { + defines += [ "SKCMS_API=__attribute__((visibility(\"default\")))" ] + } } if (skia_support_gpu) { @@ -144,7 +149,10 @@ # TODO: remove after Skia shader relocation (https://skia-review.googlesource.com/c/17927) include_dirs += [ "//third_party/skia/src/effects/gradients" ] - defines = [ "SK_USE_SKCMS" ] + defines = [ + "SK_USE_SKCMS", + "SK_IGNORE_MASK_FILTER_GLYPH_FIX", + ] if (!is_ios && !use_system_freetype) { defines += [ "SK_FREETYPE_MINIMUM_RUNTIME_VERSION=(((FREETYPE_MAJOR) * 0x01000000) | ((FREETYPE_MINOR) * 0x00010000) | ((FREETYPE_PATCH) * 0x00000100))" ]
diff --git a/storage/browser/database/vfs_backend.cc b/storage/browser/database/vfs_backend.cc index 411872f8..8be20f2 100644 --- a/storage/browser/database/vfs_backend.cc +++ b/storage/browser/database/vfs_backend.cc
@@ -126,7 +126,7 @@ return SQLITE_IOERR_DELETE; int error_code = SQLITE_OK; -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) if (sync_dir) { base::File dir(file_path.DirName(), base::File::FLAG_READ); if (dir.IsValid()) { @@ -144,7 +144,7 @@ uint32_t VfsBackend::GetFileAttributes(const base::FilePath& file_path) { #if defined(OS_WIN) uint32_t attributes = ::GetFileAttributes(file_path.value().c_str()); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) uint32_t attributes = 0; if (!access(file_path.value().c_str(), R_OK)) attributes |= static_cast<uint32_t>(R_OK);
diff --git a/storage/common/fileapi/file_system_util.cc b/storage/common/fileapi/file_system_util.cc index 8168b5d..35c99ec 100644 --- a/storage/common/fileapi/file_system_util.cc +++ b/storage/common/fileapi/file_system_util.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "net/base/escape.h" #include "net/base/net_errors.h" #include "storage/common/database/database_identifier.h" @@ -324,7 +325,7 @@ std::string FilePathToString(const base::FilePath& file_path) { #if defined(OS_WIN) return base::UTF16ToUTF8(file_path.value()); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) return file_path.value(); #endif } @@ -332,7 +333,7 @@ base::FilePath StringToFilePath(const std::string& file_path_string) { #if defined(OS_WIN) return base::FilePath(base::UTF8ToUTF16(file_path_string)); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) return base::FilePath(file_path_string); #endif }
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index c5cacdc..376211d 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -13155,5 +13155,2457 @@ "test": "chrome_public_test_vr_apk" } ] + }, + "android-kitkat-arm-rel": { + "additional_compile_targets": [ + "cronet_test_instrumentation_apk", + "monochrome_static_initializers" + ], + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "android_webview_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "android_webview_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "base_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "base_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "blink_heap_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "blink_heap_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "boringssl_crypto_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "boringssl_crypto_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "boringssl_ssl_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "boringssl_ssl_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "breakpad_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "breakpad_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cacheinvalidation_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cacheinvalidation_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "capture_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "capture_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cc_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 900, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cc_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 1500, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 10 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_vr_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "chrome_public_test_vr_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_sync_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "chrome_sync_shell_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "components_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "components_browsertests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "components_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 900, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 2 + }, + "test": "components_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 1500, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 8 + }, + "test": "content_browsertests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 3 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "content_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "crypto_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "crypto_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "device_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "device_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "display_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "display_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "events_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "events_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gfx_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 900, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gfx_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gin_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gin_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gl_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gl_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 120, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "google_apis_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "google_apis_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gpu_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gpu_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ipc_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "ipc_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "jingle_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "jingle_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "latency_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "latency_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "libjingle_xmpp_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "libjingle_xmpp_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "media_blink_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "media_blink_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "media_service_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "media_service_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "media_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 900, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "media_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "midi_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "midi_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "mojo_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "mojo_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "net_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 1800, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 3 + }, + "test": "net_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "remoting_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "remoting_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "sandbox_linux_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "sandbox_linux_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "service_manager_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "service_manager_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "services_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 300, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "services_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "skia_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "skia_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "sql_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "sql_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "storage_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "storage_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ui_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "ui_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ui_base_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "ui_base_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ui_touch_selection_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "ui_touch_selection_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "unit_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 900, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "unit_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "url_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "url_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "viz_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "viz_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "vr_common_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_common_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "vr_pixeltests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_pixeltests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webkit_unit_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "webkit_unit_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webview_instrumentation_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "webview_instrumentation_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "wtf_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "wtf_unittests" + } + ], + "isolated_scripts": [ + { + "isolate_name": "monochrome_apk_checker", + "name": "monochrome_apk_checker", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ] + } + } + ], + "junit_tests": [ + { + "test": "base_junit_tests" + }, + { + "test": "chrome_junit_tests" + }, + { + "test": "components_background_task_scheduler_junit_tests" + }, + { + "test": "components_gcm_driver_junit_tests" + }, + { + "test": "components_invalidation_impl_junit_tests" + }, + { + "test": "components_policy_junit_tests" + }, + { + "test": "components_signin_junit_tests" + }, + { + "test": "components_variations_junit_tests" + }, + { + "test": "components_web_restrictions_junit_tests" + }, + { + "test": "content_junit_tests" + }, + { + "test": "device_junit_tests" + }, + { + "test": "junit_unit_tests" + }, + { + "test": "media_base_junit_tests" + }, + { + "test": "net_junit_tests" + }, + { + "test": "service_junit_tests" + }, + { + "test": "ui_junit_tests" + }, + { + "test": "webapk_client_junit_tests" + }, + { + "test": "webapk_shell_apk_junit_tests" + } + ] } }
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index c13f253..e3a2916 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -2694,5 +2694,1371 @@ "test": "services_unittests" } ] + }, + "linux-xenial-rel": { + "additional_compile_targets": [ + "all" + ], + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "accessibility_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "app_shell_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "aura_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "battor_agent_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "boringssl_crypto_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "boringssl_ssl_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter" + ], + "name": "network_service_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--disable-site-isolation-trials" + ], + "name": "not_site_per_process_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor", + "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter" + ], + "name": "viz_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 10 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "cacheinvalidation_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "cast_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "cc_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "chrome_app_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "chromedriver_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "components_browsertests" + }, + { + "args": [ + "--enable-features=NetworkService" + ], + "name": "network_service_components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "components_browsertests" + }, + { + "args": [ + "--site-per-process" + ], + "name": "site_per_process_components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "components_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "components_unittests" + }, + { + "args": [ + "--site-per-process" + ], + "name": "site_per_process_components_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "compositor_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter" + ], + "name": "network_service_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ + "--site-per-process", + "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.content_browsertests.filter" + ], + "name": "site_per_process_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor", + "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter" + ], + "name": "viz_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 2 + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_unittests" + }, + { + "args": [ + "--site-per-process" + ], + "name": "site_per_process_content_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_unittests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor", + "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_unittests.filter" + ], + "name": "viz_content_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "cronet_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "cronet_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "dbus_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "device_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "display_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "events_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "extensions_browsertests" + }, + { + "args": [ + "--enable-features=NetworkService" + ], + "name": "network_service_extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "extensions_browsertests" + }, + { + "args": [ + "--site-per-process" + ], + "name": "site_per_process_extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "extensions_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "extensions_unittests" + }, + { + "args": [ + "--site-per-process" + ], + "name": "site_per_process_extensions_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "extensions_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "filesystem_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "gin_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "gn_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "headless_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "headless_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 2 + }, + "test": "interactive_ui_tests" + }, + { + "args": [ + "--enable-features=NetworkService" + ], + "name": "network_service_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "interactive_ui_tests" + }, + { + "args": [ + "--disable-site-isolation-trials" + ], + "name": "not_site_per_process_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "interactive_ui_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "keyboard_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "latency_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "leveldb_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "libjingle_xmpp_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "media_blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "media_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "message_center_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "mojo_core_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "nacl_loader_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "native_theme_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "pdf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "ppapi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "printing_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "sandbox_linux_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "service_manager_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "storage_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "sync_integration_tests" + }, + { + "args": [ + "--disable-site-isolation-trials" + ], + "name": "not_site_per_process_sync_integration_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "sync_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "traffic_annotation_auditor_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "ui_touch_selection_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "unit_tests" + }, + { + "args": [ + "--disable-site-isolation-trials" + ], + "name": "not_site_per_process_unit_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "vr_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "vr_pixeltests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "wtf_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "--test-type=integration" + ], + "isolate_name": "chromedriver_py_tests", + "name": "chromedriver_py_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "isolate_name": "content_shell_crash_test", + "name": "content_shell_crash_test", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "isolate_name": "devtools_closure_compile", + "name": "devtools_closure_compile", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "isolate_name": "devtools_eslint", + "name": "devtools_eslint", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "isolate_name": "metrics_python_tests", + "name": "metrics_python_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "args": [ + "--additional-driver-flag", + "--site-per-process", + "--additional-driver-flag", + "--isolate-origins=http://www.web-platform.test:8001/,http://www1.web-platform.test:8001/,http://www2.web-platform.test:8001/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001/,http://xn--lve-6lad.web-platform.test:8001/,http://www.web-platform.test:8081/,http://www1.web-platform.test:8081/,http://www2.web-platform.test:8081/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8081/,http://xn--lve-6lad.web-platform.test:8081/,https://www.web-platform.test:8444/,https://www1.web-platform.test:8444/,https://www2.web-platform.test:8444/,https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8444/,https://xn--lve-6lad.web-platform.test:8444/", + "--additional-expectations", + "src/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process" + ], + "isolate_name": "webkit_layout_tests_exparchive", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "site_per_process_webkit_layout_tests", + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 10 + } + }, + { + "isolate_name": "telemetry_gpu_unittests", + "name": "telemetry_gpu_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "hard_timeout": 960, + "shards": 12 + } + }, + { + "args": [ + "--jobs=1" + ], + "isolate_name": "telemetry_unittests", + "name": "telemetry_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 4 + } + }, + { + "isolate_name": "views_perftests", + "name": "views_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + }, + { + "args": [ + "--zero-tests-executed-ok" + ], + "isolate_name": "webkit_layout_tests_exparchive", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "webkit_layout_tests", + "only_retry_failed_tests": true, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ], + "shards": 12 + } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + } + } + ], + "scripts": [ + { + "name": "checkdeps", + "script": "checkdeps.py" + }, + { + "name": "checkperms", + "script": "checkperms.py" + }, + { + "name": "webkit_lint", + "script": "webkit_lint.py" + } + ] } }
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 6808826..eca58f87 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -3795,7 +3795,7 @@ "-v", "--upload-results", "--browser=android-chromium", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_mobile", @@ -3824,7 +3824,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -3855,7 +3855,7 @@ "-v", "--upload-results", "--browser=android-chromium", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_mobile", @@ -3884,7 +3884,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -8548,7 +8548,7 @@ "-v", "--upload-results", "--browser=android-chromium", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_mobile", @@ -8577,7 +8577,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -8608,7 +8608,7 @@ "-v", "--upload-results", "--browser=android-chromium", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_mobile", @@ -8637,7 +8637,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -11271,7 +11271,7 @@ "-v", "--upload-results", "--browser=android-webview", - "--output-format=chartjson", + "--output-format=histograms", "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" ], "isolate_name": "telemetry_perf_webview_tests", @@ -11301,7 +11301,7 @@ "-v", "--upload-results", "--browser=android-webview", - "--output-format=chartjson", + "--output-format=histograms", "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" ], "isolate_name": "telemetry_perf_webview_tests", @@ -11331,7 +11331,7 @@ "-v", "--upload-results", "--browser=android-webview", - "--output-format=chartjson", + "--output-format=histograms", "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" ], "isolate_name": "telemetry_perf_webview_tests", @@ -13555,7 +13555,7 @@ "-v", "--upload-results", "--browser=android-webview", - "--output-format=chartjson", + "--output-format=histograms", "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" ], "isolate_name": "telemetry_perf_webview_tests", @@ -13585,7 +13585,7 @@ "-v", "--upload-results", "--browser=android-webview", - "--output-format=chartjson", + "--output-format=histograms", "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" ], "isolate_name": "telemetry_perf_webview_tests", @@ -13615,7 +13615,7 @@ "-v", "--upload-results", "--browser=android-webview", - "--output-format=chartjson", + "--output-format=histograms", "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" ], "isolate_name": "telemetry_perf_webview_tests", @@ -17787,7 +17787,7 @@ "-v", "--upload-results", "--browser=android-chromium", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_mobile", @@ -17816,7 +17816,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -17847,7 +17847,7 @@ "-v", "--upload-results", "--browser=android-chromium", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_mobile", @@ -17876,7 +17876,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -22118,7 +22118,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -22148,7 +22148,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -22180,7 +22180,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -22210,7 +22210,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -26160,7 +26160,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -26190,7 +26190,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -26222,7 +26222,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -26252,7 +26252,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -30186,7 +30186,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -30216,7 +30216,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -30248,7 +30248,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -30278,7 +30278,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -34062,7 +34062,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -34092,7 +34092,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -34124,7 +34124,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -34154,7 +34154,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -37980,7 +37980,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -38010,7 +38010,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -38042,7 +38042,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -38072,7 +38072,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -41940,7 +41940,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -41970,7 +41970,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -42002,7 +42002,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -42032,7 +42032,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -45903,7 +45903,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -45933,7 +45933,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -45965,7 +45965,7 @@ "-v", "--upload-results", "--browser=release_x64", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -45995,7 +45995,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -49866,7 +49866,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.common_desktop", @@ -49896,7 +49896,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ], @@ -49928,7 +49928,7 @@ "-v", "--upload-results", "--browser=release", - "--output-format=chartjson" + "--output-format=histograms" ], "isolate_name": "telemetry_perf_tests", "name": "system_health.memory_desktop", @@ -49958,7 +49958,7 @@ "-v", "--upload-results", "--browser=reference", - "--output-format=chartjson", + "--output-format=histograms", "--max-failures=5", "--output-trace-tag=_ref" ],
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter index eee9b5d..aa830c64 100644 --- a/testing/buildbot/filters/fuchsia.base_unittests.filter +++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -26,12 +26,6 @@ -SysInfoTest.AmountOfMem -SysInfoTest.AmountOfTotalDiskSpace -# These tests are affected by an issue with cloning namespace entries from -# inside a package. See https://crbug.com/826018 --ProcessUtilTest.CloneAlternateDir --ProcessUtilTest.KillSlowChild --ProcessUtilTest.SelectivelyClonedDir - # These tests all rely on being able to set the exit code of an externally # terminated process, which mx_task_kill() does not support. # https://crbug.com/753490.
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index 7d695b0..0bef714 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -244,13 +244,22 @@ -IOThreadEctFieldTrialAndCommandLineBrowserTest.ECTFromCommandLineOverridesFieldTrial -IOThreadEctFieldTrialBrowserTest.ForceECTUsingFieldTrial -# No certificate_transparency::TreeStateTracker observes the CTVerifier created -# by the network service, so Certificate Transparency tests fail. -# https://crbug.com/803871 --CertificateTransparencyBrowserTest.ProfileRequest --CertificateTransparencyBrowserTest.SystemRequest +# SafeBrowsing doesn't yet set up its NetworkContext correctly when the network +# service is enabled. +# https://crbug.com/789640 +-SafeBrowsingNetworkContext/NetworkContextConfigurationBrowserTest.DiskCache/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationBrowserTest.DataURL/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationBrowserTest.FileURL/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationBrowserTest.ProxyConfig/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationFilePacBrowserTest.FilePac/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationFtpPacBrowserTest.FtpPac/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationHttpsStrippingPacBrowserTest.PacHttpsUrlStripping/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationProxyOnStartBrowserTest.TestInitialProxyConfig/0 -# Fail on Windows only +# Fails on Windows. It's passing on Linux but this feature needs to be converted +# to work with network service. -ConditionalCacheCountingHelperBrowserTest.Count # NOTE: if adding an exclusion for an existing failure (e.g. additional test for
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index ed13bb9..988e4dc 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -170,6 +170,26 @@ 'use_swarming': False, 'os_type': 'android', }, + 'android-kitkat-arm-rel': { + 'additional_compile_targets': [ + 'cronet_test_instrumentation_apk', + 'monochrome_static_initializers', + ], + 'test_suites': { + 'gtest_tests': 'chromium_android_gtests', + 'junit_tests': 'chromium_junit_tests', + 'isolated_scripts': 'monochrome_apk_checker_isolated_script', + }, + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'KTU84P', + 'device_type': 'hammerhead', + }, + ], + }, + 'os_type': 'android', + }, 'KitKat Phone Tester (dbg)': { 'test_suites': { 'gtest_tests': 'chromium_android_gtests', @@ -1403,6 +1423,24 @@ { 'name': 'chromium.linux', 'machines': { + 'Cast Audio Linux': { + 'additional_compile_targets': [ + 'cast_shell', + 'cast_test_lists', + ], + 'test_suites': { + 'gtest_tests': 'chromium_linux_cast_audio_gtests', + }, + }, + 'Cast Linux': { + 'additional_compile_targets': [ + 'cast_shell', + 'cast_test_lists', + ], + 'test_suites': { + 'gtest_tests': 'chromium_linux_cast_video_gtests', + }, + }, 'Fuchsia ARM64': { 'additional_compile_targets': [ 'gn_all', @@ -1433,11 +1471,6 @@ 'scripts': 'check_network_annotations_script', } }, - 'linux-jumbo-rel': { - 'additional_compile_targets': [ - 'all' - ] - }, 'Linux Builder (dbg)': { 'additional_compile_targets': [ 'all' @@ -1449,24 +1482,6 @@ 'sync_integration_tests' ] }, - 'Cast Audio Linux': { - 'additional_compile_targets': [ - 'cast_shell', - 'cast_test_lists', - ], - 'test_suites': { - 'gtest_tests': 'chromium_linux_cast_audio_gtests', - }, - }, - 'Cast Linux': { - 'additional_compile_targets': [ - 'cast_shell', - 'cast_test_lists', - ], - 'test_suites': { - 'gtest_tests': 'chromium_linux_cast_video_gtests', - }, - }, 'Fuchsia x64': { 'additional_compile_targets': [ 'gn_all', @@ -1506,6 +1521,11 @@ 'empty_main', ], }, + 'linux-jumbo-rel': { + 'additional_compile_targets': [ + 'all' + ] + }, 'linux-ozone-rel': { 'additional_compile_targets': [ 'chrome', @@ -1514,6 +1534,23 @@ 'gtest_tests': 'ozone_linux_gtests', }, }, + 'linux-xenial-rel': { + 'swarming': { + 'dimension_sets': [ + { + 'os': 'Ubuntu-16.04', + }, + ], + }, + 'additional_compile_targets': [ + 'all', + ], + 'test_suites': { + 'gtest_tests': 'chromium_linux_gtests', + 'isolated_scripts': 'chromium_linux_rel_isolated_scripts', + 'scripts': 'chromium_linux_scripts', + }, + }, }, }, {
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc index a3394d8..ce7701c6 100644 --- a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
@@ -27,7 +27,14 @@ return source; } -extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { +// Explicitly specify some attributes to avoid issues with the linker dead- +// stripping the following function on macOS, as it is not called directly +// by fuzz target. LibFuzzer runtime uses dlsym() to resolve that function. +#if V8_OS_MACOSX +__attribute__((used)) __attribute__((visibility("default"))) +#endif // V8_OS_MACOSX +extern "C" int +LLVMFuzzerInitialize(int* argc, char*** argv) { v8::V8::InitializeICUDefaultLocation((*argv)[0]); v8::V8::InitializeExternalStartupData((*argv)[0]); v8::V8::SetFlagsFromCommandLine(argc, *argv, true);
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py index f5f411e1..9da7d93 100755 --- a/testing/scripts/run_performance_tests.py +++ b/testing/scripts/run_performance_tests.py
@@ -72,7 +72,12 @@ 'blink_perf.parser', 'blink_perf.shadow_dom', 'blink_perf.svg', - 'memory.top_10_mobile' + 'memory.top_10_mobile', + 'system_health.common_desktop', + 'system_health.common_mobile', + 'system_health.memory_desktop', + 'system_health.memory_mobile', + 'system_health.webview_startup', ] # We currently have two different sharding schemes for android
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 25c65a6..15873a7 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1015,21 +1015,9 @@ ], "experiments": [ { - "name": "Brotli", + "name": "NoTransform", "params": { - "exp": "allow_brotli" - } - }, - { - "name": "Control1", - "params": { - "exp": "finch_control1" - } - }, - { - "name": "Control2", - "params": { - "exp": "finch_control2" + "exp": "holdback" } } ] @@ -2306,21 +2294,6 @@ ] } ], - "OutOfProcessPac": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "Enabled" - } - ] - } - ], "OverflowIconsForMediaControls": [ { "platforms": [ @@ -4000,6 +3973,24 @@ ] } ], + "V8CacheInlineScriptCode": [ + { + "platforms": [ + "android", + "chromeos", + "linux", + "win" + ], + "experiments": [ + { + "name": "CacheInlineScriptCode", + "enable_features": [ + "CacheInlineScriptCode" + ] + } + ] + } + ], "V8ContextSnapshot": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 8bec42be..c6293ca 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -162,7 +162,6 @@ crbug.com/591099 css3/flexbox/flex-flow-margins-auto-size.html [ Failure ] crbug.com/591099 css3/flexbox/flex-flow-padding.html [ Failure ] crbug.com/591099 css3/flexbox/flex-item-contains-strict.html [ Failure ] -crbug.com/591099 css3/flexbox/flexbox-baseline-margins.html [ Failure ] crbug.com/591099 css3/flexbox/flexbox-baseline.html [ Failure ] crbug.com/591099 css3/flexbox/flexbox-with-multi-column-property.html [ Failure ] crbug.com/591099 css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Failure ] @@ -464,17 +463,9 @@ crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-003.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Pass ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-001.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-002.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-003.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-004.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-008.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-009.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-010.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-011.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-012.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-016.html [ Failure ] -crbug.com/591099 external/wpt/css/css-text/white-space/seg-break-transformation-017.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ] crbug.com/591099 external/wpt/css/css-transforms/2d-rotate-js.html [ Failure Pass ] crbug.com/714962 external/wpt/css/css-transforms/transform-abspos-006.html [ Failure ] @@ -654,8 +645,6 @@ crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-vrl-024.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-vrl-026.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/wm-propagation-body-006.xht [ Failure ] -crbug.com/591099 external/wpt/css/cssom-view/elementFromPoint-002.html [ Failure ] -crbug.com/591099 external/wpt/css/cssom-view/elementFromPoint-003.html [ Failure ] crbug.com/591099 external/wpt/css/cssom/interfaces.html [ Pass Timeout ] crbug.com/591099 external/wpt/css/geometry/interfaces.worker.html [ Pass ] crbug.com/591099 external/wpt/css/selectors/focus-within-004.html [ Pass ] @@ -839,7 +828,6 @@ crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Pass ] crbug.com/591099 external/wpt/html/dom/dynamic-markup-insertion/opening-the-input-stream/001.html [ Failure Pass ] crbug.com/591099 external/wpt/html/dom/dynamic-markup-insertion/opening-the-input-stream/008.html [ Failure Pass Timeout ] -crbug.com/591099 external/wpt/html/dom/elements/the-innertext-idl-attribute/getter.html [ Failure ] crbug.com/591099 external/wpt/html/dom/interfaces.https.html [ Timeout ] crbug.com/591099 external/wpt/html/editing/editing-0/autocapitalization/autocapitalize.html [ Pass Timeout ] crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Timeout ] @@ -1047,7 +1035,6 @@ crbug.com/591099 fast/css-grid-layout/grid-columns-rows-get-set-multiple.html [ Pass Timeout ] crbug.com/591099 fast/css-grid-layout/grid-columns-rows-get-set.html [ Timeout ] crbug.com/591099 fast/css-grid-layout/grid-item-column-row-get-set.html [ Timeout ] -crbug.com/591099 fast/css-grid-layout/grid-item-overflow.html [ Failure ] crbug.com/591099 fast/css-grid-layout/grid-self-baseline-01.html [ Failure ] crbug.com/591099 fast/css-grid-layout/grid-self-baseline-02-b.html [ Failure ] crbug.com/591099 fast/css-grid-layout/grid-self-baseline-02.html [ Failure ] @@ -1220,7 +1207,6 @@ crbug.com/591099 fast/hidpi/image-set-shape-outside.html [ Failure ] crbug.com/591099 fast/history/visited-link-hover-outline-color.html [ Failure ] crbug.com/591099 fast/inline-block/baseline-vertical.html [ Failure ] -crbug.com/591099 fast/inline-block/contenteditable-baseline.html [ Failure ] crbug.com/714962 fast/inline-block/tricky-baseline.html [ Failure ] crbug.com/591099 fast/inline-block/vertical-align-top-and-bottom-2.html [ Failure ] crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ] @@ -1264,7 +1250,6 @@ crbug.com/824918 fast/multicol/dynamic/change-spanner-display.html [ Failure ] crbug.com/824918 fast/multicol/flipped-blocks-hit-test.html [ Failure ] crbug.com/824918 fast/multicol/hit-test-above-or-below.html [ Failure ] -crbug.com/824918 fast/multicol/inline-block-baseline.html [ Failure ] crbug.com/824918 fast/multicol/nested-one-line-in-inner.html [ Failure ] crbug.com/824918 fast/multicol/newmulticol/list-item.html [ Failure ] crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees index 82a89943..bea5e441 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -171,83 +171,14 @@ crbug.com/836897 virtual/threaded/animations/element-animate-positive-delay.html [ Crash ] # These scrollbar tests should pass. -crbug.com/836912 compositing/fixed-background-after-style-recalc.html [ Failure ] -crbug.com/836912 compositing/fixed-body-background-positioned.html [ Failure ] -crbug.com/836912 compositing/iframe-graphics-tree-changes-parents-does-not.html [ Failure ] -crbug.com/836912 compositing/layout-width-change.html [ Failure ] -crbug.com/836912 compositing/low-dpi-non-stacking-context-scrolled-content.html [ Failure ] -crbug.com/836912 compositing/perspective-interest-rect.html [ Failure ] -crbug.com/836912 compositing/scroll-with-ancestor-clip.html [ Failure ] -crbug.com/836912 compositing/culling/filter-occlusion-alpha-large.html [ Failure ] -crbug.com/836912 compositing/geometry/fixed-in-composited.html [ Failure ] -crbug.com/836912 compositing/geometry/horizontal-scroll-composited.html [ Failure ] -crbug.com/836912 compositing/geometry/tall-page-composited.html [ Failure ] -crbug.com/836912 compositing/iframes/scroll-fixed-transformed-element.html [ Failure ] -crbug.com/836912 compositing/layer-creation/fixed-position-and-transform.html [ Failure ] -crbug.com/836912 compositing/layer-creation/fixed-position-scroll.html [ Failure ] -crbug.com/836912 compositing/layer-creation/fixed-position-under-transform.html [ Failure ] -crbug.com/836912 compositing/masks/masked-ancestor.html [ Failure ] -crbug.com/836912 compositing/masks/multiple-masks.html [ Failure ] -crbug.com/836912 compositing/masks/simple-composited-mask.html [ Failure ] -crbug.com/836912 compositing/overflow/accelerated-scrolling-with-clip-path.html [ Failure ] -crbug.com/836912 compositing/overflow/ancestor-overflow-layer-of-sticky-child-of-compositing-container.html [ Failure ] -crbug.com/836912 compositing/overflow/body-switch-composited-scrolling.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-nested-sticky-deep.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-nested-sticky-left.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-nested-sticky-table.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-nested-sticky-top.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-scroll-background-obscured.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-scroller-can-be-normal-flow.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-sticky-element-enclosing-layers-stacking-context.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-sticky-element-enclosing-layers.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-sticky-element-in-composited-ancestor-with-content-offset.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-sticky-element-perspective-child-layer.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-sticky-element-stacking-context.html [ Failure ] -crbug.com/836912 compositing/overflow/composited-sticky-element.html [ Failure ] -crbug.com/836912 compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html [ Failure ] -crbug.com/836912 compositing/overflow/image-load-overflow-scrollbars.html [ Failure ] -crbug.com/836912 compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure ] -crbug.com/836912 compositing/overflow/nested-render-surfaces.html [ Failure ] -crbug.com/836912 compositing/overflow/nested-scrolling.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-background-fractional-offset.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-background-transparent-to-opaque.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-content-fractional-offset.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-with-local-background-and-child.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-with-local-background.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html [ Failure ] -crbug.com/836912 compositing/overflow/overflow-scroll.html [ Failure ] -crbug.com/836912 compositing/overflow/paint-neg-z-order-descendants-into-scrolling-contents-layer.html [ Failure ] -crbug.com/836912 compositing/overflow/reparented-overlay-scrollbars-should-respect-ancestor-clip.html [ Failure ] -crbug.com/836912 compositing/overflow/reparented-unclipped-overlay-scrollbars-with-offset-from-renderer.html [ Failure ] -crbug.com/836912 compositing/overflow/scaled-overflow.html [ Failure ] -crbug.com/836912 compositing/overflow/scroll-children-do-not-paint-comp-scroll-phase.html [ Failure ] -crbug.com/836912 compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor.html [ Failure ] -crbug.com/836912 compositing/overflow/scrollbar-layer-placement.html [ Failure ] -crbug.com/836912 compositing/overflow/tiled-mask.html [ Failure ] -crbug.com/836912 compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure ] -crbug.com/836912 compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure ] -crbug.com/836912 compositing/overlap-blending/children-opacity-huge.html [ Failure ] -crbug.com/836912 compositing/rtl/rtl-absolute-overflow-scrolled.html [ Failure ] crbug.com/836912 compositing/rtl/rtl-absolute-overflow.html [ Failure ] crbug.com/836912 compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ] -crbug.com/836912 compositing/rtl/rtl-fixed-overflow-scrolled.html [ Failure ] crbug.com/836912 compositing/rtl/rtl-fixed-overflow.html [ Failure ] -crbug.com/836912 compositing/rtl/rtl-iframe-absolute-overflow-scrolled.html [ Failure ] crbug.com/836912 compositing/rtl/rtl-iframe-absolute-overflow.html [ Failure ] -crbug.com/836912 compositing/rtl/rtl-iframe-fixed-overflow-scrolled.html [ Failure ] crbug.com/836912 compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ] crbug.com/836912 compositing/rtl/rtl-overflow-invalidation.html [ Failure ] -crbug.com/836912 compositing/rtl/rtl-overflow-scrolling.html [ Failure ] crbug.com/836912 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ] -crbug.com/836912 compositing/squashing/attempting-to-squash-into-compositing-container.html [ Failure ] -crbug.com/836912 compositing/squashing/attempting-to-squash-into-stacking-ancestor.html [ Failure ] -crbug.com/836912 compositing/squashing/frame-clip-squashed-scrolled.html [ Failure ] -crbug.com/836912 compositing/squashing/squashing-does-not-stop-transform-propagation.html [ Failure ] -crbug.com/836912 compositing/squashing/squashing-inside-perspective-with-reparented-scrolling.html [ Failure ] -crbug.com/836912 compositing/squashing/universal-accelerated-overflow-scrolling.html [ Failure ] crbug.com/836912 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ] -crbug.com/836912 scrollbars/border-box-rect-clips-scrollbars.html [ Failure ] crbug.com/836912 scrollbars/scrollbar-added-during-drag.html [ Crash ] crbug.com/836912 scrollbars/scrollbar-removed-by-viewport-crash.html [ Crash ] @@ -285,60 +216,33 @@ crbug.com/840017 compositing/overflow/overflow-scaled-descendant-overlapping.html [ Crash ] crbug.com/840017 compositing/scaling/tiled-layer-recursion.html [ Crash ] -# Lack of content layer support (other than scrollbar layers) -crbug.com/840037 compositing/canvas-with-object-fit-contain-in-composited-layer.html [ Failure ] -crbug.com/840037 compositing/culling/tile-occlusion-boundaries.html [ Failure ] -crbug.com/840037 compositing/direct-image-compositing.html [ Failure ] -crbug.com/840037 compositing/img-layer-grow.html [ Failure ] -crbug.com/840037 compositing/layers-inside-overflow-scroll.html [ Failure ] -crbug.com/840037 compositing/lots-of-img-layers-with-opacity.html [ Failure ] -crbug.com/840037 compositing/lots-of-img-layers.html [ Failure ] -crbug.com/840037 compositing/nested-direct-image-compositing.html [ Failure ] -crbug.com/840037 compositing/self-painting-layers.html [ Failure ] -crbug.com/840037 compositing/video-frame-size-change.html [ Failure ] -crbug.com/840037 compositing/backface-visibility/backface-visibility-image.html [ Failure ] -crbug.com/840037 compositing/backface-visibility/backface-visibility-webgl.html [ Failure ] -crbug.com/840037 compositing/color-matching/image-color-matching.html [ Failure ] -crbug.com/840037 compositing/draws-content/canvas-simple-background.html [ Failure ] -crbug.com/840037 compositing/draws-content/webgl-simple-background.html [ Failure ] -crbug.com/840037 compositing/geometry/video-fixed-scrolling.html [ Failure ] -crbug.com/840037 compositing/geometry/video-opacity-overlay.html [ Failure ] -crbug.com/840037 compositing/images/content-image-change.html [ Failure ] -crbug.com/840037 compositing/masks/direct-image-mask.html [ Failure ] -crbug.com/840037 compositing/masks/mask-with-removed-filters.html [ Failure ] -crbug.com/840037 compositing/overflow/overflow-compositing-descendant.html [ Failure ] -crbug.com/840037 compositing/overflow/overflow-hidden-canvas-layer.html [ Failure ] -crbug.com/840037 compositing/overflow/scroll-ancestor-update.html [ Failure ] -crbug.com/840037 compositing/plugins/webplugin-alpha.html [ Failure ] -crbug.com/840037 compositing/plugins/webplugin-no-alpha.html [ Failure ] -crbug.com/840037 compositing/plugins/webplugin-reflection.html [ Failure ] -crbug.com/840037 compositing/reflections/load-video-in-reflection.html [ Failure ] -crbug.com/840037 compositing/video/video-reflection.html [ Failure ] -crbug.com/840037 compositing/visibility/visibility-image-layers.html [ Failure ] -crbug.com/840037 compositing/visibility/visibility-simple-canvas2d-layer.html [ Failure ] -crbug.com/840037 compositing/visibility/visibility-simple-video-layer.html [ Failure ] -crbug.com/840037 compositing/visibility/visibility-simple-webgl-layer.html [ Failure ] -crbug.com/840037 compositing/webgl/webgl-no-alpha.html [ Failure ] -crbug.com/840037 compositing/webgl/webgl-nonpremultiplied-blend.html [ Failure ] -crbug.com/840037 compositing/webgl/webgl-reflection.html [ Failure ] -crbug.com/840037 compositing/webgl/webgl-repaint.html [ Failure ] -crbug.com/840037 compositing/webgl/webgl-with-accelerated-background-color.html [ Failure ] - # Reflection drawn at wrong position. crbug.com/840038 compositing/reflections/ [ Skip ] crbug.com/840038 compositing/overflow/reflected-overlay-scrollbars-should-appear-without-compositing.html [ Failure ] crbug.com/840038 compositing/overlap-blending/reflection-opacity-huge.html [ Failure ] +crbug.com/840038 compositing/plugins/webplugin-reflection.html [ Failure ] crbug.com/840038 compositing/squashing/squashing-reflection-disallowed.html [ Failure ] +crbug.com/840038 compositing/video/video-reflection.html [ Failure ] +crbug.com/840038 compositing/webgl/webgl-reflection.html [ Failure ] # Rounding differences. # Maybe due to different render surface generation? (Needs investigation.) Bug(none) compositing/backface-visibility-transformed.html [ Failure ] +Bug(none) compositing/color-matching/image-color-matching.html [ Failure ] Bug(none) compositing/flat-with-transformed-child.html [ Failure ] +Bug(none) compositing/lots-of-img-layers-with-opacity.html [ Failure ] +Bug(none) compositing/lots-of-img-layers.html [ Failure ] Bug(none) compositing/opacity-with-mask.html [ Failure ] Bug(none) compositing/perpendicular-layer-sorting.html [ Failure ] +Bug(none) compositing/perspective-interest-rect.html [ Failure ] Bug(none) compositing/geometry/layer-due-to-layer-children.html [ Failure ] -Bug(none) compositing/overflow/reflected-overlay-scrollbars-should-respect-ancestor-clip.html [ Failure ] Bug(none) compositing/shadows/shadow-drawing.html [ Failure ] +Bug(none) compositing/masks/direct-image-mask.html [ Failure ] +Bug(none) compositing/masks/masked-ancestor.html [ Failure ] +Bug(none) compositing/masks/multiple-masks.html [ Failure ] +Bug(none) compositing/masks/simple-composited-mask.html [ Failure ] +Bug(none) compositing/overflow/scaled-overflow.html [ Failure ] +Bug(none) compositing/overflow/tiled-mask.html [ Failure ] # Failures that don't belong to any of above categories. Investigation needed. Bug(none) compositing/overflow/nested-render-surfaces-with-rotation.html [ Failure ] @@ -346,8 +250,10 @@ Bug(none) compositing/overflow-trumps-transform-style.html [ Failure ] Bug(none) compositing/backface-visibility/backface-visibility-hierarchical-transform.html [ Failure ] Bug(none) compositing/geometry/clipping-foreground.html [ Failure ] +Bug(none) compositing/masks/mask-with-removed-filters.html [ Failure ] Bug(none) compositing/video/video-controls-layer-creation.html [ Failure ] Bug(none) compositing/visibility/overlays.html [ Failure ] +Bug(none) compositing/visibility/visibility-image-layers.html [ Failure ] # These tests should also pass. TODO(pdr): Enable these tests. Bug(none) virtual/scroll_customization/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 9681b33..010bc3b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2774,9 +2774,6 @@ crbug.com/803200 external/wpt/websockets/opening-handshake/005.html?wss [ Pass Failure ] crbug.com/803200 virtual/off-main-thread-websocket/external/wpt/websockets/cookies/006.html?wss [ Failure ] crbug.com/803200 virtual/off-main-thread-websocket/external/wpt/websockets/opening-handshake/005.html?wss [ Pass Failure ] -# These tests are failing because of experimental off-main-thread WebSocket -# implementation. -crbug.com/831320 virtual/off-main-thread-websocket/http/tests/websocket/close-code-and-reason.html [ Pass Failure ] crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ] @@ -2789,6 +2786,7 @@ crbug.com/832071 virtual/navigation-mojo-response/external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Retina ] external/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ] crbug.com/626703 [ Retina ] external/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ Skip ] crbug.com/626703 [ Mac10.12 ] external/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ] crbug.com/626703 [ Mac10.12 ] external/wpt/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html [ Skip ] @@ -4633,6 +4631,9 @@ crbug.com/832274 [ Linux ] fast/forms/search/search-appearance-basic.html [ Pass Failure ] +crbug.com/840881 external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] +crbug.com/840881 virtual/outofblink-cors/external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] + # Sheriff 2018-04-12 crbug.com/831993 [ Linux ] virtual/gpu-rasterization/images/cross-fade-overflow-position.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index 90e9d3b..338c800 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -680,17 +680,17 @@ { "prefix": "off-main-thread-websocket", "base": "external/wpt/websockets", - "args": ["--enable-features=OffMainThreadWebSocket"] + "args": ["--disable-features=OffMainThreadWebSocket"] }, { "prefix": "off-main-thread-websocket", "base": "http/tests/websocket", - "args": ["--enable-features=OffMainThreadWebSocket"] + "args": ["--disable-features=OffMainThreadWebSocket"] }, { "prefix": "off-main-thread-websocket", "base": "http/tests/security/mixedContent/websocket", - "args": ["--enable-features=OffMainThreadWebSocket"] + "args": ["--disable-features=OffMainThreadWebSocket"] }, { "prefix": "webrtc-wpt-unified-plan", @@ -702,5 +702,10 @@ "base": "media", "args": ["--enable-features=UseSurfaceLayerForVideo", "--enable-display-compositor-pixel-dump"] + }, + { + "prefix": "user-activation-v2", + "base": "user-activation-v2", + "args": ["--enable-features=UserActivationV2"] } ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index c517945..46632e3 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -139997,6 +139997,16 @@ {} ] ], + "fetch/corb/resources/html-js-polyglot2.js": [ + [ + {} + ] + ], + "fetch/corb/resources/html-js-polyglot2.js.headers": [ + [ + {} + ] + ], "fetch/corb/resources/js-mislabeled-as-html-nosniff.js": [ [ {} @@ -140742,6 +140752,11 @@ {} ] ], + "generic-sensor/README.md": [ + [ + {} + ] + ], "generic-sensor/generic-sensor-feature-policy-test.sub.js": [ [ {} @@ -156357,6 +156372,11 @@ {} ] ], + "orientation-sensor/orientation-sensor-tests.js": [ + [ + {} + ] + ], "page-visibility/OWNERS": [ [ {} @@ -160827,6 +160847,16 @@ {} ] ], + "server-timing/service_worker_idl-expected.txt": [ + [ + {} + ] + ], + "server-timing/sw.js": [ + [ + {} + ] + ], "server-timing/test_server_timing.html.sub.headers": [ [ {} @@ -222413,9 +222443,9 @@ {} ] ], - "orientation-sensor/OrientationSensor.https.html": [ + "orientation-sensor/AbsoluteOrientationSensor.https.html": [ [ - "/orientation-sensor/OrientationSensor.https.html", + "/orientation-sensor/AbsoluteOrientationSensor.https.html", {} ] ], @@ -222455,6 +222485,12 @@ {} ] ], + "orientation-sensor/RelativeOrientationSensor.https.html": [ + [ + "/orientation-sensor/RelativeOrientationSensor.https.html", + {} + ] + ], "orientation-sensor/idlharness.https.html": [ [ "/orientation-sensor/idlharness.https.html", @@ -232091,6 +232127,12 @@ {} ] ], + "server-timing/service_worker_idl.html": [ + [ + "/server-timing/service_worker_idl.html", + {} + ] + ], "server-timing/test_server_timing.html": [ [ "/server-timing/test_server_timing.html", @@ -237103,6 +237145,24 @@ {} ] ], + "webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-basic.html": [ + [ + "/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-basic.html", + {} + ] + ], + "webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html": [ + [ + "/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html", + {} + ] + ], + "webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-sizing.html": [ + [ + "/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-sizing.html", + {} + ] + ], "webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html": [ [ "/webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html", @@ -237169,6 +237229,24 @@ {} ] ], + "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html": [ + [ + "/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html", + {} + ] + ], + "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html": [ + [ + "/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html", + {} + ] + ], + "webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html": [ + [ + "/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html", + {} + ] + ], "webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html": [ [ "/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html", @@ -244819,6 +244897,16 @@ {} ] ], + "xhr/sync-no-progress.any.js": [ + [ + "/xhr/sync-no-progress.any.html", + {} + ], + [ + "/xhr/sync-no-progress.any.worker.html", + {} + ] + ], "xhr/template-element.html": [ [ "/xhr/template-element.html", @@ -250561,11 +250649,11 @@ "support" ], "./README.md": [ - "2ad80e88dfd9bd3ce7cf4d1b9e53b7d61c104881", + "766bb4d66deef9bcb90339d76e3280abb36103df", "support" ], "./lint.whitelist": [ - "64e7ead5a7fa09f59be4dac4ccb5a1e7bf3cb4fc", + "b740ea6ee933d028f6b2bef92cc473778b76002f", "support" ], "./update-built-tests.sh": [ @@ -257265,11 +257353,11 @@ "testharness" ], "accelerometer/Accelerometer-disabled-by-feature-policy.https-expected.txt": [ - "52f629ee03b150890f9177af60ab82f716e16ae3", + "2f3a532fcced3d1f18bc59a8416a3f5b1ed138cf", "support" ], "accelerometer/Accelerometer-disabled-by-feature-policy.https.html": [ - "96e5a86bf78239f3aa4a79b32bb4308de0d5f60e", + "efa020e5d2384a3b753d41d32fd9e62337b5fd9e", "testharness" ], "accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers": [ @@ -257277,27 +257365,27 @@ "support" ], "accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt": [ - "a96695ef8430701cb0c45ffaa7710d1f96f90125", + "9e402c8857b93ef3f7556a5179851042a2204bc9", "support" ], "accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [ - "f20f89a31daf399a7946b928e8deca9651d38487", + "0e27e5bad61367dcc348aef1ac813e70a2e2aa36", "testharness" ], "accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https-expected.txt": [ - "dcbeb063b25e2c3f01bc7b68491f726b25c1634c", + "764f3410ef5b7fbfc70292abc51427cc94517d29", "support" ], "accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html": [ - "7ce8c39f0af6c932d1e6b6f75843c090f7274b80", + "5e072aa513efc16946b2f93ecb815d45dd6cadd2", "testharness" ], "accelerometer/Accelerometer-enabled-by-feature-policy.https-expected.txt": [ - "874b4f9b7ed78e090154e92f1cd9afa2a3af3461", + "b031e85d10ace03f19294940e92f1f6837623f76", "support" ], "accelerometer/Accelerometer-enabled-by-feature-policy.https.html": [ - "dbda7cfa838c1f2d4296b545034d42f0064f331a", + "59207b5dbc249addf4a9c0c5886e1486a2d6eb94", "testharness" ], "accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers": [ @@ -257305,11 +257393,11 @@ "support" ], "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https-expected.txt": [ - "d4f6158e03f73ef30f855ff407de2b73e564df81", + "126c72a76cdd9c2b318e0cb1b806417100d1e6a3", "support" ], "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html": [ - "b8fb07cdd23dce9690de719387b9d505382772f5", + "fe9960de7b6ac203a36096f90ede31131e38cb1b", "testharness" ], "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [ @@ -257317,11 +257405,11 @@ "support" ], "accelerometer/Accelerometer.https-expected.txt": [ - "0be3c1ea85e316926dbd226fbdb4244fc94eab07", + "eb8f690a2264e1f0a9171453b0d343a701ecd0a1", "support" ], "accelerometer/Accelerometer.https.html": [ - "3ff5f61b25c52142e9796f3903d7f2bcaa30314c", + "bef928057d49b59c2ede3916e49abdd730dc9582", "testharness" ], "accelerometer/Accelerometer_insecure_context.html": [ @@ -257329,11 +257417,11 @@ "testharness" ], "accelerometer/Accelerometer_onerror-manual.https-expected.txt": [ - "31feaa72d7b84d017d459344462e0a38a72632ba", + "5655b4361914f873488e5a79f45f0fee1e3cf5d1", "support" ], "accelerometer/Accelerometer_onerror-manual.https.html": [ - "c82f9595dc2582b2da40549a358da1c3fc2ff820", + "f6a624b70b401c0802c5f189c89e85d63fe58795", "manual" ], "accelerometer/LinearAccelerationSensor-shake-threshold-manual.https-expected.txt": [ @@ -336585,13 +336673,21 @@ "support" ], "fetch/corb/resources/html-js-polyglot.js": [ - "7fc30035583764941078fb53f950c52a217d6893", + "529e81f0fa614cb1707cf759f6bf1c7990f4d51f", "support" ], "fetch/corb/resources/html-js-polyglot.js.headers": [ "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", "support" ], + "fetch/corb/resources/html-js-polyglot2.js": [ + "2a314fc6b634c7f6a6117d5602f9a4520397850d", + "support" + ], + "fetch/corb/resources/html-js-polyglot2.js.headers": [ + "41e260e7df49e0e4ddb1fc5df11913dbda15edd7", + "support" + ], "fetch/corb/resources/js-mislabeled-as-html-nosniff.js": [ "ec322736e35e0649e1f3cd4d5b88e2f211436e2b", "support" @@ -336641,7 +336737,7 @@ "testharness" ], "fetch/corb/script-html-js-polyglot.sub.html": [ - "4b28bd95bd19ea95df3e78bbfc477fb7dea60e29", + "0e9042bc4d7492b17aeb69c9062ca9682000936b", "testharness" ], "fetch/corb/script-html-via-cross-origin-blob-url.sub.html": [ @@ -337516,16 +337612,20 @@ "1cb8a0e23d31dcdeb5ba273a40e35c021c0c53f2", "support" ], + "generic-sensor/README.md": [ + "48615c1b9e70e02c02ea0246eb7ca1953bab0c68", + "support" + ], "generic-sensor/SensorErrorEvent-constructor.https.html": [ "99bcfb42c91e084a3b847ab4bab2bad80e548540", "testharness" ], "generic-sensor/generic-sensor-feature-policy-test.sub.js": [ - "c7c9c4d1c578f267cbb4241d7ea7a981be6f49ee", + "f90a08bd96c729c5c166fd628e69f01c3413a78c", "support" ], "generic-sensor/generic-sensor-tests.js": [ - "6364f1838215eaafd91b86690039da41d4c19cd1", + "a23c776f7536e3f406c78a5aa02359c7dde8c745", "support" ], "generic-sensor/idlharness.https.html": [ @@ -337737,7 +337837,7 @@ "manual" ], "gyroscope/Gyroscope-disabled-by-feature-policy.https.html": [ - "bc6f85cb3506d3e3e062eef43dca88bf3a4ebe89", + "64db7d9fe9726d6c04e97802f2328e3cfe6e2585", "testharness" ], "gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers": [ @@ -337745,15 +337845,15 @@ "support" ], "gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [ - "cc1f4082fa420a9076f929d88268f5a1d921a44a", + "6f9c2974d9fa82d85ecc299990295f7bb44fbced", "testharness" ], "gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html": [ - "75429c87bbebd19df7b4edaddc5869c6202b3fab", + "413cad8e563dd38decb5e388a3a10363417cd413", "testharness" ], "gyroscope/Gyroscope-enabled-by-feature-policy.https.html": [ - "5129c05f9b226650a9b7fed4841871045525bf15", + "5c723e19f2f67d50d7e5d1ea75a5c09b4eeec4a3", "testharness" ], "gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers": [ @@ -337761,7 +337861,7 @@ "support" ], "gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html": [ - "2603bd858929ae6f84ebbe0cce34c5417ccdae06", + "3b6cc272c04aee446ce8dffbe041330e5c2298ea", "testharness" ], "gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers": [ @@ -337769,11 +337869,11 @@ "support" ], "gyroscope/Gyroscope.https-expected.txt": [ - "d2e562f7390f727627d5c39053c5c99313508428", + "b0a057a754e19f96e120240cdb478f58f12240ab", "support" ], "gyroscope/Gyroscope.https.html": [ - "504abfa42529e08576e49c3296464bcea5fe0b8a", + "e2b1919195d0af74bb7733a6d8a299adf43f4ee4", "testharness" ], "gyroscope/Gyroscope_insecure_context.html": [ @@ -337781,7 +337881,7 @@ "testharness" ], "gyroscope/Gyroscope_onerror-manual.https.html": [ - "1e15b883bd317ca83783864fc563794cb0f6df8e", + "c8f346f00bbc296e89e132926f974ee408d66fcf", "manual" ], "gyroscope/OWNERS": [ @@ -339901,7 +340001,7 @@ "support" ], "html/browsers/origin/origin-of-data-document.html": [ - "9fec457691ac4b071e9bc8de1ebf6f13dbadd4e5", + "844b162882b27fd3ec0a07c8d4c1a6a6254b69ca", "testharness" ], "html/browsers/origin/relaxing-the-same-origin-restriction/.gitkeep": [ @@ -358373,11 +358473,11 @@ "support" ], "magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt": [ - "9b71c24ebac69e42bc88eb682125608f2d121482", + "51726aed6ede1a2cad40d77b3d10c05017d34b6e", "support" ], "magnetometer/Magnetometer-disabled-by-feature-policy.https.html": [ - "9af542095f2fcd57691c0432ef3248b04a0207a0", + "33e6cbd89ec34e729d84f5a50bd7f75c47fa42e8", "testharness" ], "magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers": [ @@ -358385,27 +358485,27 @@ "support" ], "magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt": [ - "eeb13f720102302f7431eda65b7582e9ae269dbe", + "a20ddc097f247a109ee8c4d4322de2586844e439", "support" ], "magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [ - "47829ff5747eed99ba22e79b12ddfff288fd031e", + "3686719c3eab1867e5f5755dea11734f52123a68", "testharness" ], "magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https-expected.txt": [ - "ebd246e2346528a6a79886a8a8cce2b4b8eca945", + "429256377651387a4f60351f75375052816c6e69", "support" ], "magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html": [ - "3b6314e9176a24976d9d882644c30f00554eed6d", + "8c61e61e1a7b43a080991d12c7b469e30613a165", "testharness" ], "magnetometer/Magnetometer-enabled-by-feature-policy.https-expected.txt": [ - "c23861af9d1d4a8eaad2a3bf21bd4603d9eff5b2", + "7ea149699a3c4a0ceedd124e91e8bad80dd5dbff", "support" ], "magnetometer/Magnetometer-enabled-by-feature-policy.https.html": [ - "05128cdb7171ba230143e7b68b09968a484b602a", + "806b736a6320c82d5c6f10fae30ba5c35e695e10", "testharness" ], "magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers": [ @@ -358413,11 +358513,11 @@ "support" ], "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https-expected.txt": [ - "896aaed62339097d41937a839a8f3114b4d54611", + "5d15cb4f2b65da21c7115d614a552b4d0ca05599", "support" ], "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html": [ - "3240dafd2bc810dea0dc1ebc31728c86a29f2ec5", + "5871a3396ac4030f2202ea27f48fcb715de26236", "testharness" ], "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [ @@ -358425,11 +358525,11 @@ "support" ], "magnetometer/Magnetometer.https-expected.txt": [ - "e782e6fc41a3716f87073b5aa0dcac10690e4e03", + "19d0c8dddeee0d869e7924c71761565fc8ea34d0", "support" ], "magnetometer/Magnetometer.https.html": [ - "240e7d0af55b8681f2f45ca22283634acc406325", + "85b033df53fcaec4a55175f6a9438bd2abf5e6ff", "testharness" ], "magnetometer/Magnetometer_insecure_context.html": [ @@ -358437,11 +358537,11 @@ "testharness" ], "magnetometer/Magnetometer_onerror-manual.https-expected.txt": [ - "5535f83d0f9d1dc22d9d27d2dd000cd076e6dd98", + "71d027277b0af0e5264cc3f520145c0bdac528b6", "support" ], "magnetometer/Magnetometer_onerror-manual.https.html": [ - "da4e6b8975beecdcae24da26920a56a652f781e4", + "5da81d90bd6960c94d5b3dd7592aa4c93d996e1a", "manual" ], "magnetometer/OWNERS": [ @@ -367265,7 +367365,7 @@ "manual" ], "orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html": [ - "0c7657e32b46c64e5f050f04e40ccfc0dce32e47", + "d0ad686df1fc6e176a23f827f5afb61c55a7754b", "testharness" ], "orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers": [ @@ -367273,15 +367373,15 @@ "support" ], "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [ - "71a6966fb91f8ddfe15ee690c843e4621a3b4720", + "c666593365dba60ccf03a354f997bb86cab6581c", "testharness" ], "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html": [ - "9bbe39e1be4a669f31f0fb3960aca22d7d159c5e", + "cd0c5fb506d123dea5e162994e68e908b8e18fa0", "testharness" ], "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html": [ - "9f110b8ceca3dd3ce3d2a9e2567d92a3fc6462bf", + "260958b236c47b8d8796c8003ce3c1b1cedbe162", "testharness" ], "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers": [ @@ -367289,7 +367389,7 @@ "support" ], "orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html": [ - "c4404cf0b16c4d9ad15308392ecf52caee445b86", + "7d7709582f6fcfadd7000b79114a36adbf1c7dde", "testharness" ], "orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [ @@ -367300,6 +367400,10 @@ "e642947463a634fa4bc4e3adbfe85bc89b3ca174", "support" ], + "orientation-sensor/AbsoluteOrientationSensor.https.html": [ + "c482c21d4336decf5d4c47b4e6911dc2b03a19e9", + "testharness" + ], "orientation-sensor/OWNERS": [ "3f4a18cda77fd2fcb47f8892192c691cf201c574", "support" @@ -367308,20 +367412,16 @@ "b6295d76af50ccfbb086921827dc7e1eeae3e26b", "support" ], - "orientation-sensor/OrientationSensor.https.html": [ - "ea9a61f9d526183071a0336e11ca844f59c284a9", - "testharness" - ], "orientation-sensor/OrientationSensor_insecure_context.html": [ "eb64da888f1bedf9d5ed8b11edc1626da88b322b", "testharness" ], "orientation-sensor/OrientationSensor_onerror-manual.https.html": [ - "6f0eb976affc21e49f48c42c1bd9d9eb0083ee40", + "c7d57da56142057f23503da971875df46ef6d137", "manual" ], "orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html": [ - "8c6c5f8f3bc4421f5143a3e4fab287564cf4907d", + "c45d0a4cbfa68431c97e6d6288a9e57161100733", "testharness" ], "orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers": [ @@ -367329,15 +367429,15 @@ "support" ], "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [ - "34a79c9033a41c0aceab3fa6a470dd5a76f2ac81", + "fb57e3d552c56f9b7e21f461b4938d850c5c9d8a", "testharness" ], "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html": [ - "0e6260ccdaa8163b8db96516960be226a4d85ba7", + "04bf99c095016b4f39a99819f0cf3b5742c7e436", "testharness" ], "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html": [ - "243b2d60d4c528a77e9cfb68fa256b35234e7346", + "2286335655c89a9428193cd42a42ec1df7ddf333", "testharness" ], "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers": [ @@ -367345,7 +367445,7 @@ "support" ], "orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html": [ - "c9f234f6508fb778fdf91277bb8950c99479979d", + "4b529302141beb7cdf2b6569a0f836dc378ba062", "testharness" ], "orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [ @@ -367356,10 +367456,18 @@ "bfda2f7ce33918474e05c50052b5216b254c6226", "support" ], + "orientation-sensor/RelativeOrientationSensor.https.html": [ + "9bf83c64eb5dcf284eb6c45db8ac278ab3c637a2", + "testharness" + ], "orientation-sensor/idlharness.https.html": [ "1f94329cb330a1a904d409a6e158a5fe9f8dd709", "testharness" ], + "orientation-sensor/orientation-sensor-tests.js": [ + "250d6009213e72069acd56e847fc9509c52c1d90", + "support" + ], "page-visibility/OWNERS": [ "ef8e006eb532afaf6f561aa9ba2a46afa6b5693c", "support" @@ -367785,7 +367893,7 @@ "testharness" ], "payment-request/payment-request-not-exposed.https.worker.js": [ - "b1c3cdc182cb967ec11b1cad826b333511203d77", + "957e88d8e5f212254140487b6980abf40cf5ed96", "testharness" ], "payment-request/payment-request-onshippingaddresschange-attribute.https.html": [ @@ -377808,6 +377916,18 @@ "10f756bbf749b7ad8f7c6eb4efe752ee79c44b4a", "testharness" ], + "server-timing/service_worker_idl-expected.txt": [ + "ecc444813caba5ddc5baece8fdbaa6ca377a6d10", + "support" + ], + "server-timing/service_worker_idl.html": [ + "cb5ea3136399f88fb6c4e8071ad8e3b7ccebb242", + "testharness" + ], + "server-timing/sw.js": [ + "0c12328f152814e2f0bde7fe026cf12c8ea77ff0", + "support" + ], "server-timing/test_server_timing.html": [ "7c778ca856e5cff0bbc785f59c9ccf1ec86456fb", "testharness" @@ -379785,7 +379905,7 @@ "support" ], "service-workers/service-worker/resources/resource-timing-worker.js": [ - "2a47775874086c1cdff257e3243af1af0b5e84be", + "04a965dc0324c035bb3331e546d9bb43230d5eac", "support" ], "service-workers/service-worker/resources/respond-then-throw-worker.js": [ @@ -383653,7 +383773,7 @@ "support" ], "url/setters_tests.json": [ - "8d58bd1c98f4d987e6abe66659c812591b197e60", + "7c9707c02714de9a17989ecc71775978e994ae8a", "support" ], "url/toascii.json": [ @@ -384956,6 +385076,18 @@ "7e35ac29f00d39c84230535212c0b9ea081951d3", "testharness" ], + "webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-basic.html": [ + "a4058a967414b087e19ad8dd2af0999152f1491c", + "testharness" + ], + "webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html": [ + "f4a4122ebd500cba1d5fb383369849e31f73d7f7", + "testharness" + ], + "webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-sizing.html": [ + "9389a7e0b4c115a756e547225140150136d1103d", + "testharness" + ], "webaudio/the-audio-api/the-analysernode-interface/test-analyser-gain.html": [ "e2320e33ef1df0155d5fcf536550e0e398b15407", "testharness" @@ -385012,6 +385144,18 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], + "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html": [ + "03d32deacab7a98f3cce29562b84158e3f512668", + "testharness" + ], + "webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html": [ + "0ef6d19b75e1437ea71846d5a0d1af7dd426dc83", + "testharness" + ], + "webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html": [ + "21ea30d8fa92e908da66e79fd127e8fa0203a4c5", + "testharness" + ], "webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -386329,7 +386473,7 @@ "support" ], "webrtc/RTCDTMFSender-insertDTMF.https.html": [ - "79574cff7e0500cecaf7e3ae182e89d98f49ce72", + "a5fc15d44fe572744c07d933b9204d9319c968cd", "testharness" ], "webrtc/RTCDTMFSender-ontonechange-long.https.html": [ @@ -386389,7 +386533,7 @@ "support" ], "webrtc/RTCIceTransport.html": [ - "c145a8a34c79dd970475e77ff5bf1a363c0ac56c", + "db758cc2a744c049c291575e408dbb5f280cdf19", "testharness" ], "webrtc/RTCPeerConnection-addIceCandidate-expected.txt": [ @@ -386421,7 +386565,7 @@ "support" ], "webrtc/RTCPeerConnection-canTrickleIceCandidates.html": [ - "0f585a89bd8f25aa8f83b6ec39b704cbb8e970b2", + "8401fdc22f8f8867aa361f6a83834cdeb7a2a9d1", "testharness" ], "webrtc/RTCPeerConnection-connectionState-expected.txt": [ @@ -386501,7 +386645,7 @@ "support" ], "webrtc/RTCPeerConnection-getStats.https.html": [ - "9446d7bc1aefa7edd28b425415d983d69311e0ca", + "913cbc3d2aaf724e70108e7854f56ad5bb9b2283", "testharness" ], "webrtc/RTCPeerConnection-getTransceivers-expected.txt": [ @@ -386561,7 +386705,7 @@ "support" ], "webrtc/RTCPeerConnection-peerIdentity.html": [ - "1cc5702e0aee887d925d2bf3471ac759d7430874", + "5aa9f3d712dd320cc85645abd39f960b5072349b", "testharness" ], "webrtc/RTCPeerConnection-removeTrack.https-expected.txt": [ @@ -386577,7 +386721,7 @@ "support" ], "webrtc/RTCPeerConnection-setDescription-transceiver.html": [ - "aab677c9196488544b30c7eecd180c3046290bb2", + "4d0d9a168327e62eefc0d4398874fd944c50b43c", "testharness" ], "webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt": [ @@ -386785,7 +386929,7 @@ "support" ], "webrtc/RTCRtpReceiver-getSynchronizationSources.https.html": [ - "56d0157f4ce987436c12ddff886b74549abbe682", + "11aa1d9f6833dd019ae7ade7b9ec14780f271650", "testharness" ], "webrtc/RTCRtpSender-getCapabilities-expected.txt": [ @@ -386801,7 +386945,7 @@ "support" ], "webrtc/RTCRtpSender-getStats.https.html": [ - "64c4424e36c566294a317fb423eb02e97a9ebbca", + "ee215306e1d9d1fdcb65bd5244da09fb2005e799", "testharness" ], "webrtc/RTCRtpSender-replaceTrack-expected.txt": [ @@ -394264,6 +394408,10 @@ "42182437d8c1015339825c035127877f4970decb", "testharness" ], + "xhr/sync-no-progress.any.js": [ + "db6171c61a37cd98ea5b9c1549432f1e2b53e7eb", + "testharness" + ], "xhr/template-element.html": [ "748f12beaa646e244f8312afd545f56075cac727", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/README.md b/third_party/WebKit/LayoutTests/external/wpt/README.md index e43a05f..2a0007c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/README.md +++ b/third_party/WebKit/LayoutTests/external/wpt/README.md
@@ -69,22 +69,19 @@ ``` This will start HTTP servers on two ports and a websockets server on -one port. By default the web servers start on ports 8000 and 8443 and the other -ports are randomly-chosen free ports. Tests must be loaded from the -*first* HTTP server in the output. To change the ports, copy the -`config.default.json` file to `config.json` and edit the new file, -replacing the part that reads: +one port. By default the web servers start on ports 8000 and 8443 and +the other ports are randomly-chosen free ports. Tests must be loaded +from the *first* HTTP server in the output. To change the ports, +create a `config.json` file in the wpt root directory, and add +port definitions of your choice e.g.: ``` -"http": [8000, "auto"], -"https":[8443] -``` - -to some ports of your choice e.g. - -``` -"http": [1234, "auto"], -"https":[5678] +{ + "ports": { + "http": [1234, "auto"], + "https":[5678] + } +} ``` After your `hosts` file is configured, the servers will be locally accessible at: @@ -262,11 +259,26 @@ error when you start wptserve. Finally, set the path value in the server configuration file to the -default OpenSSL configuration file location. To do this, -copy `config.default.json` in the web-platform-tests root to `config.json`. -Then edit the JSON so that the key `ssl/openssl/base_conf_path` has a -value that is the path to the OpenSSL config file (typically this -will be `C:\\OpenSSL-Win32\\bin\\openssl.cfg`). +default OpenSSL configuration file location. To do this create a file +called `config.json`. Then add the OpenSSL configuration below, +ensuring that the key `ssl/openssl/base_conf_path` has a value that is +the path to the OpenSSL config file (typically this will be +`C:\\OpenSSL-Win32\\bin\\openssl.cfg`): + +``` +{ + "ssl": { + "type": "openssl", + "encrypt_after_connect": false, + "openssl": { + "openssl_binary": "openssl", + "base_path: "_certs", + "force_regenerate": false, + "base_conf_path": "C:\\OpenSSL-Win32\\bin\\openssl.cfg" + }, + }, +} +``` ### Trusting Root CA
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https-expected.txt index cfcbdbf..f74a581 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https-expected.txt
@@ -1,10 +1,12 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined PASS Accelerometer: Feature-Policy header accelerometer 'none' disallows the top-level document. PASS Accelerometer: Feature-Policy header accelerometer 'none' disallows same-origin iframes. PASS Accelerometer: Feature-Policy header accelerometer 'none' disallows cross-origin iframes. PASS LinearAccelerationSensor: Feature-Policy header accelerometer 'none' disallows the top-level document. PASS LinearAccelerationSensor: Feature-Policy header accelerometer 'none' disallows same-origin iframes. PASS LinearAccelerationSensor: Feature-Policy header accelerometer 'none' disallows cross-origin iframes. +FAIL GravitySensor: Feature-Policy header accelerometer 'none' disallows the top-level document. assert_true: expected true got false +FAIL GravitySensor: Feature-Policy header accelerometer 'none' disallows same-origin iframes. assert_true: expected true got false +FAIL GravitySensor: Feature-Policy header accelerometer 'none' disallows cross-origin iframes. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https.html index 9476efb..041ddc4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-disabled-by-feature-policy.https.html
@@ -8,8 +8,8 @@ <script> "use strict"; -run_fp_tests_disabled(Accelerometer); -run_fp_tests_disabled(LinearAccelerationSensor); -run_fp_tests_disabled(GravitySensor); +run_fp_tests_disabled('Accelerometer'); +run_fp_tests_disabled('LinearAccelerationSensor'); +run_fp_tests_disabled('GravitySensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt index 6647e64..15433268 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt
@@ -1,8 +1,9 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined PASS Accelerometer: Feature-Policy allow='accelerometer' attribute allows same-origin relocation PASS Accelerometer: Feature-Policy allow='accelerometer' attribute disallows cross-origin relocation PASS LinearAccelerationSensor: Feature-Policy allow='accelerometer' attribute allows same-origin relocation PASS LinearAccelerationSensor: Feature-Policy allow='accelerometer' attribute disallows cross-origin relocation +FAIL GravitySensor: Feature-Policy allow='accelerometer' attribute allows same-origin relocation assert_true: expected true got false +FAIL GravitySensor: Feature-Policy allow='accelerometer' attribute disallows cross-origin relocation assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html index aa8ea10..53f6960 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -8,8 +8,8 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute_redirect_on_load(Accelerometer); -run_fp_tests_enabled_by_attribute_redirect_on_load(LinearAccelerationSensor); -run_fp_tests_enabled_by_attribute_redirect_on_load(GravitySensor); +run_fp_tests_enabled_by_attribute_redirect_on_load('Accelerometer'); +run_fp_tests_enabled_by_attribute_redirect_on_load('LinearAccelerationSensor'); +run_fp_tests_enabled_by_attribute_redirect_on_load('GravitySensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https-expected.txt index 7a276b03..54b1ecd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https-expected.txt
@@ -1,8 +1,9 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined PASS Accelerometer: Feature-Policy allow='accelerometer' attribute allows same-origin iframe PASS Accelerometer: Feature-Policy allow='accelerometer' attribute allows cross-origin iframe PASS LinearAccelerationSensor: Feature-Policy allow='accelerometer' attribute allows same-origin iframe PASS LinearAccelerationSensor: Feature-Policy allow='accelerometer' attribute allows cross-origin iframe +FAIL GravitySensor: Feature-Policy allow='accelerometer' attribute allows same-origin iframe assert_true: expected true got false +FAIL GravitySensor: Feature-Policy allow='accelerometer' attribute allows cross-origin iframe assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html index 860a027..3dd49d3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html
@@ -8,8 +8,8 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute(Accelerometer); -run_fp_tests_enabled_by_attribute(LinearAccelerationSensor); -run_fp_tests_enabled_by_attribute(GravitySensor); +run_fp_tests_enabled_by_attribute('Accelerometer'); +run_fp_tests_enabled_by_attribute('LinearAccelerationSensor'); +run_fp_tests_enabled_by_attribute('GravitySensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https-expected.txt index e4db6df..ceb8850 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https-expected.txt
@@ -1,10 +1,12 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined PASS Accelerometer: Feature-Policy header accelerometer * allows the top-level document. PASS Accelerometer: Feature-Policy header accelerometer * allows same-origin iframes. PASS Accelerometer: Feature-Policy header accelerometer * allows cross-origin iframes. PASS LinearAccelerationSensor: Feature-Policy header accelerometer * allows the top-level document. PASS LinearAccelerationSensor: Feature-Policy header accelerometer * allows same-origin iframes. PASS LinearAccelerationSensor: Feature-Policy header accelerometer * allows cross-origin iframes. +FAIL GravitySensor: Feature-Policy header accelerometer * allows the top-level document. assert_true: expected true got false +FAIL GravitySensor: Feature-Policy header accelerometer * allows same-origin iframes. assert_true: expected true got false +FAIL GravitySensor: Feature-Policy header accelerometer * allows cross-origin iframes. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https.html index 889047a0..f5d0897 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-by-feature-policy.https.html
@@ -8,8 +8,8 @@ <script> "use strict"; -run_fp_tests_enabled(Accelerometer); -run_fp_tests_enabled(LinearAccelerationSensor); -run_fp_tests_enabled(GravitySensor); +run_fp_tests_enabled('Accelerometer'); +run_fp_tests_enabled('LinearAccelerationSensor'); +run_fp_tests_enabled('GravitySensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https-expected.txt index b196236..b22f0e5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https-expected.txt
@@ -1,10 +1,12 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined PASS Accelerometer: Feature-Policy header accelerometer 'self' allows the top-level document. PASS Accelerometer: Feature-Policy header accelerometer 'self' allows same-origin iframes. PASS Accelerometer: Feature-Policy header accelerometer 'self' disallows cross-origin iframes. PASS LinearAccelerationSensor: Feature-Policy header accelerometer 'self' allows the top-level document. PASS LinearAccelerationSensor: Feature-Policy header accelerometer 'self' allows same-origin iframes. PASS LinearAccelerationSensor: Feature-Policy header accelerometer 'self' disallows cross-origin iframes. +FAIL GravitySensor: Feature-Policy header accelerometer 'self' allows the top-level document. assert_true: expected true got false +FAIL GravitySensor: Feature-Policy header accelerometer 'self' allows same-origin iframes. assert_true: expected true got false +FAIL GravitySensor: Feature-Policy header accelerometer 'self' disallows cross-origin iframes. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html index bf45852..2074562 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html
@@ -8,8 +8,8 @@ <script> "use strict"; -run_fp_tests_enabled_on_self_origin(Accelerometer); -run_fp_tests_enabled_on_self_origin(LinearAccelerationSensor); -run_fp_tests_enabled_on_self_origin(GravitySensor); +run_fp_tests_enabled_on_self_origin('Accelerometer'); +run_fp_tests_enabled_on_self_origin('LinearAccelerationSensor'); +run_fp_tests_enabled_on_self_origin('GravitySensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt index 8649567..f9d1e1a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt
@@ -1,20 +1,45 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined -FAIL Accelerometer: Test that 'onreading' is called and sensor reading is valid assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: sensor reading is correct assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: sensor timestamp is updated when time passes assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: Test that sensor can be successfully created and its states are correct. assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Accelerometer: sensor.start() returns undefined assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Accelerometer: no exception is thrown when calling start() on already started sensor assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Accelerometer: sensor.stop() returns undefined assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Accelerometer: no exception is thrown when calling stop() on already stopped sensor assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Accelerometer: Test that fresh reading is fetched on start() assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: sensor readings can not be fired on the background tab assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: frequency hint works promise_test: Unhandled rejection with value: object "[object SensorErrorEvent]" -FAIL Accelerometer: sensor receives suspend / resume notifications when cross-origin subframe is focused assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: throw 'NotSupportedError' for an unsupported sensor option assert_throws: function "() => { new sensorType({invalid: 1}) }" did not throw +PASS Accelerometer: Test that 'onreading' is called and sensor reading is valid +PASS Accelerometer: sensor reading is correct +PASS Accelerometer: sensor timestamp is updated when time passes +PASS Accelerometer: Test that sensor can be successfully created and its states are correct. +PASS Accelerometer: sensor.start() returns undefined +PASS Accelerometer: no exception is thrown when calling start() on already started sensor +PASS Accelerometer: sensor.stop() returns undefined +PASS Accelerometer: no exception is thrown when calling stop() on already stopped sensor +PASS Accelerometer: Test that fresh reading is fetched on start() +PASS Accelerometer: frequency hint works +PASS Accelerometer: sensor receives suspend / resume notifications when cross-origin subframe is focused FAIL Accelerometer: throw 'TypeError' if frequency is invalid assert_throws: when freq is undefined function "() => { new sensorType({frequency: freq}) }" did not throw -FAIL Accelerometer: sensor reading is correct when options.referenceFrame is 'screen' assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Accelerometer: throw 'TypeError' if referenceFrame is not one of enumeration values assert_throws: when refFrame is undefined function "() => { new sensorType({referenceFrame: refFrame}) }" did not throw +PASS Accelerometer: sensor reading is correct when options.referenceFrame is 'screen' +PASS Accelerometer: throw 'TypeError' if referenceFrame is not one of enumeration values +FAIL GravitySensor: Test that 'onreading' is called and sensor reading is valid assert_true: expected true got false +FAIL GravitySensor: sensor reading is correct assert_true: expected true got false +FAIL GravitySensor: sensor timestamp is updated when time passes assert_true: expected true got false +FAIL GravitySensor: Test that sensor can be successfully created and its states are correct. assert_true: expected true got false +FAIL GravitySensor: sensor.start() returns undefined assert_true: expected true got false +FAIL GravitySensor: no exception is thrown when calling start() on already started sensor assert_true: expected true got false +FAIL GravitySensor: sensor.stop() returns undefined assert_true: expected true got false +FAIL GravitySensor: no exception is thrown when calling stop() on already stopped sensor assert_true: expected true got false +FAIL GravitySensor: Test that fresh reading is fetched on start() assert_true: expected true got false +FAIL GravitySensor: frequency hint works assert_true: expected true got false +FAIL GravitySensor: sensor receives suspend / resume notifications when cross-origin subframe is focused assert_true: expected true got false +FAIL GravitySensor: throw 'TypeError' if frequency is invalid assert_true: expected true got false +FAIL GravitySensor: sensor reading is correct when options.referenceFrame is 'screen' assert_true: expected true got false +FAIL GravitySensor: throw 'TypeError' if referenceFrame is not one of enumeration values assert_true: expected true got false +PASS LinearAccelerationSensor: Test that 'onreading' is called and sensor reading is valid +PASS LinearAccelerationSensor: sensor reading is correct +PASS LinearAccelerationSensor: sensor timestamp is updated when time passes +PASS LinearAccelerationSensor: Test that sensor can be successfully created and its states are correct. +PASS LinearAccelerationSensor: sensor.start() returns undefined +PASS LinearAccelerationSensor: no exception is thrown when calling start() on already started sensor +PASS LinearAccelerationSensor: sensor.stop() returns undefined +PASS LinearAccelerationSensor: no exception is thrown when calling stop() on already stopped sensor +PASS LinearAccelerationSensor: Test that fresh reading is fetched on start() +PASS LinearAccelerationSensor: frequency hint works +PASS LinearAccelerationSensor: sensor receives suspend / resume notifications when cross-origin subframe is focused +FAIL LinearAccelerationSensor: throw 'TypeError' if frequency is invalid assert_throws: when freq is undefined function "() => { new sensorType({frequency: freq}) }" did not throw +PASS LinearAccelerationSensor: sensor reading is correct when options.referenceFrame is 'screen' +PASS LinearAccelerationSensor: throw 'TypeError' if referenceFrame is not one of enumeration values Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https.html index 9563270..b601c61 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https.html
@@ -9,8 +9,8 @@ <div id="log"></div> <script> -runGenericSensorTests(Accelerometer); -runGenericSensorTests(GravitySensor); -runGenericSensorTests(LinearAccelerationSensor); +runGenericSensorTests('Accelerometer'); +runGenericSensorTests('GravitySensor'); +runGenericSensorTests('LinearAccelerationSensor'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https-expected.txt index d0f2a19..54466064 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https-expected.txt
@@ -1,5 +1,6 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GravitySensor is not defined PASS Accelerometer: 'onerror' event is fired when sensor is not supported +FAIL GravitySensor: 'onerror' event is fired when sensor is not supported assert_true: expected true got false +PASS LinearAccelerationSensor: 'onerror' event is fired when sensor is not supported Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https.html index f69b1b6..dec2188 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer_onerror-manual.https.html
@@ -15,8 +15,8 @@ </ol> <script> -runGenericSensorOnerror(Accelerometer); -runGenericSensorOnerror(GravitySensor); -runGenericSensorOnerror(LinearAccelerationSensor); +runGenericSensorOnerror('Accelerometer'); +runGenericSensorOnerror('GravitySensor'); +runGenericSensorOnerror('LinearAccelerationSensor'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot.js b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot.js index deeeaa0..5b048d33 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot.js +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot.js
@@ -4,6 +4,6 @@ // which found out that some script resources are served // with text/html content-type and with a body that is // both a valid html and a valid javascript. -window.polyglot = 123; +window.polyglot = "html-js-polyglot.js"; //--></script></body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot2.js b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot2.js new file mode 100644 index 0000000..9443f8e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot2.js
@@ -0,0 +1,10 @@ +<!-- comment --> <script type='text/javascript'> +//<![CDATA[ + +// This is a regression test for https://crbug.com/839945 +// which found out that some script resources are served +// with text/html content-type and with a body that is +// both a valid html and a valid javascript. +window.polyglot = "html-js-polyglot2.js"; + +//]]>--></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot2.js.headers b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot2.js.headers new file mode 100644 index 0000000..156209f9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/resources/html-js-polyglot2.js.headers
@@ -0,0 +1 @@ +Content-Type: text/html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html index 950a907..ec41037 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/corb/script-html-js-polyglot.sub.html
@@ -7,23 +7,26 @@ <script src=/resources/testharnessreport.js></script> <div id=log></div> <script> -async_test(function(t) { - var script = document.createElement("script") +["html-js-polyglot.js", "html-js-polyglot2.js"].forEach(polyglot_name => { + async_test(function(t) { + window.polyglot = "not yet set by the script"; + var script = document.createElement("script"); - script.onload = t.step_func_done(function(){ - // Verify that html-js-polyglot.js wasn't blocked - that script - // should have set window.polyglot to 123. - assert_equals(window.polyglot, 123); - }) - addEventListener("error",function(e) { - t.step(function() { - assert_unreached("No errors are expected with or without CORB."); - t.done(); + script.onload = t.step_func_done(function(){ + // Verify that the script response wasn't blocked - that script + // should have set window.polyglot to |polyglot_name|. + assert_equals(window.polyglot, polyglot_name); }) - }); + addEventListener("error",function(e) { + t.step(function() { + assert_unreached("No errors are expected with or without CORB."); + t.done(); + }) + }); - // www1 is cross-origin, so the HTTP response is CORB-eligible. - script.src = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/corb/resources/html-js-polyglot.js" - document.body.appendChild(script) -}, "CORB cannot block polyglot HTML/JS"); + // www1 is cross-origin, so the HTTP response is CORB-eligible. + script.src = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/corb/resources/" + polyglot_name; + document.body.appendChild(script); + }, "CORB cannot block polyglot HTML/JS: " + polyglot_name); +}); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/README.md b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/README.md new file mode 100644 index 0000000..993e0c5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/README.md
@@ -0,0 +1,20 @@ +The `generic-sensor-tests.js` tests require an implementation of +the `GenericSensorTest` interface, which should emulate platform +sensor backends. The `GenericSensorTest` interface is defined as: + +``` + class GenericSensorTest { + async initialize(); // Sets up the testing enviroment. + async reset(); // Frees the resources. + }; +``` + +The Chromium implementation of the `GenericSensorTest` interface is located in +[generic_sensor_mocks.js](../resources/chromium/generic_sensor_mocks.js). + +Other browser vendors should provide their own implementations of +the `GenericSensorTest` interface. + +[Known issue](https://github.com/w3c/web-platform-tests/issues/9686): a +WebDriver extension is a better approach for the Generic Sensor tests +automation.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-feature-policy-test.sub.js b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-feature-policy-test.sub.js index f722315..94e5347 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-feature-policy-test.sub.js +++ b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-feature-policy-test.sub.js
@@ -17,17 +17,19 @@ "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src; const base_src = "/feature-policy/resources/redirect-on-load.html#"; -function run_fp_tests_disabled(sensorType) { - const sensorName = sensorType.name; +function run_fp_tests_disabled(sensorName) { + const sensorType = self[sensorName]; const featureNameList = feature_policies[sensorName]; const header = "Feature-Policy header " + featureNameList.join(" 'none';") + " 'none'"; const desc = "'new " + sensorName + "()'"; test(() => { + assert_true(sensorName in self); assert_throws("SecurityError", () => {new sensorType()}); }, `${sensorName}: ${header} disallows the top-level document.`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -37,6 +39,7 @@ }, `${sensorName}: ${header} disallows same-origin iframes.`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -46,17 +49,18 @@ }, `${sensorName}: ${header} disallows cross-origin iframes.`); } -function run_fp_tests_enabled(sensorType) { - const sensorName = sensorType.name; +function run_fp_tests_enabled(sensorName) { + const sensorType = self[sensorName]; const featureNameList = feature_policies[sensorName]; const header = "Feature-Policy header " + featureNameList.join(" *;") + " *"; const desc = "'new " + sensorName + "()'"; test(() => { - assert_true(sensorName in window); + assert_true(sensorName in self); }, `${sensorName}: ${header} allows the top-level document.`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -66,6 +70,7 @@ }, `${sensorName}: ${header} allows same-origin iframes.`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -75,13 +80,14 @@ }, `${sensorName}: ${header} allows cross-origin iframes.`); } -function run_fp_tests_enabled_by_attribute(sensorType) { - const sensorName = sensorType.name; +function run_fp_tests_enabled_by_attribute(sensorName) { + const sensorType = self[sensorName]; const featureNameList = feature_policies[sensorName]; const header = "Feature-Policy allow='" + featureNameList.join(" ") + "' attribute"; const desc = "'new " + sensorName + "()'"; async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -92,6 +98,7 @@ }, `${sensorName}: ${header} allows same-origin iframe`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -102,13 +109,14 @@ }, `${sensorName}: ${header} allows cross-origin iframe`); } -function run_fp_tests_enabled_by_attribute_redirect_on_load(sensorType) { - const sensorName = sensorType.name; +function run_fp_tests_enabled_by_attribute_redirect_on_load(sensorName) { + const sensorType = self[sensorName]; const featureNameList = feature_policies[sensorName]; const header = "Feature-Policy allow='" + featureNameList.join(" ") + "' attribute"; const desc = "'new " + sensorName + "()'"; async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -119,6 +127,7 @@ }, `${sensorName}: ${header} allows same-origin relocation`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -129,17 +138,18 @@ }, `${sensorName}: ${header} disallows cross-origin relocation`); } -function run_fp_tests_enabled_on_self_origin(sensorType) { - const sensorName = sensorType.name; +function run_fp_tests_enabled_on_self_origin(sensorName) { + const sensorType = self[sensorName]; const featureNameList = feature_policies[sensorName]; const header = "Feature-Policy header " + featureNameList.join(" 'self';") + " 'self'"; const desc = "'new " + sensorName + "()'"; test(() => { - assert_true(sensorName in window); + assert_true(sensorName in self); }, `${sensorName}: ${header} allows the top-level document.`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t, @@ -149,6 +159,7 @@ }, `${sensorName}: ${header} allows same-origin iframes.`); async_test(t => { + assert_true(sensorName in self); test_feature_availability( desc, t,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js index ece481b..da2e65d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js +++ b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js
@@ -1,3 +1,54 @@ +// These tests rely on the User Agent providing an implementation of +// platform sensor backends. +// +// In Chromium-based browsers this implementation is provided by a polyfill +// in order to reduce the amount of test-only code shipped to users. To enable +// these tests the browser must be run with these options: +// +// --enable-blink-features=MojoJS,MojoJSTest +let loadChromiumResources = Promise.resolve().then(() => { + if (!MojoInterfaceInterceptor) { + // Do nothing on non-Chromium-based browsers or when the Mojo bindings are + // not present in the global namespace. + return; + } + + let chain = Promise.resolve(); + [ + '/resources/chromium/mojo_bindings.js', + '/resources/chromium/string16.mojom.js', + '/resources/chromium/sensor.mojom.js', + '/resources/chromium/sensor_provider.mojom.js', + '/resources/chromium/generic_sensor_mocks.js', + ].forEach(path => { + let script = document.createElement('script'); + script.src = path; + script.async = false; + chain = chain.then(() => new Promise(resolve => { + script.onload = resolve; + })); + document.head.appendChild(script); + }); + + return chain; +}); + +function sensor_test(func, name, properties) { + promise_test(async (t) => { + if (typeof GenericSensorTest === 'undefined') { + await loadChromiumResources; + } + assert_true(typeof GenericSensorTest !== 'undefined'); + let sensorTest = new GenericSensorTest(); + await sensorTest.initialize(); + try { + await func(t); + } finally { + await sensorTest.reset(); + }; + }, name, properties); +} + const properties = { 'AmbientLightSensor' : ['timestamp', 'illuminance'], 'Accelerometer' : ['timestamp', 'x', 'y', 'z'], @@ -45,8 +96,11 @@ return arr; } -function runGenericSensorTests(sensorType) { - promise_test(async t => { +function runGenericSensorTests(sensorName) { + const sensorType = self[sensorName]; + + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); sensor.start(); @@ -58,9 +112,10 @@ sensor.stop(); assert_reading_null(sensor); assert_false(sensor.hasReading); - }, `${sensorType.name}: Test that 'onreading' is called and sensor reading is valid`); + }, `${sensorName}: Test that 'onreading' is called and sensor reading is valid`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor1 = new sensorType(); const sensor2 = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor1, ["reading", "error"]); @@ -79,9 +134,10 @@ assert_reading_not_null(sensor2); sensor2.stop(); assert_reading_null(sensor2); - }, `${sensorType.name}: sensor reading is correct`); + }, `${sensorName}: sensor reading is correct`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); sensor.start(); @@ -94,9 +150,10 @@ assert_greater_than(cachedTimeStamp2, cachedTimeStamp1); sensor.stop(); - }, `${sensorType.name}: sensor timestamp is updated when time passes`); + }, `${sensorName}: sensor timestamp is updated when time passes`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); assert_false(sensor.activated); @@ -108,9 +165,10 @@ sensor.stop(); assert_false(sensor.activated); - }, `${sensorType.name}: Test that sensor can be successfully created and its states are correct.`); + }, `${sensorName}: Test that sensor can be successfully created and its states are correct.`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); const start_return = sensor.start(); @@ -118,9 +176,10 @@ await sensorWatcher.wait_for("activate"); assert_equals(start_return, undefined); sensor.stop(); - }, `${sensorType.name}: sensor.start() returns undefined`); + }, `${sensorName}: sensor.start() returns undefined`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); sensor.start(); @@ -129,9 +188,10 @@ await sensorWatcher.wait_for("activate"); assert_true(sensor.activated); sensor.stop(); - }, `${sensorType.name}: no exception is thrown when calling start() on already started sensor`); + }, `${sensorName}: no exception is thrown when calling start() on already started sensor`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); sensor.start(); @@ -139,9 +199,10 @@ await sensorWatcher.wait_for("activate"); const stop_return = sensor.stop(); assert_equals(stop_return, undefined); - }, `${sensorType.name}: sensor.stop() returns undefined`); + }, `${sensorName}: sensor.stop() returns undefined`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); sensor.start(); @@ -150,9 +211,10 @@ sensor.stop(); sensor.stop(); assert_false(sensor.activated); - }, `${sensorType.name}: no exception is thrown when calling stop() on already stopped sensor`); + }, `${sensorName}: no exception is thrown when calling stop() on already stopped sensor`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); sensor.start(); @@ -169,28 +231,30 @@ assert_greater_than(timestamp, 0); assert_greater_than(sensor.timestamp, timestamp); sensor.stop(); - }, `${sensorType.name}: Test that fresh reading is fetched on start()`); + }, `${sensorName}: Test that fresh reading is fetched on start()`); - promise_test(async t => { - const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); - const visibilityChangeWatcher = new EventWatcher(t, document, "visibilitychange"); - sensor.start(); +// TBD file a WPT issue: visibilityChangeWatcher times out. +// sensor_test(async t => { +// const sensor = new sensorType(); +// const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); +// const visibilityChangeWatcher = new EventWatcher(t, document, "visibilitychange"); +// sensor.start(); - await sensorWatcher.wait_for("reading"); - assert_reading_not_null(sensor); - const cachedSensor1 = reading_to_array(sensor); +// await sensorWatcher.wait_for("reading"); +// assert_reading_not_null(sensor); +// const cachedSensor1 = reading_to_array(sensor); - const win = window.open('', '_blank'); - await visibilityChangeWatcher.wait_for("visibilitychange"); - const cachedSensor2 = reading_to_array(sensor); +// const win = window.open('', '_blank'); +// await visibilityChangeWatcher.wait_for("visibilitychange"); +// const cachedSensor2 = reading_to_array(sensor); - win.close(); - sensor.stop(); - assert_object_equals(cachedSensor1, cachedSensor2); - }, `${sensorType.name}: sensor readings can not be fired on the background tab`); +// win.close(); +// sensor.stop(); +// assert_object_equals(cachedSensor1, cachedSensor2); +// }, `${sensorName}: sensor readings can not be fired on the background tab`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const fastSensor = new sensorType({frequency: 30}); const slowSensor = new sensorType({frequency: 5}); slowSensor.start(); @@ -217,9 +281,10 @@ }); assert_greater_than(fastCounter, 2, "Fast sensor overtakes the slow one"); - }, `${sensorType.name}: frequency hint works`); + }, `${sensorName}: frequency hint works`); - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); // Create a focused editbox inside a cross-origin iframe, // sensor notification must suspend. const iframeSrc = 'data:text/html;charset=utf-8,<html><body>' @@ -248,18 +313,20 @@ assert_greater_than(sensor.timestamp, cachedTimestamp); sensor.stop(); - }, `${sensorType.name}: sensor receives suspend / resume notifications when\ + }, `${sensorName}: sensor receives suspend / resume notifications when\ cross-origin subframe is focused`); - test(() => { - assert_throws("NotSupportedError", () => { new sensorType({invalid: 1}) }); - assert_throws("NotSupportedError", () => { new sensorType({frequency: 60, invalid: 1}) }); - if (spatialSensors.indexOf(sensorType.name) == -1) { - assert_throws("NotSupportedError", () => { new sensorType({referenceFrame: "screen"}) }); - } - }, `${sensorType.name}: throw 'NotSupportedError' for an unsupported sensor option`); +// Re-enable after https://github.com/w3c/sensors/issues/361 is fixed. +// test(() => { +// assert_throws("NotSupportedError", () => { new sensorType({invalid: 1}) }); +// assert_throws("NotSupportedError", () => { new sensorType({frequency: 60, invalid: 1}) }); +// if (spatialSensors.indexOf(sensorName) == -1) { +// assert_throws("NotSupportedError", () => { new sensorType({referenceFrame: "screen"}) }); +// } +// }, `${sensorName}: throw 'NotSupportedError' for an unsupported sensor option`); test(() => { + assert_true(sensorName in self); const invalidFreqs = [ "invalid", NaN, @@ -273,14 +340,15 @@ () => { new sensorType({frequency: freq}) }, `when freq is ${freq}`); }); - }, `${sensorType.name}: throw 'TypeError' if frequency is invalid`); + }, `${sensorName}: throw 'TypeError' if frequency is invalid`); - if (spatialSensors.indexOf(sensorType.name) == -1) { + if (spatialSensors.indexOf(sensorName) == -1) { // The sensorType does not represent a spatial sensor. return; } - promise_test(async t => { + sensor_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType({referenceFrame: "screen"}); const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); sensor.start(); @@ -291,34 +359,37 @@ assert_reading_not_null(sensor); sensor.stop(); - }, `${sensorType.name}: sensor reading is correct when options.referenceFrame is 'screen'`); + }, `${sensorName}: sensor reading is correct when options.referenceFrame is 'screen'`); test(() => { + assert_true(sensorName in self); const invalidRefFrames = [ "invalid", null, 123, {}, "", - true, - undefined + true ]; invalidRefFrames.map(refFrame => { assert_throws(new TypeError(), () => { new sensorType({referenceFrame: refFrame}) }, `when refFrame is ${refFrame}`); }); - }, `${sensorType.name}: throw 'TypeError' if referenceFrame is not one of enumeration values`); + }, `${sensorName}: throw 'TypeError' if referenceFrame is not one of enumeration values`); } -function runGenericSensorInsecureContext(sensorType) { +function runGenericSensorInsecureContext(sensorName) { test(() => { - assert_false(sensorType in window, `${sensorType} must not be exposed`); - }, `${sensorType} is not exposed in an insecure context`); + assert_false(sensorName in window, `${sensorName} must not be exposed`); + }, `${sensorName} is not exposed in an insecure context`); } -function runGenericSensorOnerror(sensorType) { +function runGenericSensorOnerror(sensorName) { + const sensorType = self[sensorName]; + promise_test(async t => { + assert_true(sensorName in self); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ["error", "activate"]); sensor.start(); @@ -327,5 +398,5 @@ assert_false(sensor.activated); assert_true(event.error.name == 'NotReadableError' || event.error.name == 'NotAllowedError'); - }, `${sensorType.name}: 'onerror' event is fired when sensor is not supported`); + }, `${sensorName}: 'onerror' event is fired when sensor is not supported`); }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-disabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-disabled-by-feature-policy.https.html index de4aee2d..02cc44e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-disabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-disabled-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_disabled(Gyroscope); +run_fp_tests_disabled('Gyroscope'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html index 3c831bb7..e1aa0f94 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute_redirect_on_load(Gyroscope); +run_fp_tests_enabled_by_attribute_redirect_on_load('Gyroscope'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html index 46473c3a..17e5b27 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute(Gyroscope); +run_fp_tests_enabled_by_attribute('Gyroscope'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy.https.html index 95eee33..9bcced92 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled(Gyroscope); +run_fp_tests_enabled('Gyroscope'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html index ae5a63d1..76d1c5e7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_on_self_origin(Gyroscope); +run_fp_tests_enabled_on_self_origin('Gyroscope'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt index 0121138..c673fd7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt
@@ -1,19 +1,17 @@ This is a testharness.js-based test. -FAIL Gyroscope: Test that 'onreading' is called and sensor reading is valid assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: sensor reading is correct assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: sensor timestamp is updated when time passes assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: Test that sensor can be successfully created and its states are correct. assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Gyroscope: sensor.start() returns undefined assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Gyroscope: no exception is thrown when calling start() on already started sensor assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Gyroscope: sensor.stop() returns undefined assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Gyroscope: no exception is thrown when calling stop() on already stopped sensor assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Gyroscope: Test that fresh reading is fetched on start() assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: sensor readings can not be fired on the background tab assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: frequency hint works promise_test: Unhandled rejection with value: object "[object SensorErrorEvent]" -FAIL Gyroscope: sensor receives suspend / resume notifications when cross-origin subframe is focused assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: throw 'NotSupportedError' for an unsupported sensor option assert_throws: function "() => { new sensorType({invalid: 1}) }" did not throw +PASS Gyroscope: Test that 'onreading' is called and sensor reading is valid +PASS Gyroscope: sensor reading is correct +PASS Gyroscope: sensor timestamp is updated when time passes +PASS Gyroscope: Test that sensor can be successfully created and its states are correct. +PASS Gyroscope: sensor.start() returns undefined +PASS Gyroscope: no exception is thrown when calling start() on already started sensor +PASS Gyroscope: sensor.stop() returns undefined +PASS Gyroscope: no exception is thrown when calling stop() on already stopped sensor +PASS Gyroscope: Test that fresh reading is fetched on start() +PASS Gyroscope: frequency hint works +PASS Gyroscope: sensor receives suspend / resume notifications when cross-origin subframe is focused FAIL Gyroscope: throw 'TypeError' if frequency is invalid assert_throws: when freq is undefined function "() => { new sensorType({frequency: freq}) }" did not throw -FAIL Gyroscope: sensor reading is correct when options.referenceFrame is 'screen' assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Gyroscope: throw 'TypeError' if referenceFrame is not one of enumeration values assert_throws: when refFrame is undefined function "() => { new sensorType({referenceFrame: refFrame}) }" did not throw +PASS Gyroscope: sensor reading is correct when options.referenceFrame is 'screen' +PASS Gyroscope: throw 'TypeError' if referenceFrame is not one of enumeration values Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https.html index 81cdfdd..0c3f08f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https.html
@@ -9,6 +9,6 @@ <div id="log"></div> <script> -runGenericSensorTests(Gyroscope); +runGenericSensorTests('Gyroscope'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope_onerror-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope_onerror-manual.https.html index f012615..b63448b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope_onerror-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope_onerror-manual.https.html
@@ -15,6 +15,6 @@ </ol> <script> -runGenericSensorOnerror(Gyroscope); +runGenericSensorOnerror('Gyroscope'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/origin-of-data-document.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/origin-of-data-document.html index 345a3a6..d6b6d53 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/origin-of-data-document.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/origin-of-data-document.html
@@ -20,16 +20,7 @@ assert_throws("SecurityError", function () { var couldAccessCrossOriginProperty = e.source.location.href; }, "The 'data:' frame should be cross-origin: 'window.location.href'"); - - // Try to access contentDocument of the 'data: ' frame. Some browsers - // (i.e. Firefox, Safari) will return |null| and some (i.e. Chrome) - // will throw an exception. - var dataFrameContentDocument = null; - try { - dataFrameContentDocument = i.contentDocument; - } catch (ex) { - } - assert_equals(dataFrameContentDocument, null, "The 'data:' iframe should be unable to access its contentDocument."); + assert_equals(i.contentDocument, null, "The 'data:' iframe should be unable to access its contentDocument."); })); document.body.appendChild(i);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist index e7e1af8..ce825bfa 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist +++ b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
@@ -10,18 +10,13 @@ INDENT TABS: .gitmodules INDENT TABS: conformance-checkers/* INDENT TABS: content-security-policy/* -INDENT TABS: custom-elements/* -INDENT TABS: old-tests/* INDENT TABS: pointerlock/* INDENT TABS: shadow-dom/* -INDENT TABS: tools/* -INDENT TABS: web-animations/* INDENT TABS: webaudio/* INDENT TABS: webvtt/* INDENT TABS: encoding/legacy*/* TRAILING WHITESPACE: 2dcontext/tools/current-work-canvas.xhtml -TRAILING WHITESPACE: battery-status/* TRAILING WHITESPACE: conformance-checkers/* TRAILING WHITESPACE: content-security-policy/* TRAILING WHITESPACE: custom-elements/* @@ -29,11 +24,9 @@ TRAILING WHITESPACE: old-tests/* TRAILING WHITESPACE: pointerevents/* TRAILING WHITESPACE: shadow-dom/* -TRAILING WHITESPACE: tools/* TRAILING WHITESPACE: webaudio/* TRAILING WHITESPACE: WebIDL/* TRAILING WHITESPACE: webvtt/* -TRAILING WHITESPACE: encoding/legacy*/* TRAILING WHITESPACE: server-timing/resources/parsing/*.sub.headers ## File types that should never be checked ## @@ -77,9 +70,6 @@ ## Helper scripts ## -W3C-TEST.ORG: tools/* -PRINT STATEMENT: tools/* -W3C-TEST.ORG: */tools/* PRINT STATEMENT: */tools/* ## Deliberate copies of Ahem ## @@ -101,7 +91,6 @@ CR AT EOL: html/form-elements/the-textarea-element/multiline-placeholder-crlf.html CR AT EOL: html/input/the-placeholder-attribute/multiline-cr.html CR AT EOL: html/input/the-placeholder-attribute/multiline-crlf.html -CR AT EOL: html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html CR AT EOL: webvtt/parsing/file-parsing/tests/support/newlines.vtt # Intentional use of tabs @@ -139,7 +128,6 @@ # setTimeout usage (should probably mostly be fixed) SET TIMEOUT: *-manual.* -SET TIMEOUT: 2dcontext/* SET TIMEOUT: annotation-model/scripts/ajv.min.js SET TIMEOUT: apng/animated-png-timeout.html SET TIMEOUT: cookies/resources/testharness-helpers.js @@ -181,18 +169,13 @@ SET TIMEOUT: navigation-timing/* SET TIMEOUT: offscreen-canvas/the-offscreen-canvas/* SET TIMEOUT: old-tests/submission/Microsoft/history/history_000.htm -SET TIMEOUT: page-visibility/resources/pagevistestharness.js SET TIMEOUT: paint-timing/resources/subframe-painting.html SET TIMEOUT: payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html -SET TIMEOUT: payment-request/payment-request-response-id.html -SET TIMEOUT: pointerevents/pointerevent_support.js SET TIMEOUT: preload/single-download-preload.html SET TIMEOUT: resize-observer/resources/iframe.html SET TIMEOUT: resource-timing/resource-timing.js SET TIMEOUT: resource-timing/single-entry-per-resource.html -SET TIMEOUT: screen-orientation/lock-bad-argument.html SET TIMEOUT: screen-orientation/onchange-event.html -SET TIMEOUT: screen-orientation/resources/sandboxed-iframe-locking.html SET TIMEOUT: secure-contexts/basic-popup-and-iframe-tests.https.js SET TIMEOUT: service-workers/cache-storage/script-tests/cache-abort.js SET TIMEOUT: service-workers/service-worker/activation.https.html @@ -208,12 +191,10 @@ SET TIMEOUT: service-workers/service-worker/resources/opaque-response-preloaded-xhr.html SET TIMEOUT: service-workers/service-worker/resources/performance-timeline-worker.js SET TIMEOUT: service-workers/service-worker/resources/resource-timing-worker.js -SET TIMEOUT: service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js SET TIMEOUT: shadow-dom/Document-prototype-currentScript.html SET TIMEOUT: shadow-dom/scroll-to-the-fragment-in-shadow-tree.html SET TIMEOUT: shadow-dom/slotchange-event.html SET TIMEOUT: shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html -SET TIMEOUT: shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html SET TIMEOUT: streams/piping/close-propagation-forward.js SET TIMEOUT: streams/piping/error-propagation-backward.js SET TIMEOUT: streams/piping/error-propagation-forward.js @@ -222,12 +203,10 @@ SET TIMEOUT: streams/resources/rs-utils.js SET TIMEOUT: streams/writable-streams/byte-length-queuing-strategy.js SET TIMEOUT: user-timing/* -SET TIMEOUT: webaudio/js/lodash.js SET TIMEOUT: webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html SET TIMEOUT: webauthn/*timeout.https.html SET TIMEOUT: webdriver/* SET TIMEOUT: webmessaging/* -SET TIMEOUT: websockets/* SET TIMEOUT: webstorage/eventTestHarness.js SET TIMEOUT: webvtt/* SET TIMEOUT: workers/* @@ -250,17 +229,13 @@ GENERATE_TESTS: css/css-tables/height-distribution/computing-row-measure-0.html GENERATE_TESTS: css/css-tables/height-distribution/computing-row-measure-1.html GENERATE_TESTS: css/css-tables/height-distribution/percentage-sizing-of-table-cell-children.html -GENERATE_TESTS: css/css-tables/height-distribution/percentage-sizing-of-table-cell-children.html GENERATE_TESTS: css/css-tables/html-to-css-mapping-1.html GENERATE_TESTS: css/css-tables/html-to-css-mapping-2.html GENERATE_TESTS: css/css-tables/html5-table-formatting-1.html -GENERATE_TESTS: css/css-tables/html5-table-formatting-1.html GENERATE_TESTS: css/css-tables/html5-table-formatting-2.html GENERATE_TESTS: css/css-tables/html5-table-formatting-3.html GENERATE_TESTS: css/css-tables/html5-table-formatting-fixed-layout-1.html GENERATE_TESTS: css/css-tables/table-model-fixup-2.html -GENERATE_TESTS: css/css-tables/table-model-fixup-2.html -GENERATE_TESTS: css/css-tables/table-model-fixup-2.html GENERATE_TESTS: css/css-tables/table-model-fixup.html GENERATE_TESTS: css/css-tables/visibility-collapse-col-001.html GENERATE_TESTS: css/css-tables/visibility-collapse-row-001.html @@ -323,12 +298,8 @@ SET TIMEOUT: acid/acid3/test.html # Travis -W3C-TEST.ORG: .travis.yml WEB-PLATFORM.TEST: .travis.yml -# Config -WEB-PLATFORM.TEST: config.default.json -WEB-PLATFORM.TEST: resources/test/config.test.json # Third party code *: css/tools/apiclient/* @@ -339,29 +310,22 @@ # Build system virtualenv *: css/tools/_virtualenv/* - ## Third party data files TRAILING WHITESPACE: css/css-writing-modes/tools/generators/ucd/Blocks.txt TRAILING WHITESPACE: resources/chromium/* - ## Test generation files CONSOLE: css/css-writing-modes/tools/generators/unicode-data.js - ## Test plans and implementation reports -*: css/*/reports/* *: css/*/test-plan/* - ## Things we don't have enabled yet OPEN-NO-MODE: css/* -PARSE-FAILED: css/* PRINT STATEMENT: css/* CONTENT-VISUAL: css/* CONTENT-MANUAL: css/* - ## Support files not in /support/ or similar SUPPORT-WRONG-DIR: css/requirements.txt SUPPORT-WRONG-DIR: css/README.md @@ -374,10 +338,8 @@ SUPPORT-WRONG-DIR: css/*-README SUPPORT-WRONG-DIR: css/*/LICENSE SUPPORT-WRONG-DIR: css/*/LICENSE-* -SUPPORT-WRONG-DIR: css/*/COPYING SUPPORT-WRONG-DIR: css/*/Makefile SUPPORT-WRONG-DIR: css/*/OWNERS -SUPPORT-WRONG-DIR: fonts/* # The selectors-3 testsuite has a weird build system SUPPORT-WRONG-DIR: css/selectors/* @@ -420,8 +382,6 @@ INDENT TABS: css/css-lists/* INDENT TABS: css/css-masking/* INDENT TABS: css/css-multicol/* -INDENT TABS: css/cssom/* -INDENT TABS: css/cssom-view/* INDENT TABS: css/css-page/* INDENT TABS: css/css-pseudo/* INDENT TABS: css/css-regions/* @@ -437,7 +397,6 @@ INDENT TABS: css/css-variables/* INDENT TABS: css/css-writing-modes/* INDENT TABS: css/filter-effects/* -INDENT TABS: fonts/* INDENT TABS: css/mediaqueries/* INDENT TABS: css/selectors/* INDENT TABS: css/vendor-imports/* @@ -474,10 +433,7 @@ TRAILING WHITESPACE: css/css-scoping/css-scoping-shadow-with-outside-rules.html TRAILING WHITESPACE: css/css-scoping/css-scoping-shadow-with-rules.html TRAILING WHITESPACE: css/css-scoping/css-scoping-shadow-with-rules-no-style-leak.html -TRAILING WHITESPACE: css/css-transforms/css3-transform-rotateY.html TRAILING WHITESPACE: css/css-variables/reference/vars-font-shorthand-001-ref.html -TRAILING WHITESPACE: css/css-variables/vars-font-shorthand-001.html -TRAILING WHITESPACE: css/geometry/DOMMatrix-001.html TRAILING WHITESPACE: css/vendor-imports/mozilla/mozilla-central-reftests/css21/pagination/moz-css21-float-page-break-inside-avoid-7.html TRAILING WHITESPACE: css/vendor-imports/mozilla/mozilla-central-reftests/css21/pagination/moz-css21-float-page-break-inside-avoid-7-ref.html TRAILING WHITESPACE: css/vendor-imports/mozilla/mozilla-central-reftests/css21/pagination/moz-css21-float-page-break-inside-avoid-8.html @@ -549,24 +505,10 @@ SET TIMEOUT: css/CSS2/selectors/dom-hover-001.xht SET TIMEOUT: css/CSS2/selectors/dom-hover-002.xht SET TIMEOUT: css/CSS2/tables/tables-102.xht -SET TIMEOUT: css/cssom-view/matchMediaAddListener.html SET TIMEOUT: css/mediaqueries/min-width-tables-001.html -SET TIMEOUT: css/selectors/focus-within-shadow-001.html -SET TIMEOUT: css/selectors/focus-within-shadow-002.html -SET TIMEOUT: css/selectors/focus-within-shadow-003.html -SET TIMEOUT: css/selectors/focus-within-shadow-004.html -SET TIMEOUT: css/selectors/focus-within-shadow-005.html ## Build system stuff -CSS-COLLIDING-TEST-NAME: css/*/OWNERS -CSS-COLLIDING-TEST-NAME: css/*/README -CSS-COLLIDING-TEST-NAME: css/*/README.md -CSS-COLLIDING-TEST-NAME: css/*/LICENSE -CSS-COLLIDING-TEST-NAME: css/*/Makefile -CSS-COLLIDING-TEST-NAME: css/*/reftest.list -CSS-COLLIDING-TEST-NAME: css/*/.htaccess CSS-COLLIDING-SUPPORT-NAME: css/*/README -CSS-COLLIDING-SUPPORT-NAME: css/*/.htaccess CSS-COLLIDING-SUPPORT-NAME: css/*/LOCK # These are all the current "merge mismatch" errors the build system produces @@ -664,95 +606,6 @@ CSS-COLLIDING-SUPPORT-NAME: css/CSS2/tables/support/pattern-grg-rgr-grg.png CSS-COLLIDING-SUPPORT-NAME: css/CSS2/values/support/pattern-grg-rgr-grg.png -# These are thrown off by their support/support/ copies -# https:css///github.com/w3c/csswg-test/issues/1235 -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/bidi-text/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/tables/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/lists/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/filter-effects/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/cssom-view/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-values/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-style-attr/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/text/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-multicol/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/values/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/box-display/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/generated-content/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/support/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-fonts/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/pagination/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-flexbox/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/fonts/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/selectors/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/ui/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/zindex/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/csswg-issues/submitted/css2.1/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/backgrounds/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/i18n/syndata/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-text/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-backgrounds/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-transforms/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/syntax/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-images/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-transitions/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/cascade/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/floats-clear/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/css1/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-shapes/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/colors/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/positioning/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-regions/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/borders/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/cssom/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-page/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/generate/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/normal-flow/support/swatch-red.png -CSS-COLLIDING-SUPPORT-NAME: css/css-flexbox/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/generated-content/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/backgrounds/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/text/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-values/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/csswg-issues/submitted/css2.1/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/borders/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/filter-effects/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/support/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/cssom/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-writing-modes/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/positioning/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-fonts/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-images/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/box-display/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/colors/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/generate/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-transforms/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/normal-flow/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-text/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-page/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/bidi-text/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-style-attr/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/zindex/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-transitions/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/fonts/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/i18n/syndata/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/selectors/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/syntax/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/css1/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-shapes/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/lists/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/ui/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/margin-padding-clear/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-backgrounds/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/tables/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/cascade/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-multicol/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/values/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/css-regions/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/floats-clear/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/cssom-view/support/swatch-green.png -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/pagination/support/swatch-green.png - # Duplicate filename not picked up by the build system # https:css///github.com/w3c/csswg-test/issues/1236 CSS-COLLIDING-REF-NAME: css/css-masking/clip-path-svg-content/reference/clip-path-square-001-ref.svg @@ -794,7 +647,6 @@ CSS-COLLIDING-SUPPORT-NAME: css/CSS2/ui/support/animated.gif CSS-COLLIDING-SUPPORT-NAME: css/CSS2/backgrounds/support/animated.gif CSS-COLLIDING-SUPPORT-NAME: css/css-shapes/shape-outside/shape-image/support/animated.gif -CSS-COLLIDING-SUPPORT-NAME: css/CSS2/css1/support/pattern-gg-gr.png CSS-COLLIDING-SUPPORT-NAME: css/css-display/support/util.js CSS-COLLIDING-SUPPORT-NAME: css/CSS2/normal-flow/support/replaced-min-max-1.png CSS-COLLIDING-SUPPORT-NAME: css/vendor-imports/mozilla/mozilla-central-reftests/ui3/support/replaced-min-max-1.png @@ -885,7 +737,6 @@ SUPPORT-WRONG-DIR: css/css-timing/testcommon.js MISSING-LINK: css/css-typed-om/CSSMatrixComponent-DOMMatrix-mutable.html MISSING-LINK: css/css-typed-om/declared-styleMap-accepts-inherit.html -MISSING-LINK: css/css-typed-om/styleMap-update-function.html SUPPORT-WRONG-DIR: css/cssom/stylesheet-same-origin.css MISSING-LINK: css/cssom-view/DOMRectList.html MISSING-LINK: css/cssom-view/elementFromPoint-002.html @@ -913,20 +764,14 @@ MISSING-LINK: css/cssom-view/scrollIntoView-shadow.html MISSING-LINK: css/cssom-view/scrollIntoView-smooth.html MISSING-LINK: css/cssom-view/scrollTop-display-change.html -CSS-COLLIDING-TEST-NAME: css/cssom-view/interfaces.html -CSS-COLLIDING-TEST-NAME: css/cssom/interfaces.html # TODO https://github.com/w3c/web-platform-tests/issues/5770 MISSING-LINK: css/geometry/*.worker.js MISSING-LINK: css/filter-effects/*.any.js -WEBIDL2.JS: .gitmodules - -# Manual test that uses console.logs for feedback -CONSOLE: payment-request/payment-request-response-id.html - # Tests that use WebKit/Blink testing APIs LAYOUTTESTS APIS: css/css-regions/interactivity/* +LAYOUTTESTS APIS: resources/chromium/generic_sensor_mocks.js # Existing use of WEB-PLATFORM.TEST WEB-PLATFORM.TEST: clear-site-data/support/test_utils.sub.js @@ -939,12 +784,7 @@ WEB-PLATFORM.TEST: html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter.html WEB-PLATFORM.TEST: html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html WEB-PLATFORM.TEST: html/semantics/forms/the-label-element/label-attributes.html -WEB-PLATFORM.TEST: longtask-timing/longtask-in-childiframe-crossorigin.html -WEB-PLATFORM.TEST: longtask-timing/longtask-in-sibling-iframe-crossorigin.html WEB-PLATFORM.TEST: navigation-timing/nav2_test_attributes_values.html WEB-PLATFORM.TEST: navigation-timing/nav2_test_instance_accessors.html -WEB-PLATFORM.TEST: service-workers/service-worker/update-bytecheck.https.html -WEB-PLATFORM.TEST: webdriver/tests/cookies/add_cookie.py -WEB-PLATFORM.TEST: webdriver/tests/cookies/get_named_cookie.py WEB-PLATFORM.TEST: webrtc/RTCPeerConnection-getIdentityAssertion.html WEB-PLATFORM.TEST: webrtc/identity-helper.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt index 62553057..8b1bae9e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt
@@ -1,7 +1,9 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined PASS Magnetometer: Feature-Policy header magnetometer 'none' disallows the top-level document. PASS Magnetometer: Feature-Policy header magnetometer 'none' disallows same-origin iframes. PASS Magnetometer: Feature-Policy header magnetometer 'none' disallows cross-origin iframes. +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer 'none' disallows the top-level document. assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer 'none' disallows same-origin iframes. assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer 'none' disallows cross-origin iframes. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https.html index 56a1cc4..6e496c1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-disabled-by-feature-policy.https.html
@@ -8,7 +8,7 @@ <script> "use strict"; -run_fp_tests_disabled(Magnetometer); -run_fp_tests_disabled(UncalibratedMagnetometer); +run_fp_tests_disabled('Magnetometer'); +run_fp_tests_disabled('UncalibratedMagnetometer'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt index e948ee0..737d71a4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https-expected.txt
@@ -1,6 +1,7 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined PASS Magnetometer: Feature-Policy allow='magnetometer' attribute allows same-origin relocation PASS Magnetometer: Feature-Policy allow='magnetometer' attribute disallows cross-origin relocation +FAIL UncalibratedMagnetometer: Feature-Policy allow='magnetometer' attribute allows same-origin relocation assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy allow='magnetometer' attribute disallows cross-origin relocation assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html index b5f6798..4b65317 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -8,7 +8,7 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute_redirect_on_load(Magnetometer); -run_fp_tests_enabled_by_attribute_redirect_on_load(UncalibratedMagnetometer); +run_fp_tests_enabled_by_attribute_redirect_on_load('Magnetometer'); +run_fp_tests_enabled_by_attribute_redirect_on_load('UncalibratedMagnetometer'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https-expected.txt index 8bf806c..411fc9c0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https-expected.txt
@@ -1,6 +1,7 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined PASS Magnetometer: Feature-Policy allow='magnetometer' attribute allows same-origin iframe PASS Magnetometer: Feature-Policy allow='magnetometer' attribute allows cross-origin iframe +FAIL UncalibratedMagnetometer: Feature-Policy allow='magnetometer' attribute allows same-origin iframe assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy allow='magnetometer' attribute allows cross-origin iframe assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html index 6cad267..4c120f6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html
@@ -8,7 +8,7 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute(Magnetometer); -run_fp_tests_enabled_by_attribute(UncalibratedMagnetometer); +run_fp_tests_enabled_by_attribute('Magnetometer'); +run_fp_tests_enabled_by_attribute('UncalibratedMagnetometer'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https-expected.txt index 5613fb0..ab2f29b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https-expected.txt
@@ -1,7 +1,9 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined PASS Magnetometer: Feature-Policy header magnetometer * allows the top-level document. PASS Magnetometer: Feature-Policy header magnetometer * allows same-origin iframes. PASS Magnetometer: Feature-Policy header magnetometer * allows cross-origin iframes. +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer * allows the top-level document. assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer * allows same-origin iframes. assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer * allows cross-origin iframes. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https.html index 24e2554b..ae59834 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-by-feature-policy.https.html
@@ -8,7 +8,7 @@ <script> "use strict"; -run_fp_tests_enabled(Magnetometer); -run_fp_tests_enabled(UncalibratedMagnetometer); +run_fp_tests_enabled('Magnetometer'); +run_fp_tests_enabled('UncalibratedMagnetometer'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https-expected.txt index 67c6a69..c8818b0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https-expected.txt
@@ -1,7 +1,9 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined PASS Magnetometer: Feature-Policy header magnetometer 'self' allows the top-level document. PASS Magnetometer: Feature-Policy header magnetometer 'self' allows same-origin iframes. PASS Magnetometer: Feature-Policy header magnetometer 'self' disallows cross-origin iframes. +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer 'self' allows the top-level document. assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer 'self' allows same-origin iframes. assert_true: expected true got false +FAIL UncalibratedMagnetometer: Feature-Policy header magnetometer 'self' disallows cross-origin iframes. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html index 59dfef5..e621040 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html
@@ -8,7 +8,7 @@ <script> "use strict"; -run_fp_tests_enabled_on_self_origin(Magnetometer); -run_fp_tests_enabled_on_self_origin(UncalibratedMagnetometer); +run_fp_tests_enabled_on_self_origin('Magnetometer'); +run_fp_tests_enabled_on_self_origin('UncalibratedMagnetometer'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt index 7b01f3d9b..e0cd043 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt
@@ -1,20 +1,31 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined -FAIL Magnetometer: Test that 'onreading' is called and sensor reading is valid assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: sensor reading is correct assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: sensor timestamp is updated when time passes assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: Test that sensor can be successfully created and its states are correct. assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Magnetometer: sensor.start() returns undefined assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Magnetometer: no exception is thrown when calling start() on already started sensor assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Magnetometer: sensor.stop() returns undefined assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Magnetometer: no exception is thrown when calling stop() on already stopped sensor assert_equals: Expected activate event, but got error event instead expected "activate" but got "error" -FAIL Magnetometer: Test that fresh reading is fetched on start() assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: sensor readings can not be fired on the background tab assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: frequency hint works promise_test: Unhandled rejection with value: object "[object SensorErrorEvent]" -FAIL Magnetometer: sensor receives suspend / resume notifications when cross-origin subframe is focused assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: throw 'NotSupportedError' for an unsupported sensor option assert_throws: function "() => { new sensorType({invalid: 1}) }" did not throw +PASS Magnetometer: Test that 'onreading' is called and sensor reading is valid +PASS Magnetometer: sensor reading is correct +PASS Magnetometer: sensor timestamp is updated when time passes +PASS Magnetometer: Test that sensor can be successfully created and its states are correct. +PASS Magnetometer: sensor.start() returns undefined +PASS Magnetometer: no exception is thrown when calling start() on already started sensor +PASS Magnetometer: sensor.stop() returns undefined +PASS Magnetometer: no exception is thrown when calling stop() on already stopped sensor +PASS Magnetometer: Test that fresh reading is fetched on start() +PASS Magnetometer: frequency hint works +PASS Magnetometer: sensor receives suspend / resume notifications when cross-origin subframe is focused FAIL Magnetometer: throw 'TypeError' if frequency is invalid assert_throws: when freq is undefined function "() => { new sensorType({frequency: freq}) }" did not throw -FAIL Magnetometer: sensor reading is correct when options.referenceFrame is 'screen' assert_equals: Expected reading event, but got error event instead expected "reading" but got "error" -FAIL Magnetometer: throw 'TypeError' if referenceFrame is not one of enumeration values assert_throws: when refFrame is undefined function "() => { new sensorType({referenceFrame: refFrame}) }" did not throw +PASS Magnetometer: sensor reading is correct when options.referenceFrame is 'screen' +PASS Magnetometer: throw 'TypeError' if referenceFrame is not one of enumeration values +FAIL UncalibratedMagnetometer: Test that 'onreading' is called and sensor reading is valid assert_true: expected true got false +FAIL UncalibratedMagnetometer: sensor reading is correct assert_true: expected true got false +FAIL UncalibratedMagnetometer: sensor timestamp is updated when time passes assert_true: expected true got false +FAIL UncalibratedMagnetometer: Test that sensor can be successfully created and its states are correct. assert_true: expected true got false +FAIL UncalibratedMagnetometer: sensor.start() returns undefined assert_true: expected true got false +FAIL UncalibratedMagnetometer: no exception is thrown when calling start() on already started sensor assert_true: expected true got false +FAIL UncalibratedMagnetometer: sensor.stop() returns undefined assert_true: expected true got false +FAIL UncalibratedMagnetometer: no exception is thrown when calling stop() on already stopped sensor assert_true: expected true got false +FAIL UncalibratedMagnetometer: Test that fresh reading is fetched on start() assert_true: expected true got false +FAIL UncalibratedMagnetometer: frequency hint works assert_true: expected true got false +FAIL UncalibratedMagnetometer: sensor receives suspend / resume notifications when cross-origin subframe is focused assert_true: expected true got false +FAIL UncalibratedMagnetometer: throw 'TypeError' if frequency is invalid assert_true: expected true got false +FAIL UncalibratedMagnetometer: sensor reading is correct when options.referenceFrame is 'screen' assert_true: expected true got false +FAIL UncalibratedMagnetometer: throw 'TypeError' if referenceFrame is not one of enumeration values assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https.html index a3cefc2..661ea68 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https.html
@@ -9,7 +9,7 @@ <div id="log"></div> <script> -runGenericSensorTests(Magnetometer); -runGenericSensorTests(UncalibratedMagnetometer); +runGenericSensorTests('Magnetometer'); +runGenericSensorTests('UncalibratedMagnetometer'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https-expected.txt index 163ea371..912aa34c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: UncalibratedMagnetometer is not defined PASS Magnetometer: 'onerror' event is fired when sensor is not supported +FAIL UncalibratedMagnetometer: 'onerror' event is fired when sensor is not supported assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https.html index 04b9877..dbdcf1d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer_onerror-manual.https.html
@@ -15,7 +15,7 @@ </ol> <script> -runGenericSensorOnerror(Magnetometer); -runGenericSensorOnerror(UncalibratedMagnetometer); +runGenericSensorOnerror('Magnetometer'); +runGenericSensorOnerror('UncalibratedMagnetometer'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html index ccefe2e..7f42571 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_disabled(AbsoluteOrientationSensor); +run_fp_tests_disabled('AbsoluteOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html index 6aed47d..ab34f5b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute_redirect_on_load(AbsoluteOrientationSensor); +run_fp_tests_enabled_by_attribute_redirect_on_load('AbsoluteOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html index 51bbba1..cb23e8b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute(AbsoluteOrientationSensor); +run_fp_tests_enabled_by_attribute('AbsoluteOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html index c0b4cc8e..cc09eea 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled(AbsoluteOrientationSensor); +run_fp_tests_enabled('AbsoluteOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html index 9ce51ab..62e21be 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_on_self_origin(AbsoluteOrientationSensor); +run_fp_tests_enabled_on_self_origin('AbsoluteOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor.https.html new file mode 100644 index 0000000..c476047f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/AbsoluteOrientationSensor.https.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>OrientationSensor Test</title> +<link rel="author" title="Intel" href="http://www.intel.com"> +<link rel="help" href="https://w3c.github.io/orientation-sensor/"> +<link rel="help" href="https://w3c.github.io/sensors/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="/orientation-sensor/orientation-sensor-tests.js"></script> +<div id="log"></div> + +<script> +runOrienationSensorTests('AbsoluteOrientationSensor'); +runGenericSensorTests('AbsoluteOrientationSensor'); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https.html index d70ea304..415a63c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https.html
@@ -16,7 +16,7 @@ </ol> <script> -runGenericSensorOnerror(AbsoluteOrientationSensor); -runGenericSensorOnerror(RelativeOrientationSensor); +runGenericSensorOnerror('AbsoluteOrientationSensor'); +runGenericSensorOnerror('RelativeOrientationSensor'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html index 9296af8..d97d40b6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_disabled(RelativeOrientationSensor); +run_fp_tests_disabled('RelativeOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html index 01b45b0..3a6173a2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute_redirect_on_load(RelativeOrientationSensor); +run_fp_tests_enabled_by_attribute_redirect_on_load('RelativeOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html index 1bf4119..e8d3002 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_by_attribute(RelativeOrientationSensor); +run_fp_tests_enabled_by_attribute('RelativeOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html index 7ea2fb5..d9f38f2d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled(RelativeOrientationSensor); +run_fp_tests_enabled('RelativeOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html index 6d677bf0..d63bf4e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html
@@ -8,6 +8,6 @@ <script> "use strict"; -run_fp_tests_enabled_on_self_origin(RelativeOrientationSensor); +run_fp_tests_enabled_on_self_origin('RelativeOrientationSensor'); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor.https.html new file mode 100644 index 0000000..9521a15 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/RelativeOrientationSensor.https.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>OrientationSensor Test</title> +<link rel="author" title="Intel" href="http://www.intel.com"> +<link rel="help" href="https://w3c.github.io/orientation-sensor/"> +<link rel="help" href="https://w3c.github.io/sensors/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="/orientation-sensor/orientation-sensor-tests.js"></script> +<div id="log"></div> + +<script> +runOrienationSensorTests('RelativeOrientationSensor'); +runGenericSensorTests('RelativeOrientationSensor'); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/orientation-sensor-tests.js similarity index 63% rename from third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https.html rename to third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/orientation-sensor-tests.js index 5e728a6..74e360a0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/orientation-sensor-tests.js
@@ -1,16 +1,3 @@ - <!DOCTYPE html> -<meta charset="utf-8"> -<title>OrientationSensor Test</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="help" href="https://w3c.github.io/orientation-sensor/"> -<link rel="help" href="https://w3c.github.io/sensors/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/generic-sensor/generic-sensor-tests.js"></script> -<div id="log"></div> - -<script> - //IEEE 754: single precision retricts to 7 decimal digits const float_precision = 1e-7; @@ -80,23 +67,17 @@ sensor.stop(); } -promise_test(t => { - return checkQuaternion(t, AbsoluteOrientationSensor); -}, "Test AbsoluteOrientationSensor.quaternion return a four-element FrozenArray."); +function runOrienationSensorTests(sensorName) { + const sensorType = self[sensorName]; -promise_test(t => { - return checkQuaternion(t, RelativeOrientationSensor); -}, "Test RelativeOrientationSensor.quaternion return a four-element FrozenArray."); + sensor_test(async t => { + assert_true(sensorName in self); + return checkQuaternion(t, sensorType); + }, `${sensorName}.quaternion return a four-element FrozenArray.`); -promise_test(t => { - return checkPopulateMatrix(t, AbsoluteOrientationSensor); -}, "Test AbsoluteOrientationSensor.populateMatrix() method works correctly."); + sensor_test(async t => { + assert_true(sensorName in self); + return checkPopulateMatrix(t, sensorType); + }, `${sensorName}.populateMatrix() method works correctly.`); +} -promise_test(t => { - return checkPopulateMatrix(t, RelativeOrientationSensor); -}, "Test RelativeOrientationSensor.populateMatrix() method works correctly."); - -runGenericSensorTests(AbsoluteOrientationSensor); -runGenericSensorTests(RelativeOrientationSensor); - -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-not-exposed.https.worker.js b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-not-exposed.https.worker.js index df20f801..e5576e67 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-not-exposed.https.worker.js +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-not-exposed.https.worker.js
@@ -1,11 +1,7 @@ importScripts("/resources/testharness.js"); -test(function() { +test(() => { assert_true(isSecureContext); assert_false('PaymentRequest' in self); - assert_false('PaymentRequestUpdateEvent' in self); - assert_false('PaymentResponse' in self); - assert_false('PaymentAddress' in self); }, "PaymentRequest constructor must not be exposed in worker global scope"); - done();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/generic_sensor_mocks.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/generic_sensor_mocks.js new file mode 100644 index 0000000..ff3a051 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/generic_sensor_mocks.js
@@ -0,0 +1,226 @@ +'use strict'; + +var GenericSensorTest = (() => { + // Class that mocks Sensor interface defined in + // https://cs.chromium.org/chromium/src/services/device/public/mojom/sensor.mojom + class MockSensor { + constructor(sensorRequest, handle, offset, size, reportingMode) { + this.client_ = null; + this.reportingMode_ = reportingMode; + this.sensorReadingTimerId_ = null; + this.requestedFrequencies_ = []; + let rv = handle.mapBuffer(offset, size); + assert_equals(rv.result, Mojo.RESULT_OK, "Failed to map shared buffer"); + this.buffer_ = new Float64Array(rv.buffer); + this.buffer_.fill(0); + this.binding_ = new mojo.Binding(device.mojom.Sensor, this, + sensorRequest); + this.binding_.setConnectionErrorHandler(() => { + this.reset(); + }); + } + + getDefaultConfiguration() { + return Promise.resolve({frequency: 5}); + } + + addConfiguration(configuration) { + assert_not_equals(configuration, null, "Invalid sensor configuration."); + + this.requestedFrequencies_.push(configuration.frequency); + // Sort using descending order. + this.requestedFrequencies_.sort( + (first, second) => { return second - first }); + + this.startReading(); + + return Promise.resolve({success: true}); + } + + removeConfiguration(configuration) { + let index = this.requestedFrequencies_.indexOf(configuration.frequency); + if (index == -1) + return; + + this.requestedFrequencies_.splice(index, 1); + + if (this.isReading) { + this.stopReading(); + if (this.requestedFrequencies_.length !== 0) + this.startReading(); + } + } + + suspend() { + this.stopReading(); + } + + resume() { + this.startReading(); + } + + reset() { + this.stopReading(); + this.requestedFrequencies_ = []; + this.buffer_.fill(0); + this.binding_.close(); + } + + startReading() { + if (this.isReading) { + console.warn("Sensor reading is already started."); + return; + } + + if (this.requestedFrequencies_.length == 0) { + console.warn("Sensor reading cannot be started as" + + "there are no configurations added."); + return; + } + + const maxFrequencyHz = this.requestedFrequencies_[0]; + const timeoutMs = (1 / maxFrequencyHz) * 1000; + this.sensorReadingTimerId_ = window.setInterval(() => { + // For all tests sensor reading should have monotonically + // increasing timestamp in seconds. + this.buffer_[1] = window.performance.now() * 0.001; + if (this.reportingMode_ === device.mojom.ReportingMode.ON_CHANGE) { + this.client_.sensorReadingChanged(); + } + }, timeoutMs); + } + + stopReading() { + if (this.isReading) { + window.clearInterval(this.sensorReadingTimerId_); + this.sensorReadingTimerId_ = null; + } + } + + get isReading() { + this.sensorReadingTimerId_ !== null; + } + } + + // Class that mocks SensorProvider interface defined in + // https://cs.chromium.org/chromium/src/services/device/public/mojom/sensor_provider.mojom + class MockSensorProvider { + constructor() { + this.readingSizeInBytes_ = + device.mojom.SensorInitParams.kReadBufferSizeForTests; + this.sharedBufferSizeInBytes_ = this.readingSizeInBytes_ * + device.mojom.SensorType.LAST; + let rv = Mojo.createSharedBuffer(this.sharedBufferSizeInBytes_); + assert_equals(rv.result, Mojo.RESULT_OK, "Failed to create buffer"); + this.sharedBufferHandle_ = rv.handle; + this.activeSensor_ = null; + this.isContinuous_ = false; + this.binding_ = new mojo.Binding(device.mojom.SensorProvider, this); + + this.interceptor_ = new MojoInterfaceInterceptor( + device.mojom.SensorProvider.name); + this.interceptor_.oninterfacerequest = e => { + this.binding_.bind(e.handle); + this.binding_.setConnectionErrorHandler(() => { + console.error("Mojo connection error"); + this.reset(); + }); + }; + this.interceptor_.start(); + } + + async getSensor(type) { + const offset = (device.mojom.SensorType.LAST - type) * + this.readingSizeInBytes_; + const reportingMode = device.mojom.ReportingMode.ON_CHANGE; + + let sensorPtr = new device.mojom.SensorPtr(); + if (this.activeSensor_ == null) { + let mockSensor = new MockSensor( + mojo.makeRequest(sensorPtr), this.sharedBufferHandle_, offset, + this.readingSizeInBytes_, reportingMode); + this.activeSensor_ = mockSensor; + this.activeSensor_.client_ = new device.mojom.SensorClientPtr(); + } + + let rv = this.sharedBufferHandle_.duplicateBufferHandle(); + + assert_equals(rv.result, Mojo.RESULT_OK); + let maxAllowedFrequencyHz = 60; + if (type == device.mojom.SensorType.AMBIENT_LIGHT || + type == device.mojom.SensorType.MAGNETOMETER) { + maxAllowedFrequencyHz = 10; + } + + let initParams = new device.mojom.SensorInitParams({ + sensor: sensorPtr, + clientRequest: mojo.makeRequest(this.activeSensor_.client_), + memory: rv.handle, + bufferOffset: offset, + mode: reportingMode, + defaultConfiguration: {frequency: 5}, + minimumFrequency: 1, + maximumFrequency: maxAllowedFrequencyHz + }); + + return {result: device.mojom.SensorCreationResult.SUCCESS, + initParams: initParams}; + } + + async reset() { + if (this.activeSensor_ !== null) { + this.activeSensor_.reset(); + this.activeSensor_ = null; + } + // Wait for an event loop iteration to let + // the pending mojo commands pass. + function schedule(func) { + return new Promise(resolve => { + setTimeout(() => { + func(); + resolve(); + }, 0); + }); + } + await schedule(this.binding_.close.bind(this.binding_)); + await schedule(this.interceptor_.stop.bind(this.interceptor_)); + } + } + + let testInternal = { + initialized: false, + sensorProvider: null + } + + class GenericSensorTestChromium { + constructor() { + Object.freeze(this); // Make it immutable. + } + + initialize() { + if (testInternal.initialized) + throw new Error('Call reset() before initialize().'); + + if (testRunner) { // Grant sensor permissions for Chromium testrunner. + ['accelerometer', 'gyroscope', + 'magnetometer', 'ambient-light-sensor'].forEach((entry) => { + testRunner.setPermission(entry, 'granted', + location.origin, location.origin); + }); + } + + testInternal.sensorProvider = new MockSensorProvider; + testInternal.initialized = true; + } + // Resets state of sensor mocks between test runs. + async reset() { + if (!testInternal.initialized) + throw new Error('Call initialize() before reset().'); + await testInternal.sensorProvider.reset(); + testInternal.sensorProvider = null; + testInternal.initialized = false; + } + } + + return GenericSensorTestChromium; +})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/generic_sensor_mocks.js.headers b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/generic_sensor_mocks.js.headers new file mode 100644 index 0000000..6805c323 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/generic_sensor_mocks.js.headers
@@ -0,0 +1 @@ +Content-Type: text/javascript; charset=utf-8
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/sensor.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/sensor.mojom.js new file mode 100644 index 0000000..9e75aed --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/sensor.mojom.js
@@ -0,0 +1,1072 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +(function() { + var mojomId = 'services/device/public/mojom/sensor.mojom'; + if (mojo.internal.isMojomLoaded(mojomId)) { + console.warn('The following mojom is loaded multiple times: ' + mojomId); + return; + } + mojo.internal.markMojomLoaded(mojomId); + var bindings = mojo; + var associatedBindings = mojo; + var codec = mojo.internal; + var validator = mojo.internal; + + var exports = mojo.internal.exposeNamespace('device.mojom'); + + + var SensorType = {}; + SensorType.FIRST = 1; + SensorType.AMBIENT_LIGHT = SensorType.FIRST; + SensorType.PROXIMITY = SensorType.AMBIENT_LIGHT + 1; + SensorType.ACCELEROMETER = SensorType.PROXIMITY + 1; + SensorType.LINEAR_ACCELERATION = SensorType.ACCELEROMETER + 1; + SensorType.GYROSCOPE = SensorType.LINEAR_ACCELERATION + 1; + SensorType.MAGNETOMETER = SensorType.GYROSCOPE + 1; + SensorType.PRESSURE = SensorType.MAGNETOMETER + 1; + SensorType.ABSOLUTE_ORIENTATION_EULER_ANGLES = SensorType.PRESSURE + 1; + SensorType.ABSOLUTE_ORIENTATION_QUATERNION = SensorType.ABSOLUTE_ORIENTATION_EULER_ANGLES + 1; + SensorType.RELATIVE_ORIENTATION_EULER_ANGLES = SensorType.ABSOLUTE_ORIENTATION_QUATERNION + 1; + SensorType.RELATIVE_ORIENTATION_QUATERNION = SensorType.RELATIVE_ORIENTATION_EULER_ANGLES + 1; + SensorType.LAST = SensorType.RELATIVE_ORIENTATION_QUATERNION; + + SensorType.isKnownEnumValue = function(value) { + switch (value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + return true; + } + return false; + }; + + SensorType.validate = function(enumValue) { + var isExtensible = false; + if (isExtensible || this.isKnownEnumValue(enumValue)) + return validator.validationError.NONE; + + return validator.validationError.UNKNOWN_ENUM_VALUE; + }; + var ReportingMode = {}; + ReportingMode.ON_CHANGE = 0; + ReportingMode.CONTINUOUS = ReportingMode.ON_CHANGE + 1; + + ReportingMode.isKnownEnumValue = function(value) { + switch (value) { + case 0: + case 1: + return true; + } + return false; + }; + + ReportingMode.validate = function(enumValue) { + var isExtensible = false; + if (isExtensible || this.isKnownEnumValue(enumValue)) + return validator.validationError.NONE; + + return validator.validationError.UNKNOWN_ENUM_VALUE; + }; + + function SensorConfiguration(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + SensorConfiguration.prototype.initDefaults_ = function() { + this.frequency = 0; + }; + SensorConfiguration.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + SensorConfiguration.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + return validator.validationError.NONE; + }; + + SensorConfiguration.encodedSize = codec.kStructHeaderSize + 8; + + SensorConfiguration.decode = function(decoder) { + var packed; + var val = new SensorConfiguration(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.frequency = decoder.decodeStruct(codec.Double); + return val; + }; + + SensorConfiguration.encode = function(encoder, val) { + var packed; + encoder.writeUint32(SensorConfiguration.encodedSize); + encoder.writeUint32(0); + encoder.encodeStruct(codec.Double, val.frequency); + }; + function Sensor_GetDefaultConfiguration_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_GetDefaultConfiguration_Params.prototype.initDefaults_ = function() { + }; + Sensor_GetDefaultConfiguration_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_GetDefaultConfiguration_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 8} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + Sensor_GetDefaultConfiguration_Params.encodedSize = codec.kStructHeaderSize + 0; + + Sensor_GetDefaultConfiguration_Params.decode = function(decoder) { + var packed; + var val = new Sensor_GetDefaultConfiguration_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + return val; + }; + + Sensor_GetDefaultConfiguration_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_GetDefaultConfiguration_Params.encodedSize); + encoder.writeUint32(0); + }; + function Sensor_GetDefaultConfiguration_ResponseParams(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_GetDefaultConfiguration_ResponseParams.prototype.initDefaults_ = function() { + this.configuration = null; + }; + Sensor_GetDefaultConfiguration_ResponseParams.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_GetDefaultConfiguration_ResponseParams.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate Sensor_GetDefaultConfiguration_ResponseParams.configuration + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, SensorConfiguration, false); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + Sensor_GetDefaultConfiguration_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; + + Sensor_GetDefaultConfiguration_ResponseParams.decode = function(decoder) { + var packed; + var val = new Sensor_GetDefaultConfiguration_ResponseParams(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.configuration = decoder.decodeStructPointer(SensorConfiguration); + return val; + }; + + Sensor_GetDefaultConfiguration_ResponseParams.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_GetDefaultConfiguration_ResponseParams.encodedSize); + encoder.writeUint32(0); + encoder.encodeStructPointer(SensorConfiguration, val.configuration); + }; + function Sensor_AddConfiguration_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_AddConfiguration_Params.prototype.initDefaults_ = function() { + this.configuration = null; + }; + Sensor_AddConfiguration_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_AddConfiguration_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate Sensor_AddConfiguration_Params.configuration + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, SensorConfiguration, false); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + Sensor_AddConfiguration_Params.encodedSize = codec.kStructHeaderSize + 8; + + Sensor_AddConfiguration_Params.decode = function(decoder) { + var packed; + var val = new Sensor_AddConfiguration_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.configuration = decoder.decodeStructPointer(SensorConfiguration); + return val; + }; + + Sensor_AddConfiguration_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_AddConfiguration_Params.encodedSize); + encoder.writeUint32(0); + encoder.encodeStructPointer(SensorConfiguration, val.configuration); + }; + function Sensor_AddConfiguration_ResponseParams(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_AddConfiguration_ResponseParams.prototype.initDefaults_ = function() { + this.success = false; + }; + Sensor_AddConfiguration_ResponseParams.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_AddConfiguration_ResponseParams.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + return validator.validationError.NONE; + }; + + Sensor_AddConfiguration_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; + + Sensor_AddConfiguration_ResponseParams.decode = function(decoder) { + var packed; + var val = new Sensor_AddConfiguration_ResponseParams(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + packed = decoder.readUint8(); + val.success = (packed >> 0) & 1 ? true : false; + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + return val; + }; + + Sensor_AddConfiguration_ResponseParams.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_AddConfiguration_ResponseParams.encodedSize); + encoder.writeUint32(0); + packed = 0; + packed |= (val.success & 1) << 0 + encoder.writeUint8(packed); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + }; + function Sensor_RemoveConfiguration_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_RemoveConfiguration_Params.prototype.initDefaults_ = function() { + this.configuration = null; + }; + Sensor_RemoveConfiguration_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_RemoveConfiguration_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate Sensor_RemoveConfiguration_Params.configuration + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, SensorConfiguration, false); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + Sensor_RemoveConfiguration_Params.encodedSize = codec.kStructHeaderSize + 8; + + Sensor_RemoveConfiguration_Params.decode = function(decoder) { + var packed; + var val = new Sensor_RemoveConfiguration_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.configuration = decoder.decodeStructPointer(SensorConfiguration); + return val; + }; + + Sensor_RemoveConfiguration_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_RemoveConfiguration_Params.encodedSize); + encoder.writeUint32(0); + encoder.encodeStructPointer(SensorConfiguration, val.configuration); + }; + function Sensor_Suspend_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_Suspend_Params.prototype.initDefaults_ = function() { + }; + Sensor_Suspend_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_Suspend_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 8} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + Sensor_Suspend_Params.encodedSize = codec.kStructHeaderSize + 0; + + Sensor_Suspend_Params.decode = function(decoder) { + var packed; + var val = new Sensor_Suspend_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + return val; + }; + + Sensor_Suspend_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_Suspend_Params.encodedSize); + encoder.writeUint32(0); + }; + function Sensor_Resume_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_Resume_Params.prototype.initDefaults_ = function() { + }; + Sensor_Resume_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_Resume_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 8} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + Sensor_Resume_Params.encodedSize = codec.kStructHeaderSize + 0; + + Sensor_Resume_Params.decode = function(decoder) { + var packed; + var val = new Sensor_Resume_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + return val; + }; + + Sensor_Resume_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_Resume_Params.encodedSize); + encoder.writeUint32(0); + }; + function Sensor_ConfigureReadingChangeNotifications_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + Sensor_ConfigureReadingChangeNotifications_Params.prototype.initDefaults_ = function() { + this.enabled = false; + }; + Sensor_ConfigureReadingChangeNotifications_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + Sensor_ConfigureReadingChangeNotifications_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + return validator.validationError.NONE; + }; + + Sensor_ConfigureReadingChangeNotifications_Params.encodedSize = codec.kStructHeaderSize + 8; + + Sensor_ConfigureReadingChangeNotifications_Params.decode = function(decoder) { + var packed; + var val = new Sensor_ConfigureReadingChangeNotifications_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + packed = decoder.readUint8(); + val.enabled = (packed >> 0) & 1 ? true : false; + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + return val; + }; + + Sensor_ConfigureReadingChangeNotifications_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(Sensor_ConfigureReadingChangeNotifications_Params.encodedSize); + encoder.writeUint32(0); + packed = 0; + packed |= (val.enabled & 1) << 0 + encoder.writeUint8(packed); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + }; + function SensorClient_RaiseError_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + SensorClient_RaiseError_Params.prototype.initDefaults_ = function() { + }; + SensorClient_RaiseError_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + SensorClient_RaiseError_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 8} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + SensorClient_RaiseError_Params.encodedSize = codec.kStructHeaderSize + 0; + + SensorClient_RaiseError_Params.decode = function(decoder) { + var packed; + var val = new SensorClient_RaiseError_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + return val; + }; + + SensorClient_RaiseError_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(SensorClient_RaiseError_Params.encodedSize); + encoder.writeUint32(0); + }; + function SensorClient_SensorReadingChanged_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + SensorClient_SensorReadingChanged_Params.prototype.initDefaults_ = function() { + }; + SensorClient_SensorReadingChanged_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + SensorClient_SensorReadingChanged_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 8} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + SensorClient_SensorReadingChanged_Params.encodedSize = codec.kStructHeaderSize + 0; + + SensorClient_SensorReadingChanged_Params.decode = function(decoder) { + var packed; + var val = new SensorClient_SensorReadingChanged_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + return val; + }; + + SensorClient_SensorReadingChanged_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(SensorClient_SensorReadingChanged_Params.encodedSize); + encoder.writeUint32(0); + }; + var kSensor_GetDefaultConfiguration_Name = 0; + var kSensor_AddConfiguration_Name = 1; + var kSensor_RemoveConfiguration_Name = 2; + var kSensor_Suspend_Name = 3; + var kSensor_Resume_Name = 4; + var kSensor_ConfigureReadingChangeNotifications_Name = 5; + + function SensorPtr(handleOrPtrInfo) { + this.ptr = new bindings.InterfacePtrController(Sensor, + handleOrPtrInfo); + } + + function SensorAssociatedPtr(associatedInterfacePtrInfo) { + this.ptr = new associatedBindings.AssociatedInterfacePtrController( + Sensor, associatedInterfacePtrInfo); + } + + SensorAssociatedPtr.prototype = + Object.create(SensorPtr.prototype); + SensorAssociatedPtr.prototype.constructor = + SensorAssociatedPtr; + + function SensorProxy(receiver) { + this.receiver_ = receiver; + } + SensorPtr.prototype.getDefaultConfiguration = function() { + return SensorProxy.prototype.getDefaultConfiguration + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProxy.prototype.getDefaultConfiguration = function() { + var params = new Sensor_GetDefaultConfiguration_Params(); + return new Promise(function(resolve, reject) { + var builder = new codec.MessageV1Builder( + kSensor_GetDefaultConfiguration_Name, + codec.align(Sensor_GetDefaultConfiguration_Params.encodedSize), + codec.kMessageExpectsResponse, 0); + builder.encodeStruct(Sensor_GetDefaultConfiguration_Params, params); + var message = builder.finish(); + this.receiver_.acceptAndExpectResponse(message).then(function(message) { + var reader = new codec.MessageReader(message); + var responseParams = + reader.decodeStruct(Sensor_GetDefaultConfiguration_ResponseParams); + resolve(responseParams); + }).catch(function(result) { + reject(Error("Connection error: " + result)); + }); + }.bind(this)); + }; + SensorPtr.prototype.addConfiguration = function() { + return SensorProxy.prototype.addConfiguration + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProxy.prototype.addConfiguration = function(configuration) { + var params = new Sensor_AddConfiguration_Params(); + params.configuration = configuration; + return new Promise(function(resolve, reject) { + var builder = new codec.MessageV1Builder( + kSensor_AddConfiguration_Name, + codec.align(Sensor_AddConfiguration_Params.encodedSize), + codec.kMessageExpectsResponse, 0); + builder.encodeStruct(Sensor_AddConfiguration_Params, params); + var message = builder.finish(); + this.receiver_.acceptAndExpectResponse(message).then(function(message) { + var reader = new codec.MessageReader(message); + var responseParams = + reader.decodeStruct(Sensor_AddConfiguration_ResponseParams); + resolve(responseParams); + }).catch(function(result) { + reject(Error("Connection error: " + result)); + }); + }.bind(this)); + }; + SensorPtr.prototype.removeConfiguration = function() { + return SensorProxy.prototype.removeConfiguration + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProxy.prototype.removeConfiguration = function(configuration) { + var params = new Sensor_RemoveConfiguration_Params(); + params.configuration = configuration; + var builder = new codec.MessageV0Builder( + kSensor_RemoveConfiguration_Name, + codec.align(Sensor_RemoveConfiguration_Params.encodedSize)); + builder.encodeStruct(Sensor_RemoveConfiguration_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + SensorPtr.prototype.suspend = function() { + return SensorProxy.prototype.suspend + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProxy.prototype.suspend = function() { + var params = new Sensor_Suspend_Params(); + var builder = new codec.MessageV0Builder( + kSensor_Suspend_Name, + codec.align(Sensor_Suspend_Params.encodedSize)); + builder.encodeStruct(Sensor_Suspend_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + SensorPtr.prototype.resume = function() { + return SensorProxy.prototype.resume + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProxy.prototype.resume = function() { + var params = new Sensor_Resume_Params(); + var builder = new codec.MessageV0Builder( + kSensor_Resume_Name, + codec.align(Sensor_Resume_Params.encodedSize)); + builder.encodeStruct(Sensor_Resume_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + SensorPtr.prototype.configureReadingChangeNotifications = function() { + return SensorProxy.prototype.configureReadingChangeNotifications + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProxy.prototype.configureReadingChangeNotifications = function(enabled) { + var params = new Sensor_ConfigureReadingChangeNotifications_Params(); + params.enabled = enabled; + var builder = new codec.MessageV0Builder( + kSensor_ConfigureReadingChangeNotifications_Name, + codec.align(Sensor_ConfigureReadingChangeNotifications_Params.encodedSize)); + builder.encodeStruct(Sensor_ConfigureReadingChangeNotifications_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + + function SensorStub(delegate) { + this.delegate_ = delegate; + } + SensorStub.prototype.getDefaultConfiguration = function() { + return this.delegate_ && this.delegate_.getDefaultConfiguration && this.delegate_.getDefaultConfiguration(); + } + SensorStub.prototype.addConfiguration = function(configuration) { + return this.delegate_ && this.delegate_.addConfiguration && this.delegate_.addConfiguration(configuration); + } + SensorStub.prototype.removeConfiguration = function(configuration) { + return this.delegate_ && this.delegate_.removeConfiguration && this.delegate_.removeConfiguration(configuration); + } + SensorStub.prototype.suspend = function() { + return this.delegate_ && this.delegate_.suspend && this.delegate_.suspend(); + } + SensorStub.prototype.resume = function() { + return this.delegate_ && this.delegate_.resume && this.delegate_.resume(); + } + SensorStub.prototype.configureReadingChangeNotifications = function(enabled) { + return this.delegate_ && this.delegate_.configureReadingChangeNotifications && this.delegate_.configureReadingChangeNotifications(enabled); + } + + SensorStub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kSensor_RemoveConfiguration_Name: + var params = reader.decodeStruct(Sensor_RemoveConfiguration_Params); + this.removeConfiguration(params.configuration); + return true; + case kSensor_Suspend_Name: + var params = reader.decodeStruct(Sensor_Suspend_Params); + this.suspend(); + return true; + case kSensor_Resume_Name: + var params = reader.decodeStruct(Sensor_Resume_Params); + this.resume(); + return true; + case kSensor_ConfigureReadingChangeNotifications_Name: + var params = reader.decodeStruct(Sensor_ConfigureReadingChangeNotifications_Params); + this.configureReadingChangeNotifications(params.enabled); + return true; + default: + return false; + } + }; + + SensorStub.prototype.acceptWithResponder = + function(message, responder) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kSensor_GetDefaultConfiguration_Name: + var params = reader.decodeStruct(Sensor_GetDefaultConfiguration_Params); + this.getDefaultConfiguration().then(function(response) { + var responseParams = + new Sensor_GetDefaultConfiguration_ResponseParams(); + responseParams.configuration = response.configuration; + var builder = new codec.MessageV1Builder( + kSensor_GetDefaultConfiguration_Name, + codec.align(Sensor_GetDefaultConfiguration_ResponseParams.encodedSize), + codec.kMessageIsResponse, reader.requestID); + builder.encodeStruct(Sensor_GetDefaultConfiguration_ResponseParams, + responseParams); + var message = builder.finish(); + responder.accept(message); + }); + return true; + case kSensor_AddConfiguration_Name: + var params = reader.decodeStruct(Sensor_AddConfiguration_Params); + this.addConfiguration(params.configuration).then(function(response) { + var responseParams = + new Sensor_AddConfiguration_ResponseParams(); + responseParams.success = response.success; + var builder = new codec.MessageV1Builder( + kSensor_AddConfiguration_Name, + codec.align(Sensor_AddConfiguration_ResponseParams.encodedSize), + codec.kMessageIsResponse, reader.requestID); + builder.encodeStruct(Sensor_AddConfiguration_ResponseParams, + responseParams); + var message = builder.finish(); + responder.accept(message); + }); + return true; + default: + return false; + } + }; + + function validateSensorRequest(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kSensor_GetDefaultConfiguration_Name: + if (message.expectsResponse()) + paramsClass = Sensor_GetDefaultConfiguration_Params; + break; + case kSensor_AddConfiguration_Name: + if (message.expectsResponse()) + paramsClass = Sensor_AddConfiguration_Params; + break; + case kSensor_RemoveConfiguration_Name: + if (!message.expectsResponse() && !message.isResponse()) + paramsClass = Sensor_RemoveConfiguration_Params; + break; + case kSensor_Suspend_Name: + if (!message.expectsResponse() && !message.isResponse()) + paramsClass = Sensor_Suspend_Params; + break; + case kSensor_Resume_Name: + if (!message.expectsResponse() && !message.isResponse()) + paramsClass = Sensor_Resume_Params; + break; + case kSensor_ConfigureReadingChangeNotifications_Name: + if (!message.expectsResponse() && !message.isResponse()) + paramsClass = Sensor_ConfigureReadingChangeNotifications_Params; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + function validateSensorResponse(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kSensor_GetDefaultConfiguration_Name: + if (message.isResponse()) + paramsClass = Sensor_GetDefaultConfiguration_ResponseParams; + break; + case kSensor_AddConfiguration_Name: + if (message.isResponse()) + paramsClass = Sensor_AddConfiguration_ResponseParams; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + var Sensor = { + name: 'device::mojom::Sensor', + kVersion: 0, + ptrClass: SensorPtr, + proxyClass: SensorProxy, + stubClass: SensorStub, + validateRequest: validateSensorRequest, + validateResponse: validateSensorResponse, + }; + SensorStub.prototype.validator = validateSensorRequest; + SensorProxy.prototype.validator = validateSensorResponse; + var kSensorClient_RaiseError_Name = 0; + var kSensorClient_SensorReadingChanged_Name = 1; + + function SensorClientPtr(handleOrPtrInfo) { + this.ptr = new bindings.InterfacePtrController(SensorClient, + handleOrPtrInfo); + } + + function SensorClientAssociatedPtr(associatedInterfacePtrInfo) { + this.ptr = new associatedBindings.AssociatedInterfacePtrController( + SensorClient, associatedInterfacePtrInfo); + } + + SensorClientAssociatedPtr.prototype = + Object.create(SensorClientPtr.prototype); + SensorClientAssociatedPtr.prototype.constructor = + SensorClientAssociatedPtr; + + function SensorClientProxy(receiver) { + this.receiver_ = receiver; + } + SensorClientPtr.prototype.raiseError = function() { + return SensorClientProxy.prototype.raiseError + .apply(this.ptr.getProxy(), arguments); + }; + + SensorClientProxy.prototype.raiseError = function() { + var params = new SensorClient_RaiseError_Params(); + var builder = new codec.MessageV0Builder( + kSensorClient_RaiseError_Name, + codec.align(SensorClient_RaiseError_Params.encodedSize)); + builder.encodeStruct(SensorClient_RaiseError_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + SensorClientPtr.prototype.sensorReadingChanged = function() { + return SensorClientProxy.prototype.sensorReadingChanged + .apply(this.ptr.getProxy(), arguments); + }; + + SensorClientProxy.prototype.sensorReadingChanged = function() { + var params = new SensorClient_SensorReadingChanged_Params(); + var builder = new codec.MessageV0Builder( + kSensorClient_SensorReadingChanged_Name, + codec.align(SensorClient_SensorReadingChanged_Params.encodedSize)); + builder.encodeStruct(SensorClient_SensorReadingChanged_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + + function SensorClientStub(delegate) { + this.delegate_ = delegate; + } + SensorClientStub.prototype.raiseError = function() { + return this.delegate_ && this.delegate_.raiseError && this.delegate_.raiseError(); + } + SensorClientStub.prototype.sensorReadingChanged = function() { + return this.delegate_ && this.delegate_.sensorReadingChanged && this.delegate_.sensorReadingChanged(); + } + + SensorClientStub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kSensorClient_RaiseError_Name: + var params = reader.decodeStruct(SensorClient_RaiseError_Params); + this.raiseError(); + return true; + case kSensorClient_SensorReadingChanged_Name: + var params = reader.decodeStruct(SensorClient_SensorReadingChanged_Params); + this.sensorReadingChanged(); + return true; + default: + return false; + } + }; + + SensorClientStub.prototype.acceptWithResponder = + function(message, responder) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + default: + return false; + } + }; + + function validateSensorClientRequest(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kSensorClient_RaiseError_Name: + if (!message.expectsResponse() && !message.isResponse()) + paramsClass = SensorClient_RaiseError_Params; + break; + case kSensorClient_SensorReadingChanged_Name: + if (!message.expectsResponse() && !message.isResponse()) + paramsClass = SensorClient_SensorReadingChanged_Params; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + function validateSensorClientResponse(messageValidator) { + return validator.validationError.NONE; + } + + var SensorClient = { + name: 'device::mojom::SensorClient', + kVersion: 0, + ptrClass: SensorClientPtr, + proxyClass: SensorClientProxy, + stubClass: SensorClientStub, + validateRequest: validateSensorClientRequest, + validateResponse: null, + }; + SensorClientStub.prototype.validator = validateSensorClientRequest; + SensorClientProxy.prototype.validator = null; + exports.SensorType = SensorType; + exports.ReportingMode = ReportingMode; + exports.SensorConfiguration = SensorConfiguration; + exports.Sensor = Sensor; + exports.SensorPtr = SensorPtr; + exports.SensorAssociatedPtr = SensorAssociatedPtr; + exports.SensorClient = SensorClient; + exports.SensorClientPtr = SensorClientPtr; + exports.SensorClientAssociatedPtr = SensorClientAssociatedPtr; +})(); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/sensor_provider.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/sensor_provider.mojom.js new file mode 100644 index 0000000..2fac8b5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/sensor_provider.mojom.js
@@ -0,0 +1,429 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +(function() { + var mojomId = 'services/device/public/mojom/sensor_provider.mojom'; + if (mojo.internal.isMojomLoaded(mojomId)) { + console.warn('The following mojom is loaded multiple times: ' + mojomId); + return; + } + mojo.internal.markMojomLoaded(mojomId); + var bindings = mojo; + var associatedBindings = mojo; + var codec = mojo.internal; + var validator = mojo.internal; + + var exports = mojo.internal.exposeNamespace('device.mojom'); + var sensor$ = + mojo.internal.exposeNamespace('device.mojom'); + if (mojo.config.autoLoadMojomDeps) { + mojo.internal.loadMojomIfNecessary( + 'services/device/public/mojom/sensor.mojom', 'sensor.mojom.js'); + } + + + var SensorCreationResult = {}; + SensorCreationResult.SUCCESS = 0; + SensorCreationResult.ERROR_NOT_AVAILABLE = SensorCreationResult.SUCCESS + 1; + SensorCreationResult.ERROR_NOT_ALLOWED = SensorCreationResult.ERROR_NOT_AVAILABLE + 1; + + SensorCreationResult.isKnownEnumValue = function(value) { + switch (value) { + case 0: + case 1: + case 2: + return true; + } + return false; + }; + + SensorCreationResult.validate = function(enumValue) { + var isExtensible = false; + if (isExtensible || this.isKnownEnumValue(enumValue)) + return validator.validationError.NONE; + + return validator.validationError.UNKNOWN_ENUM_VALUE; + }; + + function SensorInitParams(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + SensorInitParams.kReadBufferSizeForTests = 48; + SensorInitParams.prototype.initDefaults_ = function() { + this.sensor = new sensor$.SensorPtr(); + this.clientRequest = new bindings.InterfaceRequest(); + this.memory = null; + this.bufferOffset = 0; + this.mode = 0; + this.defaultConfiguration = null; + this.maximumFrequency = 0; + this.minimumFrequency = 0; + }; + SensorInitParams.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + SensorInitParams.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 64} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorInitParams.sensor + err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 0, false); + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorInitParams.clientRequest + err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 8, false) + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorInitParams.memory + err = messageValidator.validateHandle(offset + codec.kStructHeaderSize + 12, false) + if (err !== validator.validationError.NONE) + return err; + + + + // validate SensorInitParams.mode + err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 24, sensor$.ReportingMode); + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorInitParams.defaultConfiguration + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 32, sensor$.SensorConfiguration, false); + if (err !== validator.validationError.NONE) + return err; + + + + return validator.validationError.NONE; + }; + + SensorInitParams.encodedSize = codec.kStructHeaderSize + 56; + + SensorInitParams.decode = function(decoder) { + var packed; + var val = new SensorInitParams(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.sensor = decoder.decodeStruct(new codec.Interface(sensor$.SensorPtr)); + val.clientRequest = decoder.decodeStruct(codec.InterfaceRequest); + val.memory = decoder.decodeStruct(codec.Handle); + val.bufferOffset = decoder.decodeStruct(codec.Uint64); + val.mode = decoder.decodeStruct(codec.Int32); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + val.defaultConfiguration = decoder.decodeStructPointer(sensor$.SensorConfiguration); + val.maximumFrequency = decoder.decodeStruct(codec.Double); + val.minimumFrequency = decoder.decodeStruct(codec.Double); + return val; + }; + + SensorInitParams.encode = function(encoder, val) { + var packed; + encoder.writeUint32(SensorInitParams.encodedSize); + encoder.writeUint32(0); + encoder.encodeStruct(new codec.Interface(sensor$.SensorPtr), val.sensor); + encoder.encodeStruct(codec.InterfaceRequest, val.clientRequest); + encoder.encodeStruct(codec.Handle, val.memory); + encoder.encodeStruct(codec.Uint64, val.bufferOffset); + encoder.encodeStruct(codec.Int32, val.mode); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.encodeStructPointer(sensor$.SensorConfiguration, val.defaultConfiguration); + encoder.encodeStruct(codec.Double, val.maximumFrequency); + encoder.encodeStruct(codec.Double, val.minimumFrequency); + }; + function SensorProvider_GetSensor_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + SensorProvider_GetSensor_Params.prototype.initDefaults_ = function() { + this.type = 0; + }; + SensorProvider_GetSensor_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + SensorProvider_GetSensor_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorProvider_GetSensor_Params.type + err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, sensor$.SensorType); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + SensorProvider_GetSensor_Params.encodedSize = codec.kStructHeaderSize + 8; + + SensorProvider_GetSensor_Params.decode = function(decoder) { + var packed; + var val = new SensorProvider_GetSensor_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.type = decoder.decodeStruct(codec.Int32); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + return val; + }; + + SensorProvider_GetSensor_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(SensorProvider_GetSensor_Params.encodedSize); + encoder.writeUint32(0); + encoder.encodeStruct(codec.Int32, val.type); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + }; + function SensorProvider_GetSensor_ResponseParams(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + SensorProvider_GetSensor_ResponseParams.prototype.initDefaults_ = function() { + this.result = 0; + this.initParams = null; + }; + SensorProvider_GetSensor_ResponseParams.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + SensorProvider_GetSensor_ResponseParams.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 24} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorProvider_GetSensor_ResponseParams.result + err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, SensorCreationResult); + if (err !== validator.validationError.NONE) + return err; + + + // validate SensorProvider_GetSensor_ResponseParams.initParams + err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, SensorInitParams, true); + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + SensorProvider_GetSensor_ResponseParams.encodedSize = codec.kStructHeaderSize + 16; + + SensorProvider_GetSensor_ResponseParams.decode = function(decoder) { + var packed; + var val = new SensorProvider_GetSensor_ResponseParams(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.result = decoder.decodeStruct(codec.Int32); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + decoder.skip(1); + val.initParams = decoder.decodeStructPointer(SensorInitParams); + return val; + }; + + SensorProvider_GetSensor_ResponseParams.encode = function(encoder, val) { + var packed; + encoder.writeUint32(SensorProvider_GetSensor_ResponseParams.encodedSize); + encoder.writeUint32(0); + encoder.encodeStruct(codec.Int32, val.result); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.skip(1); + encoder.encodeStructPointer(SensorInitParams, val.initParams); + }; + var kSensorProvider_GetSensor_Name = 0; + + function SensorProviderPtr(handleOrPtrInfo) { + this.ptr = new bindings.InterfacePtrController(SensorProvider, + handleOrPtrInfo); + } + + function SensorProviderAssociatedPtr(associatedInterfacePtrInfo) { + this.ptr = new associatedBindings.AssociatedInterfacePtrController( + SensorProvider, associatedInterfacePtrInfo); + } + + SensorProviderAssociatedPtr.prototype = + Object.create(SensorProviderPtr.prototype); + SensorProviderAssociatedPtr.prototype.constructor = + SensorProviderAssociatedPtr; + + function SensorProviderProxy(receiver) { + this.receiver_ = receiver; + } + SensorProviderPtr.prototype.getSensor = function() { + return SensorProviderProxy.prototype.getSensor + .apply(this.ptr.getProxy(), arguments); + }; + + SensorProviderProxy.prototype.getSensor = function(type) { + var params = new SensorProvider_GetSensor_Params(); + params.type = type; + return new Promise(function(resolve, reject) { + var builder = new codec.MessageV1Builder( + kSensorProvider_GetSensor_Name, + codec.align(SensorProvider_GetSensor_Params.encodedSize), + codec.kMessageExpectsResponse, 0); + builder.encodeStruct(SensorProvider_GetSensor_Params, params); + var message = builder.finish(); + this.receiver_.acceptAndExpectResponse(message).then(function(message) { + var reader = new codec.MessageReader(message); + var responseParams = + reader.decodeStruct(SensorProvider_GetSensor_ResponseParams); + resolve(responseParams); + }).catch(function(result) { + reject(Error("Connection error: " + result)); + }); + }.bind(this)); + }; + + function SensorProviderStub(delegate) { + this.delegate_ = delegate; + } + SensorProviderStub.prototype.getSensor = function(type) { + return this.delegate_ && this.delegate_.getSensor && this.delegate_.getSensor(type); + } + + SensorProviderStub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + default: + return false; + } + }; + + SensorProviderStub.prototype.acceptWithResponder = + function(message, responder) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kSensorProvider_GetSensor_Name: + var params = reader.decodeStruct(SensorProvider_GetSensor_Params); + this.getSensor(params.type).then(function(response) { + var responseParams = + new SensorProvider_GetSensor_ResponseParams(); + responseParams.result = response.result; + responseParams.initParams = response.initParams; + var builder = new codec.MessageV1Builder( + kSensorProvider_GetSensor_Name, + codec.align(SensorProvider_GetSensor_ResponseParams.encodedSize), + codec.kMessageIsResponse, reader.requestID); + builder.encodeStruct(SensorProvider_GetSensor_ResponseParams, + responseParams); + var message = builder.finish(); + responder.accept(message); + }); + return true; + default: + return false; + } + }; + + function validateSensorProviderRequest(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kSensorProvider_GetSensor_Name: + if (message.expectsResponse()) + paramsClass = SensorProvider_GetSensor_Params; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + function validateSensorProviderResponse(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kSensorProvider_GetSensor_Name: + if (message.isResponse()) + paramsClass = SensorProvider_GetSensor_ResponseParams; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + var SensorProvider = { + name: 'device::mojom::SensorProvider', + kVersion: 0, + ptrClass: SensorProviderPtr, + proxyClass: SensorProviderProxy, + stubClass: SensorProviderStub, + validateRequest: validateSensorProviderRequest, + validateResponse: validateSensorProviderResponse, + }; + SensorProviderStub.prototype.validator = validateSensorProviderRequest; + SensorProviderProxy.prototype.validator = validateSensorProviderResponse; + exports.SensorCreationResult = SensorCreationResult; + exports.SensorInitParams = SensorInitParams; + exports.SensorProvider = SensorProvider; + exports.SensorProviderPtr = SensorProviderPtr; + exports.SensorProviderAssociatedPtr = SensorProviderAssociatedPtr; +})(); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/server-timing/service_worker_idl-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/server-timing/service_worker_idl-expected.txt new file mode 100644 index 0000000..c75bc11 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/server-timing/service_worker_idl-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Untitled Only secure origins are allowed (see: https://goo.gl/Y0ZkNV). +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/server-timing/service_worker_idl.html b/third_party/WebKit/LayoutTests/external/wpt/server-timing/service_worker_idl.html new file mode 100644 index 0000000..1c1be899 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/server-timing/service_worker_idl.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<head> + <meta charset='utf-8' /> + <script src="/resources/testharness.js"></script> + <script src='/resources/testharnessreport.js'></script> + <script> + (async () => { + const scope = 'does/not/exist' + + let registration = await navigator.serviceWorker.getRegistration(scope) + if (registration) + await registration.unregister() + registration = await navigator.serviceWorker.register('./sw.js', {scope}) + + fetch_tests_from_worker(registration.installing) + })() + </script> +</head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/server-timing/sw.js b/third_party/WebKit/LayoutTests/external/wpt/server-timing/sw.js new file mode 100644 index 0000000..4d3b620 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/server-timing/sw.js
@@ -0,0 +1,10 @@ +importScripts('/resources/testharness.js') + +promise_test(async (test) => { + return fetch('./sw.js').then(function(response) { + assert_not_equals(typeof performance.getEntriesByName(response.url)[0].serverTiming, + 'undefined', + 'An instance of `PerformanceResourceTiming` should have a `serverTiming` attribute in the Service Worker context.') + done() + }) +})
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-worker.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-worker.js index c83e4851..8b3046722 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-worker.js +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/resource-timing-worker.js
@@ -1,5 +1,9 @@ self.addEventListener('fetch', function(event) { - if (event.request.url.indexOf('dummy.js') != -1) { - event.respondWith(fetch('empty.js')); - } - }); + if (event.request.url.indexOf('dummy.js') != -1) { + event.respondWith(new Promise(resolve => { + // Slightly delay the response so we ensure we get a non-zero + // duration. + setTimeout(_ => resolve(new Response('// Empty javascript')), 50); + })); + } +});
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/setters_tests.json b/third_party/WebKit/LayoutTests/external/wpt/url/setters_tests.json index 714bd5e7..db23d92 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/url/setters_tests.json +++ b/third_party/WebKit/LayoutTests/external/wpt/url/setters_tests.json
@@ -720,6 +720,17 @@ } }, { + "comment": "Port number is removed if new port is scheme default and existing URL has a non-default port", + "href": "http://example.net:8080", + "new_value": "example.com:80", + "expected": { + "href": "http://example.com/", + "host": "example.com", + "hostname": "example.com", + "port": "" + } + }, + { "comment": "Stuff after a / delimiter is ignored", "href": "http://example.net/path", "new_value": "example.com/stuff",
diff --git a/third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-basic.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-basic.html similarity index 85% rename from third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-basic.html rename to third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-basic.html index 4e23760..e176d61 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-basic.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-basic.html
@@ -4,10 +4,10 @@ <title> realtimeanalyser-basic.html </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + <script src="/webaudio/resources/audit.js"></script> </head> <body> <script id="layout-test-code">
diff --git a/third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-fft-scaling.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html similarity index 93% rename from third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-fft-scaling.html rename to third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html index dadf683..6a0ab7d 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-fft-scaling.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html
@@ -4,10 +4,10 @@ <title> realtimeanalyser-fft-scaling.html </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + <script src="/webaudio/resources/audit.js"></script> </head> <body> <div id="description"></div>
diff --git a/third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-fft-sizing.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-sizing.html similarity index 84% rename from third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-fft-sizing.html rename to third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-sizing.html index 0b0bb3bb..b3de37f 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Analyser/realtimeanalyser-fft-sizing.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-sizing.html
@@ -4,10 +4,10 @@ <title> realtimeanalyser-fft-sizing.html </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + <script src="/webaudio/resources/audit.js"></script> </head> <body> <script id="layout-test-code">
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-getoutputtimestamp.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html similarity index 81% rename from third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-getoutputtimestamp.html rename to third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html index 9375cbd..cd09696e 100644 --- a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-getoutputtimestamp.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-getoutputtimestamp.html
@@ -4,9 +4,9 @@ <title> Testing AudioContext.getOutputTimestamp() method </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit.js"></script> </head> <body> <script id="layout-test-code">
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-suspend-resume.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html similarity index 95% rename from third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-suspend-resume.html rename to third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html index ee7d64a..48506d65 100644 --- a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontext-suspend-resume.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-suspend-resume.html
@@ -4,10 +4,10 @@ <title> Test AudioContext.suspend() and AudioContext.resume() </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit-util.js"></script> - <script src="../resources/audit.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + <script src="/webaudio/resources/audit.js"></script> </head> <body> <script id="layout-test-code">
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontextoptions.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html similarity index 96% rename from third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontextoptions.html rename to third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html index e77ed92..295cd5a 100644 --- a/third_party/WebKit/LayoutTests/webaudio/AudioContext/audiocontextoptions.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontextoptions.html
@@ -4,9 +4,9 @@ <title> Test AudioContextOptions </title> - <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit.js"></script> </head> <body> <script id="layout-test-code">
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/sync-no-progress.any.js b/third_party/WebKit/LayoutTests/external/wpt/xhr/sync-no-progress.any.js new file mode 100644 index 0000000..a915e4d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/sync-no-progress.any.js
@@ -0,0 +1,12 @@ +test(t => { + let xhr = new XMLHttpRequest(); + let loadEventFired = false; + xhr.onprogress = t.unreached_func('progress event should not be fired'); + xhr.onload = () => { + loadEventFired = true; + }; + xhr.open('GET', 'resources/trickle.py?count=4&delay=150', false); + xhr.send(); + // Check the load event as a sanity check that the test is working. + assert_true(loadEventFired, 'load event should have fired'); +}, 'progress event should not be fired by sync XHR');
diff --git a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt index bb0dd50..720ce61 100644 --- a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS setParameters() changes getParameters() returned values FAIL setParameters() with large maxBitrate changes getParameters() returned values assert_equals: expected 4294967295 but got 2147483647 -PASS setParameters() with multiple calls +PASS setParameters() with multiple calls after single getParameters() PASS setParameters() fails without getParameters() PASS video setParameters() check for transactionId modification FAIL video setParameters() check for transactionId removed assert_unreached: Should have rejected: undefined Reached unreachable code
diff --git a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters.html b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters.html index 3df999b..9d7ff118 100644 --- a/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters.html +++ b/third_party/WebKit/LayoutTests/fast/peerconnection/RTCRtpSender-setParameters.html
@@ -43,7 +43,7 @@ assert_equals(videoParameters.encodings[0].maxBitrate, 0xFFFFFFFF); }, 'setParameters() with large maxBitrate changes getParameters() returned values'); -promise_test(async () => { +promise_test(async (t) => { let pc1 = new RTCPeerConnection(); let pc2 = new RTCPeerConnection(); @@ -60,14 +60,13 @@ videoParameters.encodings[0].active = true; videoParameters.encodings[0].priority = 'low'; videoParameters.encodings[0].maxBitrate = 1337001; - await videoSender.setParameters(videoParameters); - - videoParameters = videoSender.getParameters(); - assert_equals(videoParameters.encodings[0].active, true); - assert_equals(videoParameters.encodings[0].priority, 'low'); - assert_equals(videoParameters.encodings[0].maxBitrate, 1337001); - -}, 'setParameters() with multiple calls'); + return promise_rejects( + t, + new DOMException( + "getParameters() needs to be called before setParameters().", + "InvalidStateError"), + videoSender.setParameters(videoParameters)); +}, 'setParameters() with multiple calls after single getParameters()'); promise_test(async (t) => { let pc1 = new RTCPeerConnection();
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-001-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-001-expected.txt new file mode 100644 index 0000000..f5d8c0e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-001-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS spaces linebreak +PASS linebreak spaces +PASS spaces linebreak spaces +PASS multiple linebreaks +PASS multiple linebreaks + spaces +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-002-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-002-expected.txt new file mode 100644 index 0000000..f5d8c0e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-002-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS spaces linebreak +PASS linebreak spaces +PASS spaces linebreak spaces +PASS multiple linebreaks +PASS multiple linebreaks + spaces +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-003-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-003-expected.txt new file mode 100644 index 0000000..f5d8c0e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-003-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS spaces linebreak +PASS linebreak spaces +PASS spaces linebreak spaces +PASS multiple linebreaks +PASS multiple linebreaks + spaces +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-004-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-004-expected.txt new file mode 100644 index 0000000..59f2b32f0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-004-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS linebreak only ₩24 +PASS spaces linebreak ₩24 +PASS linebreak spaces ₩24 +PASS spaces linebreak spaces ₩24 +PASS multiple linebreaks ₩24 +PASS multiple linebreaks + spaces ₩24 +PASS linebreak only 24₩ +PASS spaces linebreak 24₩ +PASS linebreak spaces 24₩ +PASS spaces linebreak spaces 24₩ +PASS multiple linebreaks 24₩ +PASS multiple linebreaks + spaces 24₩ +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-008-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-008-expected.txt new file mode 100644 index 0000000..f5d8c0e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-008-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS spaces linebreak +PASS linebreak spaces +PASS spaces linebreak spaces +PASS multiple linebreaks +PASS multiple linebreaks + spaces +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-009-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-009-expected.txt new file mode 100644 index 0000000..f5d8c0e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-009-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS spaces linebreak +PASS linebreak spaces +PASS spaces linebreak spaces +PASS multiple linebreaks +PASS multiple linebreaks + spaces +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-016-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-016-expected.txt new file mode 100644 index 0000000..0a4bad7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-016-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS zwsp retained 1 +PASS spaces linebreak +PASS zwsp retained 2 +PASS linebreak spaces +PASS zwsp retained 3 +PASS spaces linebreak spaces +PASS zwsp retained 4 +PASS multiple linebreaks +PASS zwsp retained 5 +PASS multiple linebreaks + spaces +PASS zwsp retained 6 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-017-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-017-expected.txt new file mode 100644 index 0000000..0a4bad7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/css-text/white-space/seg-break-transformation-017-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS linebreak only +PASS zwsp retained 1 +PASS spaces linebreak +PASS zwsp retained 2 +PASS linebreak spaces +PASS zwsp retained 3 +PASS spaces linebreak spaces +PASS zwsp retained 4 +PASS multiple linebreaks +PASS zwsp retained 5 +PASS multiple linebreaks + spaces +PASS zwsp retained 6 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/cssom-view/elementFromPoint-002-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/cssom-view/elementFromPoint-002-expected.txt new file mode 100644 index 0000000..23dd3f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/cssom-view/elementFromPoint-002-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +PASS Checking whether dynamic changes to visibility interact correctly with + table anonymous boxes +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/cssom-view/elementFromPoint-003-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/cssom-view/elementFromPoint-003-expected.txt new file mode 100644 index 0000000..23dd3f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/css/cssom-view/elementFromPoint-003-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +PASS Checking whether dynamic changes to visibility interact correctly with + table anonymous boxes +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt new file mode 100644 index 0000000..d765b87 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt
@@ -0,0 +1,217 @@ +This is a testharness.js-based test. +Found 213 tests; 138 PASS, 75 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS Simplest possible test ("<div>abc") +PASS Leading whitespace removed ("<div> abc") +PASS Trailing whitespace removed ("<div>abc ") +PASS Internal whitespace compressed ("<div>abc def") +PASS \n converted to space ("<div>abc\ndef") +PASS \r converted to space ("<div>abc\rdef") +PASS \t converted to space ("<div>abc\tdef") +PASS Trailing whitespace before hard line break removed ("<div>abc <br>def") +PASS Leading whitespace preserved ("<pre> abc") +PASS Trailing whitespace preserved ("<pre>abc ") +PASS Internal whitespace preserved ("<pre>abc def") +PASS \n preserved ("<pre>abc\ndef") +PASS \r converted to newline ("<pre>abc\rdef") +PASS \t preserved ("<pre>abc\tdef") +FAIL Two <pre> siblings ("<div><pre>abc</pre><pre>def</pre>") assert_equals: expected "abc\ndef" but got "abc\ndef\n" +PASS Leading whitespace preserved ("<div style='white-space:pre'> abc") +PASS Trailing whitespace preserved ("<div style='white-space:pre'>abc ") +PASS Internal whitespace preserved ("<div style='white-space:pre'>abc def") +PASS \n preserved ("<div style='white-space:pre'>abc\ndef") +PASS \r converted to newline ("<div style='white-space:pre'>abc\rdef") +PASS \t preserved ("<div style='white-space:pre'>abc\tdef") +PASS Leading whitespace preserved ("<span style='white-space:pre'> abc") +PASS Trailing whitespace preserved ("<span style='white-space:pre'>abc ") +PASS Internal whitespace preserved ("<span style='white-space:pre'>abc def") +PASS \n preserved ("<span style='white-space:pre'>abc\ndef") +PASS \r converted to newline ("<span style='white-space:pre'>abc\rdef") +PASS \t preserved ("<span style='white-space:pre'>abc\tdef") +PASS Leading whitespace removed ("<div style='white-space:pre-line'> abc") +PASS Trailing whitespace removed ("<div style='white-space:pre-line'>abc ") +PASS Internal whitespace collapsed ("<div style='white-space:pre-line'>abc def") +PASS \n preserved ("<div style='white-space:pre-line'>abc\ndef") +PASS \r converted to newline ("<div style='white-space:pre-line'>abc\rdef") +PASS \t converted to space ("<div style='white-space:pre-line'>abc\tdef") +PASS Whitespace collapses across element boundaries ("<div><span>abc </span> def") +PASS Whitespace collapses across element boundaries ("<div><span>abc </span><span></span> def") +PASS Whitespace collapses across element boundaries ("<div><span>abc </span><span style='white-space:pre'></span> def") +PASS Soft line breaks ignored ("<div style='width:0'>abc def") +FAIL ::first-line styles applied ("<div class='first-line-uppercase' style='width:0'>abc def") assert_equals: expected "ABC def" but got "abc def" +PASS ::first-letter styles applied ("<div class='first-letter-uppercase' style='width:0'>abc def") +PASS ::first-letter float ignored ("<div class='first-letter-float' style='width:0'>abc def") +PASS preserved ("<div> ") +PASS display:none container ("<div style='display:none'>abc") +PASS No whitespace compression in display:none container ("<div style='display:none'>abc def") +PASS No removal of leading/trailing whitespace in display:none container ("<div style='display:none'> abc def ") +PASS display:none child not rendered ("<div>123<span style='display:none'>abc") +PASS display:none container with non-display-none target child ("<div style='display:none'><span id='target'>abc") +FAIL non-display-none child of svg ("<div id='target'>abc") assert_equals: expected "" but got "abc" +PASS display:none child of svg ("<div style='display:none' id='target'>abc") +PASS child of display:none child of svg ("<div style='display:none'><div id='target'>abc") +PASS display:contents container ("<div style='display:contents'>abc") +PASS display:contents container ("<div><div style='display:contents'>abc") +PASS display:contents rendered ("<div>123<span style='display:contents'>abc") +FAIL display:contents not processed via textContent ("<div style='display:contents'> ") assert_equals: expected "" but got " " +PASS display:contents not processed via textContent ("<div><div style='display:contents'> ") +PASS visibility:hidden container ("<div style='visibility:hidden'>abc") +PASS visibility:hidden child not rendered ("<div>123<span style='visibility:hidden'>abc") +PASS visibility:visible child rendered ("<div style='visibility:hidden'>123<span style='visibility:visible'>abc") +PASS visibility:collapse row-group ("<table><tbody style='visibility:collapse'><tr><td>abc") +PASS visibility:collapse row ("<table><tr style='visibility:collapse'><td>abc") +PASS visibility:collapse cell ("<table><tr><td style='visibility:collapse'>abc") +FAIL visibility:collapse row-group with visible cell ("<table><tbody style='visibility:collapse'><tr><td style='visibility:visible'>abc") assert_equals: expected "abc" but got "abc\n" +FAIL visibility:collapse row with visible cell ("<table><tr style='visibility:collapse'><td style='visibility:visible'>abc") assert_equals: expected "abc" but got "abc\n" +FAIL visibility:collapse honored on flex item ("<div style='display:flex'><span style='visibility:collapse'>1</span><span>2</span></div>") assert_equals: expected "2" but got "2\n" +FAIL visibility:collapse honored on grid item ("<div style='display:grid'><span style='visibility:collapse'>1</span><span>2</span></div>") assert_equals: expected "2" but got "2\n" +PASS opacity:0 container ("<div style='opacity:0'>abc") +PASS Whitespace compression in opacity:0 container ("<div style='opacity:0'>abc def") +PASS Remove leading/trailing whitespace in opacity:0 container ("<div style='opacity:0'> abc def ") +PASS opacity:0 child rendered ("<div>123<span style='opacity:0'>abc") +PASS Generated content not included ("<div class='before'>") +PASS Generated content on child not included ("<div><div class='before'>") +PASS <button> contents preserved ("<button>abc") +PASS <fieldset> contents preserved ("<fieldset>abc") +FAIL <fieldset> <legend> contents preserved ("<fieldset><legend>abc") assert_equals: expected "abc" but got "abc\n" +PASS <input> contents ignored ("<input type='text' value='abc'>") +PASS <textarea> contents ignored ("<textarea>abc") +PASS <iframe> contents ignored ("<iframe>abc") +PASS <iframe> contents ignored ("<iframe><div id='target'>abc") +PASS <iframe> subdocument ignored ("<iframe src='data:text/html,abc'>") +FAIL <audio> contents ignored ("<audio style='display:block'>abc") assert_equals: expected "" but got "abc" +FAIL <audio> contents ignored ("<audio style='display:block'><source id='target' class='poke' style='display:block'>") assert_equals: expected "" but got "abc" +PASS <audio> contents ok if display:none ("<audio style='display:block'><source id='target' class='poke' style='display:none'>") +PASS <video> contents ignored ("<video>abc") +FAIL <video> contents ignored ("<video style='display:block'><source id='target' class='poke' style='display:block'>") assert_equals: expected "" but got "abc" +PASS <video> contents ok if display:none ("<video style='display:block'><source id='target' class='poke' style='display:none'>") +PASS <canvas> contents ignored ("<canvas>abc") +FAIL <canvas><div id='target'> contents ignored ("<canvas><div id='target'>abc") assert_equals: expected "" but got "abc" +PASS <img> alt text ignored ("<img alt='abc'>") +PASS <img> contents ignored ("<img src='about:blank' class='poke'>") +FAIL <select size='1'> contents of options preserved ("<select size='1'><option>abc</option><option>def") assert_equals: expected "abc\ndef" but got "" +FAIL <select size='2'> contents of options preserved ("<select size='2'><option>abc</option><option>def") assert_equals: expected "abc\ndef" but got "" +PASS <select size='1'> contents of target option preserved ("<select size='1'><option id='target'>abc</option><option>def") +PASS <select size='2'> contents of target option preserved ("<select size='2'><option id='target'>abc</option><option>def") +PASS empty <select> ("<div>a<select></select>bc") +FAIL empty <optgroup> in <select> ("<div>a<select><optgroup></select>bc") assert_equals: expected "a\nbc" but got "abc" +FAIL empty <option> in <select> ("<div>a<select><option></select>bc") assert_equals: expected "a\nbc" but got "abc" +PASS <select> containing text node child ("<select class='poke'></select>") +PASS <optgroup> containing <optgroup> ("<select><optgroup class='poke-optgroup'></select>") +FAIL <optgroup> containing <option> ("<select><optgroup><option>abc</select>") assert_equals: expected "abc" but got "" +FAIL <div> in <option> ("<select><option class='poke-div'>123</select>") assert_equals: expected "123\nabc" but got "" +FAIL empty <optgroup> in <div> ("<div>a<optgroup></optgroup>bc") assert_equals: expected "a\nbc" but got "abc" +FAIL <optgroup> in <div> ("<div>a<optgroup>123</optgroup>bc") assert_equals: expected "a\nbc" but got "abc" +FAIL empty <option> in <div> ("<div>a<option></option>bc") assert_equals: expected "a\nbc" but got "abc" +FAIL <option> in <div> ("<div>a<option>123</option>bc") assert_equals: expected "a\n123\nbc" but got "abc" +PASS <button> contents preserved ("<div><button>abc") +FAIL <fieldset> contents preserved ("<div><fieldset>abc") assert_equals: expected "abc" but got "abc\n" +FAIL <fieldset> <legend> contents preserved ("<div><fieldset><legend>abc") assert_equals: expected "abc" but got "abc\n" +PASS <input> contents ignored ("<div><input type='text' value='abc'>") +PASS <textarea> contents ignored ("<div><textarea>abc") +FAIL <select size='1'> contents of options preserved ("<div><select size='1'><option>abc</option><option>def") assert_equals: expected "abc\ndef" but got "" +FAIL <select size='2'> contents of options preserved ("<div><select size='2'><option>abc</option><option>def") assert_equals: expected "abc\ndef" but got "" +PASS <iframe> contents ignored ("<div><iframe>abc") +PASS <iframe> subdocument ignored ("<div><iframe src='data:text/html,abc'>") +PASS <audio> contents ignored ("<div><audio>abc") +PASS <video> contents ignored ("<div><video>abc") +PASS <canvas> contents ignored ("<div><canvas>abc") +PASS <img> alt text ignored ("<div><img alt='abc'>") +PASS Newline at block boundary ("<div>123<div>abc</div>def") +PASS Newline at display:block boundary ("<div>123<span style='display:block'>abc</span>def") +PASS Empty block induces single line break ("<div>abc<div></div>def") +PASS Consecutive empty blocks ignored ("<div>abc<div></div><div></div>def") +FAIL No blank lines around <p> alone ("<div><p>abc") assert_equals: expected "abc" but got "abc\n\n" +FAIL No blank lines around <p> followed by only collapsible whitespace ("<div><p>abc</p> ") assert_equals: expected "abc" but got "abc\n\n" +FAIL No blank lines around <p> preceded by only collapsible whitespace ("<div> <p>abc</p>") assert_equals: expected "abc" but got "abc\n\n" +FAIL Blank line between consecutive <p>s ("<div><p>abc<p>def") assert_equals: expected "abc\n\ndef" but got "abc\n\ndef\n\n" +FAIL Blank line between consecutive <p>s separated only by collapsible whitespace ("<div><p>abc</p> <p>def") assert_equals: expected "abc\n\ndef" but got "abc\n\ndef\n\n" +FAIL Blank line between consecutive <p>s separated only by empty block ("<div><p>abc</p><div></div><p>def") assert_equals: expected "abc\n\ndef" but got "abc\n\ndef\n\n" +FAIL Blank lines between <p>s separated by non-empty block ("<div><p>abc</p><div>123</div><p>def") assert_equals: expected "abc\n\n123\n\ndef" but got "abc\n\n123\ndef\n\n" +FAIL Blank lines around a <p> in its own block ("<div>abc<div><p>123</p></div>def") assert_equals: expected "abc\n\n123\n\ndef" but got "abc\n123\n\ndef" +FAIL Blank line before <p> ("<div>abc<p>def") assert_equals: expected "abc\n\ndef" but got "abc\ndef\n\n" +PASS Blank line after <p> ("<div><p>abc</p>def") +FAIL One blank line between <p>s, ignoring empty <p>s ("<div><p>abc<p></p><p></p><p>def") assert_equals: expected "abc\n\ndef" but got "abc\n\ndef\n\n" +FAIL Invisible <p> doesn't induce extra line breaks ("<div style='visibility:hidden'><p><span style='visibility:visible'>abc</span></p>\n<div style='visibility:visible'>def</div>") assert_equals: expected "abc\ndef" but got "abc\n\ndef\n" +FAIL No blank lines around <div> with margin ("<div>abc<div style='margin:2em'>def") assert_equals: expected "abc\ndef" but got "abc\ndef\n" +PASS No newlines at display:inline-block boundary ("<div>123<span style='display:inline-block'>abc</span>def") +PASS Leading/trailing space removal at display:inline-block boundary ("<div>123<span style='display:inline-block'> abc </span>def") +FAIL Blank lines around <p> even without margin ("<div>123<p style='margin:0px'>abc</p>def") assert_equals: expected "123\n\nabc\n\ndef" but got "123\nabc\n\ndef" +PASS No blank lines around <h1> ("<div>123<h1>abc</h1>def") +PASS No blank lines around <h2> ("<div>123<h2>abc</h2>def") +PASS No blank lines around <h3> ("<div>123<h3>abc</h3>def") +PASS No blank lines around <h4> ("<div>123<h4>abc</h4>def") +PASS No blank lines around <h5> ("<div>123<h5>abc</h5>def") +PASS No blank lines around <h6> ("<div>123<h6>abc</h6>def") +PASS <span> boundaries are irrelevant ("<div>123<span>abc</span>def") +PASS <span> boundaries are irrelevant ("<div>123 <span>abc</span> def") +PASS <span> boundaries are irrelevant ("<div style='width:0'>123 <span>abc</span> def") +PASS <em> gets no special treatment ("<div>123<em>abc</em>def") +PASS <b> gets no special treatment ("<div>123<b>abc</b>def") +PASS <i> gets no special treatment ("<div>123<i>abc</i>def") +PASS <strong> gets no special treatment ("<div>123<strong>abc</strong>def") +PASS <tt> gets no special treatment ("<div>123<tt>abc</tt>def") +PASS <code> gets no special treatment ("<div>123<code>abc</code>def") +PASS soft hyphen preserved ("<div>abc­def") +PASS soft hyphen preserved ("<div style='width:0'>abc­def") +FAIL Ignoring non-rendered table whitespace ("<div><table style='white-space:pre'> <td>abc</td> </table>") assert_equals: expected "abc" but got "abc\n" +FAIL Tab-separated table cells ("<div><table><tr><td>abc<td>def</table>") assert_equals: expected "abc\tdef" but got "abc\tdef\n" +FAIL Tab-separated table cells including empty cells ("<div><table><tr><td>abc<td><td>def</table>") assert_equals: expected "abc\t\tdef" but got "abc\t\tdef\n" +FAIL Tab-separated table cells including trailing empty cells ("<div><table><tr><td>abc<td><td></table>") assert_equals: expected "abc\t\t" but got "abc\t\t\n" +FAIL Newline-separated table rows ("<div><table><tr><td>abc<tr><td>def</table>") assert_equals: expected "abc\ndef" but got "abc\ndef\n" +PASS Newlines around table ("<div>abc<table><td>def</table>ghi") +FAIL Tab-separated table cells in a border-collapse table ("<div><table style='border-collapse:collapse'><tr><td>abc<td>def</table>") assert_equals: expected "abc\tdef" but got "abc\tdef\n" +FAIL tfoot not reordered ("<div><table><tfoot>x</tfoot><tbody>y</tbody></table>") assert_equals: expected "xy" but got "xy\n" +FAIL ("<table><tfoot><tr><td>footer</tfoot><thead><tr><td style='visibility:collapse'>thead</thead><tbody><tr><td>tbody</tbody></table>") assert_equals: expected "footer\n\ntbody" but got "footer\ntbody\n" +FAIL Newline between cells and caption ("<div><table><tr><td>abc<caption>def</caption></table>") assert_equals: expected "abc\ndef" but got "abc\ndef\n" +FAIL Tab-separated table cells ("<div><div class='table'><span class='cell'>abc</span>\n<span class='cell'>def</span></div>") assert_equals: expected "abc\tdef" but got "abc\tdef\n" +FAIL Newline-separated table rows ("<div><div class='table'><span class='row'><span class='cell'>abc</span></span>\n<span class='row'><span class='cell'>def</span></span></div>") assert_equals: expected "abc\ndef" but got "abc\ndef\n" +PASS Newlines around table ("<div>abc<div class='table'><span class='cell'>def</span></div>ghi") +FAIL Tab-separated table cells ("<div><div class='itable'><span class='cell'>abc</span>\n<span class='cell'>def</span></div>") assert_equals: expected "abc\tdef" but got "abc\tdef " +FAIL Newline-separated table rows ("<div><div class='itable'><span class='row'><span class='cell'>abc</span></span>\n<span class='row'><span class='cell'>def</span></span></div>") assert_equals: expected "abc\ndef" but got "abc\tdef " +FAIL No newlines around inline-table ("<div>abc<div class='itable'><span class='cell'>def</span></div>ghi") assert_equals: expected "abcdefghi" but got "abc def ghi" +FAIL Single newline in two-row inline-table ("<div>abc<div class='itable'><span class='row'><span class='cell'>def</span></span>\n<span class='row'><span class='cell'>123</span></span></div>ghi") assert_equals: expected "abcdef\n123ghi" but got "abc def\t123 ghi" +FAIL <ol> list items get no special treatment ("<div><ol><li>abc") assert_equals: expected "abc" but got "abc\n" +FAIL <ul> list items get no special treatment ("<div><ul><li>abc") assert_equals: expected "abc" but got "abc\n" +FAIL display:block <script> is rendered ("<div><script style='display:block'>abc") assert_equals: expected "abc" but got "abc\n" +FAIL display:block <style> is rendered ("<div><style style='display:block'>abc") assert_equals: expected "abc" but got "abc\n" +PASS display:block <noscript> is not rendered (it's not parsed!) ("<div><noscript style='display:block'>abc") +PASS display:block <template> contents are not rendered (the contents are in a different document) ("<div><template style='display:block'>abc") +PASS <br> induces line break ("<div>abc<br>def") +PASS <br> induces line break even at end of block ("<div>abc<br>") +PASS <br> content ignored ("<div><br class='poke'>") +PASS <hr> induces line break ("<div>abc<hr>def") +PASS <hr><hr> induces just one line break ("<div>abc<hr><hr>def") +PASS <hr><hr><hr> induces just one line break ("<div>abc<hr><hr><hr>def") +FAIL <hr> content rendered ("<div><hr class='poke'>") assert_equals: expected "abc" but got "abc\n" +PASS comment ignored ("<div>abc<!--comment-->def") +FAIL text-transform is applied ("<div><div style='text-transform:uppercase'>abc") assert_equals: expected "ABC" but got "ABC\n" +FAIL text-transform handles es-zet ("<div><div style='text-transform:uppercase'>Maß") assert_equals: expected "MASS" but got "MAS\n" +FAIL text-transform handles Turkish casing ("<div><div lang='tr' style='text-transform:uppercase'>i ı") assert_equals: expected "İ I" but got "İ I\n" +PASS block-in-inline doesn't add unnecessary newlines ("<div>abc<span>123<div>456</div>789</span>def") +FAIL floats induce a block boundary ("<div>abc<div style='float:left'>123</div>def") assert_equals: expected "abc\n123\ndef" but got "abc123def" +FAIL floats induce a block boundary ("<div>abc<span style='float:left'>123</span>def") assert_equals: expected "abc\n123\ndef" but got "abc123def" +FAIL position:absolute induces a block boundary ("<div>abc<div style='position:absolute'>123</div>def") assert_equals: expected "abc\n123\ndef" but got "abc123def" +FAIL position:absolute induces a block boundary ("<div>abc<span style='position:absolute'>123</span>def") assert_equals: expected "abc\n123\ndef" but got "abc123def" +PASS position:relative has no effect ("<div>abc<div style='position:relative'>123</div>def") +PASS position:relative has no effect ("<div>abc<span style='position:relative'>123</span>def") +PASS overflow:hidden ignored ("<div style='overflow:hidden'>abc") +FAIL overflow:hidden ignored even with zero width ("<div style='width:0; overflow:hidden'>abc") assert_equals: expected "abc" but got "" +FAIL overflow:hidden ignored even with zero height ("<div style='height:0; overflow:hidden'>abc") assert_equals: expected "abc" but got "" +FAIL text-overflow:ellipsis ignored ("<div style='width:0; overflow:hidden; text-overflow:ellipsis'>abc") assert_equals: expected "abc" but got "" +PASS innerText not supported on SVG elements ("<svg>abc") +PASS innerText not supported on MathML elements ("<math>abc") +PASS <rt> and no <rp> ("<div><ruby>abc<rt>def</rt></ruby>") +PASS <rp> ("<div><ruby>abc<rp>(</rp><rt>def</rt><rp>)</rp></ruby>") +FAIL Lone <rp> ("<div><rp>abc</rp>") assert_equals: expected "" but got "abc" +PASS visibility:hidden <rp> ("<div><rp style='visibility:hidden'>abc</rp>") +PASS display:block <rp> ("<div><rp style='display:block'>abc</rp>def") +PASS display:block <rp> with whitespace ("<div><rp style='display:block'> abc </rp>def") +PASS <rp> in a <select> ("<div><select class='poke-rp'></select>") +PASS Shadow DOM contents ignored ("<div class='shadow'>") +PASS Shadow DOM contents ignored ("<div><div class='shadow'>") +FAIL CSS 'order' property ignored ("<div style='display:flex'><div style='order:1'>1</div><div>2</div></div>") assert_equals: expected "1\n2" but got "1\n2\n" +FAIL Flex items blockified ("<div style='display:flex'><span>1</span><span>2</span></div>") assert_equals: expected "1\n2" but got "1\n2\n" +FAIL CSS 'order' property ignored ("<div style='display:grid'><div style='order:1'>1</div><div>2</div></div>") assert_equals: expected "1\n2" but got "1\n2\n" +FAIL Grid items blockified ("<div style='display:grid'><span>1</span><span>2</span></div>") assert_equals: expected "1\n2" but got "1\n2\n" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-expected.txt new file mode 100644 index 0000000..b5a628c --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-expected.txt
@@ -0,0 +1,188 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer A'", + "position": [6, 6], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'", + "position": [38, 38], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [67, 67], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [67, 67], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Overflow Controls Host Layer", + "position": [62, 62], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [280, 67], + "bounds": [7, 160], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer B'", + "position": [355, 6], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow DIV class='scroller'", + "position": [387, 38], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [416, 67], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [416, 67], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='content'", + "position": [428, 79], + "bounds": [196, 212], + "contentsOpaque": true, + "backgroundColor": "#DDDDDD" + }, + { + "name": "Overflow Controls Host Layer", + "position": [411, 62], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [629, 67], + "bounds": [7, 160], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer C'", + "position": [6, 297], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow DIV class='scroller'", + "position": [37, 328], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [66, 357], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [66, 357], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='content'", + "position": [78, 369], + "bounds": [196, 212], + "contentsOpaque": true, + "backgroundColor": "#DDDDDD" + }, + { + "name": "Overflow Controls Host Layer", + "position": [61, 352], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [279, 357], + "bounds": [7, 160], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer D'", + "position": [355, 297], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'", + "position": [379, 321], + "bounds": [292, 200] + }, + { + "name": "LayoutBlockFlow DIV class='scroller'", + "position": [386, 328], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [415, 357], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [415, 357], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='content'", + "position": [427, 369], + "bounds": [196, 212], + "contentsOpaque": true, + "backgroundColor": "#DDDDDD" + }, + { + "name": "Overflow Controls Host Layer", + "position": [410, 352], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [628, 357], + "bounds": [7, 160], + "drawsContent": false + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment-expected.txt index 8e34c07..556d4d4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment-expected.txt
@@ -1,7 +1,7 @@ Tests how fragment works. f1.outerHTML: -<div-a attr="val" class=""><div-c class="my-class-1 my-class-2" foo="bar">Some text here And more text</div-c> +<div-a attr="val" class=""><div-b foo1="bar1" s-state1-attr="val-state1" class="" foo2="bar2"></div-b><div-c class="my-class-1 my-class-2" foo="bar">Some text here And more text</div-c> <div></div></div-a> () => diva === f1.element() true @@ -11,13 +11,9 @@ true () => divc.tagName === 'DIV-C' true -() => shadow.nodeType === Node.DOCUMENT_FRAGMENT_NODE - true -() => shadow.parentElementOrShadowHost() === diva - true () => divc.parentNode === diva true -() => divb.parentElementOrShadowHost() === diva +() => divb.parentNode === diva true () => diva.lastChild === inner true @@ -39,31 +35,15 @@ true () => divb.getAttribute('attr') === null true -() => diva.getAttribute('attr') === 'val-state1' - true -() => divb.getAttribute('attr') === 'val-state1' - true -() => diva.getAttribute('attr') === 'val-state1' - true -() => divb.getAttribute('attr') === 'val-state1' - true -() => diva.getAttribute('attr') === 'val' - true -() => divb.getAttribute('attr') === null - true -() => diva.getAttribute('attr') === 'val-state2' - true -() => divb.getAttribute('attr') === null - true f2.outerHTML: -<div><div-a attr="val-state2" class=""><div-c class="my-class-1 my-class-2" foo="bar">Some text here And more text</div-c> +<div><div-a attr="val" class=""><div-b foo1="bar1" s-state1-attr="val-state1" class="" foo2="bar2"></div-b><div-c class="my-class-1 my-class-2" foo="bar">Some text here And more text</div-c> <div></div></div-a></div> () => f2.element().firstChild === f1.element() true f3.outerHTML: -<div><div><div-a attr="val-state2" class=""><div-c class="my-class-1 my-class-2" foo="bar">Some text here And more text</div-c> +<div><div><div-a attr="val" class=""><div-b foo1="bar1" s-state1-attr="val-state1" class="" foo2="bar2"></div-b><div-c class="my-class-1 my-class-2" foo="bar">Some text here And more text</div-c> <div></div></div-a></div></div> () => f3.element().firstChild === f2.element() true
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment.js b/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment.js index 5927e60..80b424c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/components/fragment.js
@@ -11,11 +11,9 @@ var inner = document.createElement('div'); var f1 = UI.Fragment.build` - <div-a $=name-a attr=val s-state1-attr=val-state1 s-state2-attr=val-state2> - <x-shadow $=name-shadow> - <div-b $=name-b foo1=bar1 foo${'2'}=${'b'}ar${'2'} ${''} ${element => element.divb = true} s-state1-attr=val-state1> - </div-b> - </x-shadow> + <div-a $=name-a attr=val> + <div-b $=name-b foo1=bar1 foo${'2'}=${'b'}ar${'2'} ${''} ${element => element.divb = true} s-state1-attr=val-state1> + </div-b> <div-c $=name-c class='${'my-class-1'} my-class-2' ${'foo'}=bar>${'Some text here'} ${'And more text'}</div-c> ${inner} </div-a> @@ -27,16 +25,13 @@ var diva = f1.$('name-a'); var divb = f1.$('name-b'); var divc = f1.$('name-c'); - var shadow = f1.$('name-shadow'); check(() => diva === f1.element()); check(() => diva.tagName === 'DIV-A'); check(() => divb.tagName === 'DIV-B'); check(() => divc.tagName === 'DIV-C'); - check(() => shadow.nodeType === Node.DOCUMENT_FRAGMENT_NODE); - check(() => shadow.parentElementOrShadowHost() === diva); check(() => divc.parentNode === diva); - check(() => divb.parentElementOrShadowHost() === diva); + check(() => divb.parentNode === diva); check(() => diva.lastChild === inner); check(() => divb.getAttribute('foo1') === 'bar1'); @@ -50,18 +45,6 @@ check(() => diva.getAttribute('attr') === 'val'); check(() => divb.getAttribute('attr') === null); - f1.setState('state1', true); - check(() => diva.getAttribute('attr') === 'val-state1'); - check(() => divb.getAttribute('attr') === 'val-state1'); - f1.setState('state1', true); - check(() => diva.getAttribute('attr') === 'val-state1'); - check(() => divb.getAttribute('attr') === 'val-state1'); - f1.setState('state1', false); - check(() => diva.getAttribute('attr') === 'val'); - check(() => divb.getAttribute('attr') === null); - f1.setState('state2', true); - check(() => diva.getAttribute('attr') === 'val-state2'); - check(() => divb.getAttribute('attr') === null); TestRunner.addResult('');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search-expected.txt index c20d677..72462d87 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search-expected.txt
@@ -1,5 +1,37 @@ Tests search in network requests +URL search + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=02 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=0 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=12 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=1 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=22 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=2 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=32 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=3 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=42 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=4 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=52 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=5 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=62 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=6 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=72 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=7 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=82 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=8 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=92 + URLhttp://127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=9 + Referer:http://127.0.0.1:8000/devtools/resources/inspected-page.html + Ignore case, regexp echo-payload.php—127.0.0.1:8000/devtools/network/resources/echo-payload.php?n=01 1request0-dosearch-doSearch-d.Search
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search.js index 071d628..6ddf862 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-search.js
@@ -27,9 +27,9 @@ return treeElement; } - async function search(label, isRegex, ignoreCase) { + async function search(label, isRegex, ignoreCase, query = 'd.search') { TestRunner.addResult(label); - const view = await Network.SearchNetworkView.openSearch('d.search'); + const view = await Network.SearchNetworkView.openSearch(query); view._matchCaseButton.setToggled(!ignoreCase); view._regexButton.setToggled(isRegex); const promise = TestRunner.addSnifferPromise(view, '_searchFinished'); @@ -72,6 +72,7 @@ ConsoleTestRunner.addConsoleSniffer(step2); return; } + await search('URL search', true, true, '8000/devtools'); await search('Ignore case, regexp', true, true); await search('Ignore case, No regexp', false, true); const lastResult = await search('Case sensitive, regexp', true, false);
diff --git a/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-image-compression-expected.txt b/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-image-compression-expected.txt index e277e977..1bae546 100644 --- a/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-image-compression-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-image-compression-expected.txt
@@ -11,7 +11,6 @@ layer at (0,0) size 440x168 LayoutBlockFlow {HTML} at (0,0) size 440x168 LayoutBlockFlow {BODY} at (8,8) size 424x152 + LayoutImage {IMG} at (0,0) size 200x150 LayoutImage {IMG} at (200,0) size 200x150 LayoutText {#text} at (0,0) size 0x0 - layer at (8,8) size 200x150 - LayoutImage {IMG} at (0,0) size 200x150
diff --git a/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-legacy-formats-expected.txt b/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-legacy-formats-expected.txt index 9838c8d..1bae546 100644 --- a/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-legacy-formats-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/images/feature-policy-legacy-formats-expected.txt
@@ -12,6 +12,5 @@ LayoutBlockFlow {HTML} at (0,0) size 440x168 LayoutBlockFlow {BODY} at (8,8) size 424x152 LayoutImage {IMG} at (0,0) size 200x150 + LayoutImage {IMG} at (200,0) size 200x150 LayoutText {#text} at (0,0) size 0x0 - layer at (208,8) size 200x150 - LayoutImage {IMG} at (200,0) size 200x150
diff --git a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/url/url-setters-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/url/url-setters-expected.txt index 905255f..fd516ea 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/url/url-setters-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/url/url-setters-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 589 tests; 293 PASS, 296 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 592 tests; 296 PASS, 296 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. @@ -244,6 +244,9 @@ PASS URL: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme PASS <a>: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme PASS <area>: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme +PASS URL: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port +PASS <a>: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port +PASS <area>: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port FAIL URL: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path" FAIL <a>: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path" FAIL <area>: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/url/url-setters-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/url/url-setters-expected.txt index 905255f..fd516ea 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/url/url-setters-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/url/url-setters-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 589 tests; 293 PASS, 296 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 592 tests; 296 PASS, 296 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. @@ -244,6 +244,9 @@ PASS URL: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme PASS <a>: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme PASS <area>: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme +PASS URL: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port +PASS <a>: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port +PASS <area>: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port FAIL URL: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path" FAIL <a>: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path" FAIL <area>: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path"
diff --git a/third_party/WebKit/LayoutTests/platform/win/external/wpt/url/url-setters-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/url/url-setters-expected.txt index 3975ed3..7b91a90 100644 --- a/third_party/WebKit/LayoutTests/platform/win/external/wpt/url/url-setters-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/external/wpt/url/url-setters-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 589 tests; 266 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 592 tests; 269 PASS, 323 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… FAIL URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net" FAIL <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net" @@ -244,6 +244,9 @@ PASS URL: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme PASS <a>: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme PASS <area>: Setting <https://example.net>.host = 'example.com:80' Default port number is only removed for the relevant scheme +PASS URL: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port +PASS <a>: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port +PASS <area>: Setting <http://example.net:8080>.host = 'example.com:80' Port number is removed if new port is scheme default and existing URL has a non-default port FAIL URL: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path" FAIL <a>: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path" FAIL <area>: Setting <http://example.net/path>.host = 'example.com/stuff' Stuff after a / delimiter is ignored assert_equals: expected "http://example.com/path" but got "http://example.com%2Fstuff/path"
diff --git a/third_party/WebKit/LayoutTests/user-activation-v2/full-screen-gamepad-expected.txt b/third_party/WebKit/LayoutTests/user-activation-v2/full-screen-gamepad-expected.txt new file mode 100644 index 0000000..b17e8310 --- /dev/null +++ b/third_party/WebKit/LayoutTests/user-activation-v2/full-screen-gamepad-expected.txt
@@ -0,0 +1,4 @@ +CONSOLE MESSAGE: line 33: This test requires User Activation V2. +EXPECTED (internals.runtimeFlags.userActivationV2Enabled == 'false') OK +END OF TEST +
diff --git a/third_party/WebKit/LayoutTests/user-activation-v2/full-screen-gamepad.html b/third_party/WebKit/LayoutTests/user-activation-v2/full-screen-gamepad.html new file mode 100644 index 0000000..a98e4891 --- /dev/null +++ b/third_party/WebKit/LayoutTests/user-activation-v2/full-screen-gamepad.html
@@ -0,0 +1,49 @@ +<body> +<script src="../fullscreen/full-screen-test.js"></script> +<span></span> +<script> + var span = document.getElementsByTagName('span')[0]; + + var documentEnteredFullscreen = function() { + testExpected("document.fullscreenElement", document.documentElement); + span.requestFullscreen(); + waitForEvent(document, 'fullscreenchange', spanEnteredFullscreen, false, true); + }; + + var spanEnteredFullscreen = function() { + testExpected("document.fullscreenElement", span); + waitForEvent(document, 'fullscreenchange', spanExited, false, true); + document.exitFullscreen(); + }; + + var spanExited = function() { + testExpected("document.fullscreenElement", document.documentElement); + waitForEvent(document, 'fullscreenchange', documentExited, false, true); + document.exitFullscreen(); + }; + + var documentExited = function() { + testExpected("document.fullscreenElement", undefined); + endTest(); + }; + + testExpected("internals.runtimeFlags.userActivationV2Enabled", + internals.runtimeFlags.userActivationV2Enabled); + if (!internals.runtimeFlags.userActivationV2Enabled) { + console.log("This test requires User Activation V2."); + endTest(); + } else { + if (window.gamepadController) { + // Simulate pressing a button on a connected gamepad. A gamepad + // button press should be treated as a user activation for the + // fullscreen API. + gamepadController.connect(0); + gamepadController.setId(0, "FullScream Maximizer"); + gamepadController.setButtonCount(0, 1); + gamepadController.setButtonData(0, 0, 1); + navigator.getGamepads(); + } + document.documentElement.requestFullscreen(); + waitForEvent(document, 'fullscreenchange', documentEnteredFullscreen, false, true); + } +</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/user-activation-v2/user-activation-v2/README.txt b/third_party/WebKit/LayoutTests/virtual/user-activation-v2/user-activation-v2/README.txt new file mode 100644 index 0000000..4f3b7b6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/user-activation-v2/user-activation-v2/README.txt
@@ -0,0 +1 @@ +# This suite runs tests with --enable-features=UserActivationV2.
diff --git a/third_party/WebKit/LayoutTests/virtual/user-activation-v2/user-activation-v2/full-screen-gamepad-expected.txt b/third_party/WebKit/LayoutTests/virtual/user-activation-v2/user-activation-v2/full-screen-gamepad-expected.txt new file mode 100644 index 0000000..550d85713 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/user-activation-v2/user-activation-v2/full-screen-gamepad-expected.txt
@@ -0,0 +1,11 @@ +EXPECTED (internals.runtimeFlags.userActivationV2Enabled == 'true') OK +EVENT(fullscreenchange) +EXPECTED (document.fullscreenElement == '[object HTMLHtmlElement]') OK +EVENT(fullscreenchange) +EXPECTED (document.fullscreenElement == '[object HTMLSpanElement]') OK +EVENT(fullscreenchange) +EXPECTED (document.fullscreenElement == '[object HTMLHtmlElement]') OK +EVENT(fullscreenchange) +EXPECTED (document.fullscreenElement == 'undefined') OK +END OF TEST +
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 3a90358..945c74ff 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -19,6 +19,7 @@ "color_chooser/color_chooser.mojom", "feature_policy/feature_policy.mojom", "file/file_utilities.mojom", + "frame/find_in_page.mojom", "leak_detector/leak_detector.mojom", "loader/prefetch_url_loader_service.mojom", "net/ip_address_space.mojom",
diff --git a/third_party/blink/public/mojom/frame/OWNERS b/third_party/blink/public/mojom/frame/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/blink/public/mojom/frame/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/frame/find_in_page.mojom b/third_party/blink/public/mojom/frame/find_in_page.mojom new file mode 100644 index 0000000..c1ef682 --- /dev/null +++ b/third_party/blink/public/mojom/frame/find_in_page.mojom
@@ -0,0 +1,12 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module blink.mojom; + +interface FindInPage { + // Notify the frame that it is no longer the active frame in the + // current find session, and so it should clear its active find match + // (and no longer highlight it with special coloring). + ClearActiveFindMatch(); +};
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h index 65642f9..ffe051a 100644 --- a/third_party/blink/public/platform/task_type.h +++ b/third_party/blink/public/platform/task_type.h
@@ -11,6 +11,8 @@ // This enum is used for a histogram and it should not be re-numbered. // // For the task type usage guideline, see https://bit.ly/2vMAsQ4 +// +// When a new task type is created, use kCount value as a new value. enum class TaskType : unsigned { /////////////////////////////////////// // Speced tasks should use one of the following task types @@ -163,11 +165,6 @@ // Tasks related to animation like blinking caret or CSS animation. kInternalAnimation = 34, - // Tasks related to accessbility. Tasks with this type are mainly posted by: - // * //content/renderer/accessibility - // * //third_party/blink/renderer/modules/accessibility - kInternalAccessibility = 35, - /////////////////////////////////////// // The following task types are DEPRECATED! Use kInternal* instead. ///////////////////////////////////////
diff --git a/third_party/blink/public/platform/web_compositor_support.h b/third_party/blink/public/platform/web_compositor_support.h index 890cfad..6fd2c79 100644 --- a/third_party/blink/public/platform/web_compositor_support.h +++ b/third_party/blink/public/platform/web_compositor_support.h
@@ -37,13 +37,11 @@ namespace cc { class ContentLayerClient; class Layer; -class TextureLayerClient; } namespace blink { class WebContentLayer; -class WebExternalTextureLayer; class WebImageLayer; class WebLayer; class WebScrollbarLayer; @@ -60,9 +58,6 @@ virtual std::unique_ptr<WebContentLayer> CreateContentLayer( cc::ContentLayerClient*) = 0; - virtual std::unique_ptr<WebExternalTextureLayer> CreateExternalTextureLayer( - cc::TextureLayerClient*) = 0; - virtual std::unique_ptr<WebImageLayer> CreateImageLayer() = 0; virtual std::unique_ptr<WebScrollbarLayer> CreateScrollbarLayer(
diff --git a/third_party/blink/public/platform/web_external_texture_layer.h b/third_party/blink/public/platform/web_external_texture_layer.h index 445dacf..72ad5a28 100644 --- a/third_party/blink/public/platform/web_external_texture_layer.h +++ b/third_party/blink/public/platform/web_external_texture_layer.h
@@ -27,10 +27,12 @@ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_EXTERNAL_TEXTURE_LAYER_H_ #include "third_party/blink/public/platform/web_common.h" -#include "third_party/blink/public/platform/web_float_point.h" -#include "third_party/blink/public/platform/web_float_rect.h" #include "third_party/blink/public/platform/web_layer.h" +namespace gfx { +class PointF; +} + namespace blink { // This class represents a layer that renders a texture that is generated @@ -68,8 +70,8 @@ virtual void SetNearestNeighbor(bool) = 0; // Sets a UV transform to be used at draw time. Defaults to (0, 0) and (1, 1). - virtual void SetUV(const WebFloatPoint left_top, - const WebFloatPoint right_bottom) = 0; + virtual void SetUV(const gfx::PointF& left_top, + const gfx::PointF& right_bottom) = 0; }; } // namespace blink
diff --git a/third_party/blink/public/platform/web_media_player.h b/third_party/blink/public/platform/web_media_player.h index 0e6a4bff0..3ccb19a 100644 --- a/third_party/blink/public/platform/web_media_player.h +++ b/third_party/blink/public/platform/web_media_player.h
@@ -142,6 +142,8 @@ virtual void RequestRemotePlaybackControl() {} virtual void RequestRemotePlaybackStop() {} virtual void RequestRemotePlaybackDisabled(bool disabled) {} + virtual void FlingingStarted() {} + virtual void FlingingStopped() {} virtual void SetPreload(Preload) {} virtual WebTimeRanges Buffered() const = 0; virtual WebTimeRanges Seekable() const = 0;
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index 991e55c..fc0f83c2 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -52,7 +52,6 @@ class WebString; class WebTextCheckClient; class WebURL; -class WebURLLoaderFactory; class WebView; enum class WebTreeScopeType; struct WebAssociatedURLLoaderOptions; @@ -198,16 +197,6 @@ // Note: this may lead to the destruction of the frame. virtual bool DispatchBeforeUnloadEvent(bool is_reload) = 0; - // Returns a WebURLRequest corresponding to the load of the WebHistoryItem. - virtual WebURLRequest RequestFromHistoryItem(const WebHistoryItem&, - mojom::FetchCacheMode) const = 0; - - // Returns a WebURLRequest corresponding to the reload of the current - // HistoryItem. - virtual WebURLRequest RequestForReload( - WebFrameLoadType, - const WebURL& override_url = WebURL()) const = 0; - // Load the given URL. For history navigations, a valid WebHistoryItem // should be given, as well as a WebHistoryLoadType. virtual void Load( @@ -726,9 +715,6 @@ // default behavior will be restored. virtual void SetTickmarks(const WebVector<WebRect>&) = 0; - // Clears the active find match in the frame, if one exists. - virtual void ClearActiveFindMatch() = 0; - // Context menu ----------------------------------------------------------- // Returns the node that the context menu opened over. @@ -775,10 +761,6 @@ // Loading ------------------------------------------------------------------ - // Creates and returns a new WebURLLoaderFactory. This function can be called - // only when this frame is attached to a document. - virtual std::unique_ptr<WebURLLoaderFactory> CreateURLLoaderFactory() = 0; - // Returns an AssociatedURLLoader that is associated with this frame. The // loader will, for example, be cancelled when WebFrame::stopLoading is // called. @@ -788,15 +770,10 @@ const WebAssociatedURLLoaderOptions&) = 0; // Reload the current document. - // Note: reload() and reloadWithOverrideURL() will be deprecated. + // Note: reload() will be deprecated. // Do not use these APIs any more, but use loadRequest() instead. virtual void Reload(WebFrameLoadType) = 0; - // This is used for situations where we want to reload a different URL because - // of a redirect. - virtual void ReloadWithOverrideURL(const WebURL& override_url, - WebFrameLoadType) = 0; - // Load the given URL. virtual void LoadRequest(const WebURLRequest&) = 0;
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index a2f5297..a73abc9 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -89,17 +89,6 @@ return true; return false; } - -// Returns true for image elements that violate at least one of the feature -// policy optimized image policies. -// https://github.com/WICG/feature-policy/blob/gh-pages/policies/optimized-images.md -bool ShouldInvertColor(const Element* element) { - if (IsHTMLImageElement(element)) { - return ToHTMLImageElement(element)->ShouldInvertColor(); - } - return false; -} - } // namespace static EDisplay EquivalentBlockDisplay(EDisplay display) { @@ -751,15 +740,5 @@ style.SetLogicalHeight(Length(LayoutReplaced::kDefaultHeight, kFixed)); } } - - // If an image element violates feature policy optimized image policies, - // render it with inverted color. - if (ShouldInvertColor(element)) { - FilterOperations operations; - operations.Operations().push_back( - BasicComponentTransferFilterOperation::Create(1, - FilterOperation::INVERT)); - style.SetFilter(operations); - } } } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index c4b06fe2..833398da 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -457,7 +457,7 @@ static inline bool IsValidElementNamePerHTMLParser(const CharType* characters, unsigned length) { CharType c = characters[0] | 0x20; - if (!('a' <= c && c < 'z')) + if (!('a' <= c && c <= 'z')) return false; for (unsigned i = 1; i < length; ++i) {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 56d2c2d..66f3d76 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -150,6 +150,7 @@ #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h" #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h" #include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h" +#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scroll/scrollable_area.h" #include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h" @@ -629,6 +630,7 @@ } void Element::CallDistributeScroll(ScrollState& scroll_state) { + TRACE_EVENT0("input", "Element::CallDistributeScroll"); ScrollStateCallback* callback = GetScrollCustomizationCallbacks().GetDistributeScroll(this); @@ -713,6 +715,7 @@ }; void Element::CallApplyScroll(ScrollState& scroll_state) { + TRACE_EVENT0("input", "Element::CallApplyScroll"); // Hits ASSERTs when trying to determine whether we need to scroll on main // or CC. http://crbug.com/625676. DisableCompositingQueryAsserts disabler;
diff --git a/third_party/blink/renderer/core/editing/BUILD.gn b/third_party/blink/renderer/core/editing/BUILD.gn index ff6e80f0..2db2e5e 100644 --- a/third_party/blink/renderer/core/editing/BUILD.gn +++ b/third_party/blink/renderer/core/editing/BUILD.gn
@@ -351,6 +351,7 @@ "frame_caret_test.cc", "frame_selection_test.cc", "granularity_strategy_test.cc", + "hit_testing_bidi_test.cc", "ime/ime_text_span_test.cc", "ime/input_method_controller_test.cc", "inline_box_position_test.cc",
diff --git a/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc b/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc new file mode 100644 index 0000000..302ef02c --- /dev/null +++ b/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc
@@ -0,0 +1,4022 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/dom/document.h" + +#include "third_party/blink/renderer/core/editing/ephemeral_range.h" +#include "third_party/blink/renderer/core/editing/position_with_affinity.h" +#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" +#include "third_party/blink/renderer/core/editing/text_affinity.h" + +namespace blink { + +class HitTestingBidiTest : public EditingTestBase {}; + +// This file contains script-generated tests for PositionForPoint() +// that are related to bidirectional text. The test cases are only for +// behavior recording purposes, and do not necessarily reflect the +// correct/desired behavior. + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: |C B A d e f + // Bidi: 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo>def</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">|ABC</bdo>def</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: |C B A d e f + // Bidi: 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo>def</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">|ABC</bdo>def</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: d e f C B A| + // Bidi: 0 0 0 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>def<bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">def<bdo dir=\"rtl\">ABC|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: d e f C B A| + // Bidi: 0 0 0 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>def<bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">def<bdo dir=\"rtl\">ABC|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOfOneRun) { + // Visual: |C B A + // Bidi: 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">|ABC</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOfOneRun) { + // Visual: |C B A + // Bidi: 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">|ABC</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOfOneRun) { + // Visual: C B A| + // Bidi: 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">ABC|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOfOneRun) { + // Visual: C B A| + // Bidi: 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">ABC|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: d e f|C B A g h i + // Bidi: 0 0 0 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>def<bdo dir=rtl>ABC</bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">def|<bdo dir=\"rtl\">ABC</bdo>ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: d e f|C B A g h i + // Bidi: 0 0 0 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>def<bdo dir=rtl>ABC</bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">def<bdo dir=\"rtl\">|ABC</bdo>ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: g h i C B A|d e f + // Bidi: 0 0 0 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>ghi<bdo dir=rtl>ABC</bdo>def</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">ghi<bdo dir=\"rtl\">ABC|</bdo>def</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: g h i C B A|d e f + // Bidi: 0 0 0 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>ghi<bdo dir=rtl>ABC</bdo>def</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">ghi<bdo dir=\"rtl\">ABC</bdo>|def</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOfOneRun) { + // Visual: d e f|C B A + // Bidi: 0 0 0 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>def<bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">def|<bdo dir=\"rtl\">ABC</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockLtrBaseRunRightSideOfLeftEdgeOfOneRun) { + // Visual: d e f|C B A + // Bidi: 0 0 0 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr>def<bdo dir=rtl>ABC</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\">def<bdo dir=\"rtl\">|ABC</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockLtrBaseRunLeftSideOfRightEdgeOfOneRun) { + // Visual: C B A|d e f + // Bidi: 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo>def</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">ABC|</bdo>def</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockLtrBaseRunRightSideOfRightEdgeOfOneRun) { + // Visual: C B A|d e f + // Bidi: 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent("<div dir=ltr><bdo dir=rtl>ABC</bdo>def</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ("<div dir=\"ltr\"><bdo dir=\"rtl\">ABC</bdo>|def</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: F E D|a b c I H G + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo " + "dir=\"ltr\">|abc</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: F E D|a b c I H G + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo " + "dir=\"ltr\">|abc</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: I H G a b c|F E D + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: I H G a b c|F E D + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOfOneRun) { + // Visual: F E D|a b c + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">|abc</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockRtlBaseRunRightSideOfLeftEdgeOfOneRun) { + // Visual: F E D|a b c + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">|abc</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockRtlBaseRunLeftSideOfRightEdgeOfOneRun) { + // Visual: a b c|F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InLtrBlockRtlBaseRunRightSideOfRightEdgeOfOneRun) { + // Visual: a b c|F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: |a b c F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: |a b c F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: F E D a b c| + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: F E D a b c| + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOfOneRun) { + // Visual: |a b c + // Bidi: 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOfOneRun) { + // Visual: |a b c + // Bidi: 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOfOneRun) { + // Visual: a b c| + // Bidi: 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOfOneRun) { + // Visual: a b c| + // Bidi: 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: d e f|C B A g h i + // Bidi: 2 2 2 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo>ghi|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: d e f|C B A g h i + // Bidi: 2 2 2 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo>ghi|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: g h i C B A|d e f + // Bidi: 2 2 2 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\">ABC</bdo>def|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: g h i C B A|d e f + // Bidi: 2 2 2 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\">ABC</bdo>def|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOfOneRun) { + // Visual: d e f|C B A + // Bidi: 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockLtrBaseRunRightSideOfLeftEdgeOfOneRun) { + // Visual: d e f|C B A + // Bidi: 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockLtrBaseRunLeftSideOfRightEdgeOfOneRun) { + // Visual: C B A|d e f + // Bidi: 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockLtrBaseRunRightSideOfRightEdgeOfOneRun) { + // Visual: C B A|d e f + // Bidi: 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: F E D|a b c I H G + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo " + "dir=\"ltr\">abc</bdo>DEF|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOfOneRunWithBaseRunEnd) { + // Visual: F E D|a b c I H G + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo " + "dir=\"ltr\">abc</bdo>DEF|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: I H G a b c|F E D + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOfOneRunWithBaseRunEnd) { + // Visual: I H G a b c|F E D + // Bidi: 1 1 1 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOfOneRun) { + // Visual: F E D|a b c + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockRtlBaseRunRightSideOfLeftEdgeOfOneRun) { + // Visual: F E D|a b c + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockRtlBaseRunLeftSideOfRightEdgeOfOneRun) { + // Visual: a b c|F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, InRtlBlockRtlBaseRunRightSideOfRightEdgeOfOneRun) { + // Visual: a b c|F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: |a b c F E D g h i + // Bidi: 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: |a b c F E D g h i + // Bidi: 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: g h i F E D a b c| + // Bidi: 0 0 0 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>ghi<bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">ghi<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: g h i F E D a b c| + // Bidi: 0 0 0 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>ghi<bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">ghi<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOftwoNestedRuns) { + // Visual: |a b c F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOftwoNestedRuns) { + // Visual: |a b c F E D + // Bidi: 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOftwoNestedRuns) { + // Visual: F E D a b c| + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOftwoNestedRuns) { + // Visual: F E D a b c| + // Bidi: 1 1 1 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: g h i|a b c F E D j k l + // Bidi: 0 0 0 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>ghi<bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">ghi|<bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: g h i|a b c F E D j k l + // Bidi: 0 0 0 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>ghi<bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">ghi<bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: j k l F E D a b c|g h i + // Bidi: 0 0 0 1 1 1 2 2 2 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo>ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: j k l F E D a b c|g h i + // Bidi: 0 0 0 1 1 1 2 2 2 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo>|ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOftwoNestedRuns) { + // Visual: g h i|a b c F E D + // Bidi: 0 0 0 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>ghi<bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">ghi|<bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOftwoNestedRuns) { + // Visual: g h i|a b c F E D + // Bidi: 0 0 0 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>ghi<bdo dir=rtl>DEF<bdo dir=ltr>abc</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">ghi<bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOftwoNestedRuns) { + // Visual: F E D a b c|g h i + // Bidi: 1 1 1 2 2 2 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo>ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOftwoNestedRuns) { + // Visual: F E D a b c|g h i + // Bidi: 1 1 1 2 2 2 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>abc</bdo>DEF</bdo>ghi</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo>|ghi</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: I H G|C B A d e f L K J + // Bidi: 1 1 1 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>|def</bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: I H G|C B A d e f L K J + // Bidi: 1 1 1 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: L K J d e f C B A|I H G + // Bidi: 1 1 1 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: L K J d e f C B A|I H G + // Bidi: 1 1 1 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def|<bdo " + "dir=\"rtl\">ABC</bdo></bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOftwoNestedRuns) { + // Visual: I H G|C B A d e f + // Bidi: 1 1 1 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>|def</bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOftwoNestedRuns) { + // Visual: I H G|C B A d e f + // Bidi: 1 1 1 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOftwoNestedRuns) { + // Visual: d e f C B A|I H G + // Bidi: 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOftwoNestedRuns) { + // Visual: d e f C B A|I H G + // Bidi: 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def|<bdo " + "dir=\"rtl\">ABC</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: |C B A d e f I H G + // Bidi: 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: |C B A d e f I H G + // Bidi: 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: I H G d e f C B A| + // Bidi: 1 1 1 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: I H G d e f C B A| + // Bidi: 1 1 1 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOftwoNestedRuns) { + // Visual: |C B A d e f + // Bidi: 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOftwoNestedRuns) { + // Visual: |C B A d e f + // Bidi: 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOftwoNestedRuns) { + // Visual: d e f C B A| + // Bidi: 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOftwoNestedRuns) { + // Visual: d e f C B A| + // Bidi: 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: g h i|a b c F E D j k l + // Bidi: 2 2 2 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc</bdo></bdo>jkl|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: g h i|a b c F E D j k l + // Bidi: 2 2 2 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc</bdo></bdo>jkl|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: j k l F E D a b c|g h i + // Bidi: 2 2 2 3 3 3 4 4 4 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo>ghi|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: j k l F E D a b c|g h i + // Bidi: 2 2 2 3 3 3 4 4 4 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo>ghi|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOftwoNestedRuns) { + // Visual: g h i|a b c F E D + // Bidi: 2 2 2 4 4 4 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\">DEF|<bdo dir=\"ltr\">abc</bdo></bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOftwoNestedRuns) { + // Visual: g h i|a b c F E D + // Bidi: 2 2 2 4 4 4 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\">DEF|<bdo dir=\"ltr\">abc</bdo></bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOftwoNestedRuns) { + // Visual: F E D a b c|g h i + // Bidi: 3 3 3 4 4 4 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF|</bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOftwoNestedRuns) { + // Visual: F E D a b c|g h i + // Bidi: 3 3 3 4 4 4 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF|</bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: I H G|C B A d e f L K J + // Bidi: 1 1 1 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: I H G|C B A d e f L K J + // Bidi: 1 1 1 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: L K J d e f C B A|I H G + // Bidi: 1 1 1 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOftwoNestedRunsWithBaseRunEnd) { + // Visual: L K J d e f C B A|I H G + // Bidi: 1 1 1 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOftwoNestedRuns) { + // Visual: I H G|C B A d e f + // Bidi: 1 1 1 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOftwoNestedRuns) { + // Visual: I H G|C B A d e f + // Bidi: 1 1 1 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo>GHI|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOftwoNestedRuns) { + // Visual: d e f C B A|I H G + // Bidi: 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 57; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOftwoNestedRuns) { + // Visual: d e f C B A|I H G + // Bidi: 2 2 2 3 3 3 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>GHI<bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 63; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: |C B A d e f I H G j k l + // Bidi: 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo>jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: |C B A d e f I H G j k l + // Bidi: 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo>jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: j k l I H G d e f C B A| + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl<bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: j k l I H G d e f C B A| + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl<bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: |C B A d e f I H G + // Bidi: 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: |C B A d e f I H G + // Bidi: 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOfthreeNestedRuns) { + // Visual: I H G d e f C B A| + // Bidi: 1 1 1 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOfthreeNestedRuns) { + // Visual: I H G d e f C B A| + // Bidi: 1 1 1 2 2 2 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: j k l|C B A d e f I H G m n o + // Bidi: 0 0 0 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl|<bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: j k l|C B A d e f I H G m n o + // Bidi: 0 0 0 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl<bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo>mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: m n o I H G d e f C B A|j k l + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno<bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo>jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: m n o I H G d e f C B A|j k l + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno<bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo>|jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: j k l|C B A d e f I H G + // Bidi: 0 0 0 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl|<bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: j k l|C B A d e f I H G + // Bidi: 0 0 0 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>jkl<bdo dir=rtl>GHI<bdo dir=ltr><bdo " + "dir=rtl>ABC</bdo>def</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">jkl<bdo dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOfthreeNestedRuns) { + // Visual: I H G d e f C B A|j k l + // Bidi: 1 1 1 2 2 2 3 3 3 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo>jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOfthreeNestedRuns) { + // Visual: I H G d e f C B A|j k l + // Bidi: 1 1 1 2 2 2 3 3 3 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>def<bdo " + "dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo>|jkl</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: L K J|a b c F E D g h i O N M + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>MNO<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>|ghi</bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: L K J|a b c F E D g h i O N M + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>MNO<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: O N M g h i F E D a b c|L K J + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>MNO</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: O N M g h i F E D a b c|L K J + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi|<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo></bdo>MNO</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: L K J|a b c F E D g h i + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>|ghi</bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: L K J|a b c F E D g h i + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOfthreeNestedRuns) { + // Visual: g h i F E D a b c|L K J + // Bidi: 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOfthreeNestedRuns) { + // Visual: g h i F E D a b c|L K J + // Bidi: 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi|<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: |a b c F E D g h i L K J + // Bidi: 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc|</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: |a b c F E D g h i L K J + // Bidi: 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc|</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: L K J g h i F E D a b c| + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: L K J g h i F E D a b c| + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: |a b c F E D g h i + // Bidi: 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc|</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: |a b c F E D g h i + // Bidi: 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc|</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOfthreeNestedRuns) { + // Visual: g h i F E D a b c| + // Bidi: 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOfthreeNestedRuns) { + // Visual: g h i F E D a b c| + // Bidi: 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: j k l|C B A d e f I H G m n o + // Bidi: 2 2 2 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>mno</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>mno|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: j k l|C B A d e f I H G m n o + // Bidi: 2 2 2 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>mno</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>mno|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: m n o I H G d e f C B A|j k l + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>mno<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">mno<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo>jkl|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: m n o I H G d e f C B A|j k l + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>mno<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">mno<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo>jkl|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: j k l|C B A d e f I H G + // Bidi: 2 2 2 5 5 5 4 4 4 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\">GHI|<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: j k l|C B A d e f I H G + // Bidi: 2 2 2 5 5 5 4 4 4 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\">GHI|<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOfthreeNestedRuns) { + // Visual: I H G d e f C B A|j k l + // Bidi: 3 3 3 4 4 4 5 5 5 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI|</bdo>jkl</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOfthreeNestedRuns) { + // Visual: I H G d e f C B A|j k l + // Bidi: 3 3 3 4 4 4 5 5 5 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI|</bdo>jkl</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: L K J|a b c F E D g h i O N M + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: L K J|a b c F E D g h i O N M + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: O N M g h i F E D a b c|L K J + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo></bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOfthreeNestedRunsWithBaseRunEnd) { + // Visual: O N M g h i F E D a b c|L K J + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc</bdo>DEF</bdo></bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: L K J|a b c F E D g h i + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOfthreeNestedRuns) { + // Visual: L K J|a b c F E D g h i + // Bidi: 1 1 1 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo>JKL|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOfthreeNestedRuns) { + // Visual: g h i F E D a b c|L K J + // Bidi: 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 87; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOfthreeNestedRuns) { + // Visual: g h i F E D a b c|L K J + // Bidi: 2 2 2 3 3 3 4 4 4 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>JKL<bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 93; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: |a b c F E D g h i L K J m n o + // Bidi: 4 4 4 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</bdo></bdo>mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: |a b c F E D g h i L K J m n o + // Bidi: 4 4 4 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</bdo></bdo>mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: m n o L K J g h i F E D a b c| + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 147; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno<bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: m n o L K J g h i F E D a b c| + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 153; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno<bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfLeftEdgeOffourNestedRuns) { + // Visual: |a b c F E D g h i L K J + // Bidi: 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">|abc</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfLeftEdgeOffourNestedRuns) { + // Visual: |a b c F E D g h i L K J + // Bidi: 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">|abc</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryLeftSideOfRightEdgeOffourNestedRuns) { + // Visual: L K J g h i F E D a b c| + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockAtLineBoundaryRightSideOfRightEdgeOffourNestedRuns) { + // Visual: L K J g h i F E D a b c| + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>JKL</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: m n o|a b c F E D g h i L K J p q r + // Bidi: 0 0 0 4 4 4 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo>pqr</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno|<bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc</bdo></bdo>ghi</bdo></bdo>pqr</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: m n o|a b c F E D g h i L K J p q r + // Bidi: 0 0 0 4 4 4 3 3 3 2 2 2 1 1 1 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo>pqr</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno<bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">|abc</bdo></bdo>ghi</bdo></bdo>pqr</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: p q r L K J g h i F E D a b c|m n o + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>pqr<bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 147; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">pqr<bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>JKL</bdo>mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: p q r L K J g h i F E D a b c|m n o + // Bidi: 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>pqr<bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 153; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">pqr<bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL</bdo>|mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfLeftEdgeOffourNestedRuns) { + // Visual: m n o|a b c F E D g h i L K J + // Bidi: 0 0 0 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno|<bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">abc</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfLeftEdgeOffourNestedRuns) { + // Visual: m n o|a b c F E D g h i L K J + // Bidi: 0 0 0 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr>mno<bdo dir=rtl>JKL<bdo dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\">mno<bdo dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">DEF<bdo dir=\"ltr\">|abc</bdo></bdo>ghi</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunLeftSideOfRightEdgeOffourNestedRuns) { + // Visual: L K J g h i F E D a b c|m n o + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo " + "dir=\"ltr\">abc|</bdo>DEF</bdo></bdo>JKL</bdo>mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockLtrBaseRunRightSideOfRightEdgeOffourNestedRuns) { + // Visual: L K J g h i F E D a b c|m n o + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 0 0 0 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo " + "dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL</bdo>|mno</div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: O N M|C B A d e f I H G j k l R Q P + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>PQR<bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">PQR<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>|jkl</bdo>MNO</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: O N M|C B A d e f I H G j k l R Q P + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>PQR<bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">PQR<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: R Q P j k l I H G d e f C B A|O N M + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 147; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: R Q P j k l I H G d e f C B A|O N M + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 153; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl|<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfLeftEdgeOffourNestedRuns) { + // Visual: O N M|C B A d e f I H G j k l + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>|jkl</bdo>MNO</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfLeftEdgeOffourNestedRuns) { + // Visual: O N M|C B A d e f I H G j k l + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">|ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunLeftSideOfRightEdgeOffourNestedRuns) { + // Visual: j k l I H G d e f C B A|O N M + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InLtrBlockRtlBaseRunRightSideOfRightEdgeOffourNestedRuns) { + // Visual: j k l I H G d e f C B A|O N M + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=ltr><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"ltr\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl|<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: |C B A d e f I H G j k l O N M + // Bidi: 5 5 5 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo>jkl</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: |C B A d e f I H G j k l O N M + // Bidi: 5 5 5 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo>jkl</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: O N M j k l I H G d e f C B A| + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 147; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo></bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F( + HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: O N M j k l I H G d e f C B A| + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 153; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo></bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfLeftEdgeOffourNestedRuns) { + // Visual: |C B A d e f I H G j k l + // Bidi: 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() - 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo>jkl</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfLeftEdgeOffourNestedRuns) { + // Visual: |C B A d e f I H G j k l + // Bidi: 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 3; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC|</bdo>def</bdo></bdo>jkl</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryLeftSideOfRightEdgeOffourNestedRuns) { + // Visual: j k l I H G d e f C B A| + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockAtLineBoundaryRightSideOfRightEdgeOffourNestedRuns) { + // Visual: j k l I H G d e f C B A| + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: m n o|a b c F E D g h i L K J p q r + // Bidi: 2 2 2 6 6 6 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>mno<bdo dir=rtl>JKL<bdo " + "dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo>pqr</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">mno<bdo " + "dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo></bdo>pqr|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: m n o|a b c F E D g h i L K J p q r + // Bidi: 2 2 2 6 6 6 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>mno<bdo dir=rtl>JKL<bdo " + "dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo>pqr</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">mno<bdo " + "dir=\"rtl\">JKL<bdo dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo></bdo>pqr|</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: p q r L K J g h i F E D a b c|m n o + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>pqr<bdo dir=rtl><bdo " + "dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 147; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">pqr<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">|abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: p q r L K J g h i F E D a b c|m n o + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>pqr<bdo dir=rtl><bdo " + "dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 153; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">pqr<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL|</bdo>mno</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfLeftEdgeOffourNestedRuns) { + // Visual: m n o|a b c F E D g h i L K J + // Bidi: 2 2 2 6 6 6 5 5 5 4 4 4 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>mno<bdo dir=rtl>JKL<bdo " + "dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">mno<bdo " + "dir=\"rtl\">JKL|<bdo dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo></bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfLeftEdgeOffourNestedRuns) { + // Visual: m n o|a b c F E D g h i L K J + // Bidi: 2 2 2 6 6 6 5 5 5 4 4 4 3 3 3 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr>mno<bdo dir=rtl>JKL<bdo " + "dir=ltr><bdo dir=rtl>DEF<bdo " + "dir=ltr>abc</bdo></bdo>ghi</bdo></bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\">mno<bdo " + "dir=\"rtl\">JKL|<bdo dir=\"ltr\"><bdo dir=\"rtl\">DEF<bdo " + "dir=\"ltr\">abc</bdo></bdo>ghi</bdo></bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunLeftSideOfRightEdgeOffourNestedRuns) { + // Visual: L K J g h i F E D a b c|m n o + // Bidi: 3 3 3 4 4 4 5 5 5 6 6 6 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo " + "dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL|</bdo>mno</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockLtrBaseRunRightSideOfRightEdgeOffourNestedRuns) { + // Visual: L K J g h i F E D a b c|m n o + // Bidi: 3 3 3 4 4 4 5 5 5 6 6 6 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl><bdo " + "dir=ltr>ghi<bdo dir=rtl><bdo " + "dir=ltr>abc</bdo>DEF</bdo></bdo>JKL</bdo>mno</bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">ghi<bdo dir=\"rtl\"><bdo " + "dir=\"ltr\">abc</bdo>DEF</bdo></bdo>JKL|</bdo>mno</bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: O N M|C B A d e f I H G j k l R Q P + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>PQR<bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">PQR<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>jkl</bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: O N M|C B A d e f I H G j k l R Q P + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>PQR<bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">PQR<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>jkl</bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: R Q P j k l I H G d e f C B A|O N M + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 147; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC</bdo></bdo>GHI</bdo></bdo>|PQR</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOffourNestedRunsWithBaseRunEnd) { + // Visual: R Q P j k l I H G d e f C B A|O N M + // Bidi: 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 153; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo>PQR</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfLeftEdgeOffourNestedRuns) { + // Visual: O N M|C B A d e f I H G j k l + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 27; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>jkl</bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfLeftEdgeOffourNestedRuns) { + // Visual: O N M|C B A d e f I H G j k l + // Bidi: 1 1 1 5 5 5 4 4 4 3 3 3 2 2 2 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl><bdo dir=ltr><bdo dir=rtl>GHI<bdo " + "dir=ltr><bdo dir=rtl>ABC</bdo>def</bdo></bdo>jkl</bdo>MNO</bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 33; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\"><bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">GHI<bdo dir=\"ltr\"><bdo " + "dir=\"rtl\">ABC</bdo>def</bdo></bdo>jkl</bdo>MNO|</bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunLeftSideOfRightEdgeOffourNestedRuns) { + // Visual: j k l I H G d e f C B A|O N M + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 117; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +TEST_F(HitTestingBidiTest, + InRtlBlockRtlBaseRunRightSideOfRightEdgeOffourNestedRuns) { + // Visual: j k l I H G d e f C B A|O N M + // Bidi: 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 + LoadAhem(); + InsertStyleElement("div {font: 10px/10px Ahem; width: 300px}"); + SetBodyContent( + "<div dir=rtl><bdo dir=rtl>MNO<bdo dir=ltr>jkl<bdo dir=rtl><bdo " + "dir=ltr>def<bdo dir=rtl>ABC</bdo></bdo>GHI</bdo></bdo></bdo></div>"); + Element* div = GetDocument().QuerySelector("div"); + int x = div->OffsetLeft() + 123; + int y = div->OffsetTop() + 5; + const EphemeralRange result(GetDocument().caretRangeFromPoint(x, y)); + EXPECT_TRUE(result.IsNotNull()); + EXPECT_TRUE(result.IsCollapsed()); + EXPECT_EQ( + "<div dir=\"rtl\"><bdo dir=\"rtl\">MNO<bdo dir=\"ltr\">jkl<bdo " + "dir=\"rtl\"><bdo dir=\"ltr\">def<bdo " + "dir=\"rtl\">ABC|</bdo></bdo>GHI</bdo></bdo></bdo></div>", + GetCaretTextFromBody(result.StartPosition())); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/editing/iterators/character_iterator.cc b/third_party/blink/renderer/core/editing/iterators/character_iterator.cc index fd957f4..d07c56d 100644 --- a/third_party/blink/renderer/core/editing/iterators/character_iterator.cc +++ b/third_party/blink/renderer/core/editing/iterators/character_iterator.cc
@@ -90,37 +90,13 @@ template <typename Strategy> PositionTemplate<Strategy> CharacterIteratorAlgorithm<Strategy>::GetPositionBefore() const { - if (text_iterator_.AtEnd()) { - DCHECK_EQ(run_offset_, 0); - return PositionTemplate<Strategy>( - text_iterator_.CurrentContainer(), - text_iterator_.StartOffsetInCurrentContainer()); - } - const Node& node = *text_iterator_.GetNode(); - DCHECK_GE(text_iterator_.length(), 1); - if (node.IsTextNode()) { - const int offset = text_iterator_.StartOffsetInCurrentContainer(); - return PositionTemplate<Strategy>(node, offset + run_offset_); - } - return PositionTemplate<Strategy>::BeforeNode(node); + return text_iterator_.GetPositionBefore(run_offset_); } template <typename Strategy> PositionTemplate<Strategy> CharacterIteratorAlgorithm<Strategy>::GetPositionAfter() const { - if (text_iterator_.AtEnd()) { - DCHECK_EQ(run_offset_, 0); - return PositionTemplate<Strategy>( - text_iterator_.CurrentContainer(), - text_iterator_.EndOffsetInCurrentContainer()); - } - DCHECK_GE(text_iterator_.length(), 1); - const Node& node = *text_iterator_.GetNode(); - if (node.IsTextNode()) { - const int offset = text_iterator_.StartOffsetInCurrentContainer(); - return PositionTemplate<Strategy>(node, offset + run_offset_ + 1); - } - return PositionTemplate<Strategy>::AfterNode(node); + return text_iterator_.GetPositionAfter(run_offset_); } template <typename Strategy>
diff --git a/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc b/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc index 3022d0e..212c2e6d 100644 --- a/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc +++ b/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc
@@ -72,6 +72,107 @@ EXPECT_EQ(Position(text_node, 3), result.EndPosition()); } +TEST_F(CharacterIteratorTest, GetPositionWithBlock) { + SetBodyContent("a<div>b</div>c"); + + const Element& body = *GetDocument().body(); + CharacterIterator it(EphemeralRange::RangeOfContents(body)); + + const Node& text_a = *body.firstChild(); + const Node& div = *text_a.nextSibling(); + const Node& text_b = *div.firstChild(); + const Node& text_c = *body.lastChild(); + + EXPECT_EQ(Position(text_a, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_a, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_a, 0), it.StartPosition()); + EXPECT_EQ(Position(text_a, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position::BeforeNode(div), it.GetPositionBefore()); + EXPECT_EQ(Position::BeforeNode(div), it.GetPositionAfter()); + EXPECT_EQ(Position(body, 1), it.StartPosition()); + EXPECT_EQ(Position(body, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_b, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_b, 0), it.StartPosition()); + EXPECT_EQ(Position(text_b, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_b, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(div, 1), it.StartPosition()); + EXPECT_EQ(Position(div, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_c, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_c, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_c, 0), it.StartPosition()); + EXPECT_EQ(Position(text_c, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(body, 3), it.GetPositionBefore()); + EXPECT_EQ(Position(body, 3), it.GetPositionAfter()); + EXPECT_EQ(Position(body, 3), it.StartPosition()); + EXPECT_EQ(Position(body, 3), it.EndPosition()); + + EXPECT_TRUE(it.AtEnd()); +} + +TEST_F(CharacterIteratorTest, GetPositionWithBlocks) { + SetBodyContent("<p id=a>b</p><p id=c>d</p>"); + + const Element& body = *GetDocument().body(); + CharacterIterator it(EphemeralRange::RangeOfContents(body)); + + const Node& element_p_a = *GetDocument().getElementById("a"); + const Node& text_b = *element_p_a.firstChild(); + const Node& element_p_c = *GetDocument().getElementById("c"); + const Node& text_d = *element_p_c.firstChild(); + + EXPECT_EQ(Position(text_b, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_b, 0), it.StartPosition()); + EXPECT_EQ(Position(text_b, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_b, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(element_p_a, 1), it.StartPosition()); + EXPECT_EQ(Position(element_p_a, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_b, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(element_p_a, 1), it.StartPosition()); + EXPECT_EQ(Position(element_p_a, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_d, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_d, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_d, 0), it.StartPosition()); + EXPECT_EQ(Position(text_d, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(body, 2), it.GetPositionBefore()); + EXPECT_EQ(Position(body, 2), it.GetPositionAfter()); + EXPECT_EQ(Position(body, 2), it.StartPosition()); + EXPECT_EQ(Position(body, 2), it.EndPosition()); + + EXPECT_TRUE(it.AtEnd()); +} + TEST_F(CharacterIteratorTest, GetPositionWithBR) { SetBodyContent("a<br>b"); @@ -111,4 +212,115 @@ EXPECT_TRUE(it.AtEnd()); } +TEST_F(CharacterIteratorTest, GetPositionWithCollapsedWhitespaces) { + SetBodyContent("a <div> b </div> c"); + + const Element& body = *GetDocument().body(); + CharacterIterator it(EphemeralRange::RangeOfContents(body)); + + const Node& text_a = *body.firstChild(); + const Node& div = *text_a.nextSibling(); + const Node& text_b = *div.firstChild(); + const Node& text_c = *body.lastChild(); + + EXPECT_EQ(Position(text_a, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_a, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_a, 0), it.StartPosition()); + EXPECT_EQ(Position(text_a, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position::BeforeNode(div), it.GetPositionBefore()); + EXPECT_EQ(Position::BeforeNode(div), it.GetPositionAfter()); + EXPECT_EQ(Position(body, 1), it.StartPosition()); + EXPECT_EQ(Position(body, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_b, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 2), it.GetPositionAfter()); + EXPECT_EQ(Position(text_b, 1), it.StartPosition()); + EXPECT_EQ(Position(text_b, 2), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_b, 3), it.GetPositionBefore()); + EXPECT_EQ(Position(text_b, 3), it.GetPositionAfter()); + EXPECT_EQ(Position(div, 1), it.StartPosition()); + EXPECT_EQ(Position(div, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_c, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_c, 2), it.GetPositionAfter()); + EXPECT_EQ(Position(text_c, 1), it.StartPosition()); + EXPECT_EQ(Position(text_c, 2), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(body, 3), it.GetPositionBefore()); + EXPECT_EQ(Position(body, 3), it.GetPositionAfter()); + EXPECT_EQ(Position(body, 3), it.StartPosition()); + EXPECT_EQ(Position(body, 3), it.EndPosition()); + + EXPECT_TRUE(it.AtEnd()); +} + +TEST_F(CharacterIteratorTest, GetPositionWithEmitChar16Before) { + InsertStyleElement("b { white-space: pre; }"); + SetBodyContent("a <b> c</b>"); + + const Element& body = *GetDocument().body(); + CharacterIterator it(EphemeralRange::RangeOfContents(body)); + + const Node& text_a = *body.firstChild(); + const Node& element_b = *text_a.nextSibling(); + const Node& text_c = *element_b.firstChild(); + + EXPECT_EQ(Position(text_a, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_a, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_a, 0), it.StartPosition()); + EXPECT_EQ(Position(text_a, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_a, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_a, 2), it.GetPositionAfter()); + EXPECT_EQ(Position(text_a, 1), it.StartPosition()); + EXPECT_EQ(Position(text_a, 2), it.EndPosition()); + + // TODO(editing-dev): We should know why we emit a space character for + // "white-space: pre" element after trailing whitespace. + // A space character emitted by |EmitChar16Before()|. + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_c, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_c, 0), it.GetPositionAfter()); + EXPECT_EQ(Position(text_c, 0), it.StartPosition()); + EXPECT_EQ(Position(text_c, 0), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_c, 0), it.GetPositionBefore()); + EXPECT_EQ(Position(text_c, 1), it.GetPositionAfter()); + EXPECT_EQ(Position(text_c, 0), it.StartPosition()); + EXPECT_EQ(Position(text_c, 1), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(text_c, 1), it.GetPositionBefore()); + EXPECT_EQ(Position(text_c, 2), it.GetPositionAfter()); + EXPECT_EQ(Position(text_c, 1), it.StartPosition()); + EXPECT_EQ(Position(text_c, 2), it.EndPosition()); + + ASSERT_FALSE(it.AtEnd()); + it.Advance(1); + EXPECT_EQ(Position(body, 2), it.GetPositionBefore()); + EXPECT_EQ(Position(body, 2), it.GetPositionAfter()); + EXPECT_EQ(Position(body, 2), it.StartPosition()); + EXPECT_EQ(Position(body, 2), it.EndPosition()); + + EXPECT_TRUE(it.AtEnd()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator.cc b/third_party/blink/renderer/core/editing/iterators/text_iterator.cc index 5d28508..9f42381 100644 --- a/third_party/blink/renderer/core/editing/iterators/text_iterator.cc +++ b/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
@@ -886,6 +886,64 @@ } template <typename Strategy> +PositionTemplate<Strategy> TextIteratorAlgorithm<Strategy>::GetPositionBefore( + int char16_offset) const { + if (AtEnd()) { + DCHECK_EQ(char16_offset, 0); + return PositionTemplate<Strategy>(CurrentContainer(), + StartOffsetInCurrentContainer()); + } + DCHECK_GE(char16_offset, 0); + DCHECK_LT(char16_offset, length()); + DCHECK_GE(length(), 1); + const Node& node = *text_state_.PositionNode(); + if (text_state_.IsInTextNode() || text_state_.IsBeforeCharacter()) { + return PositionTemplate<Strategy>( + node, text_state_.PositionStartOffset() + char16_offset); + } + if (node.IsTextNode()) { + if (text_state_.IsAfterPositionNode()) + return PositionTemplate<Strategy>(node, ToText(node).length()); + return PositionTemplate<Strategy>(node, 0); + } + if (text_state_.IsAfterPositionNode()) + return PositionTemplate<Strategy>::AfterNode(node); + DCHECK(!text_state_.IsBeforeChildren()); + return PositionTemplate<Strategy>::BeforeNode(node); +} + +template <typename Strategy> +PositionTemplate<Strategy> TextIteratorAlgorithm<Strategy>::GetPositionAfter( + int char16_offset) const { + if (AtEnd()) { + DCHECK_EQ(char16_offset, 0); + return PositionTemplate<Strategy>(CurrentContainer(), + EndOffsetInCurrentContainer()); + } + DCHECK_GE(char16_offset, 0); + DCHECK_LT(char16_offset, length()); + DCHECK_GE(length(), 1); + const Node& node = *text_state_.PositionNode(); + if (text_state_.IsBeforeCharacter()) { + return PositionTemplate<Strategy>( + node, text_state_.PositionStartOffset() + char16_offset); + } + if (text_state_.IsInTextNode()) { + return PositionTemplate<Strategy>( + node, text_state_.PositionStartOffset() + char16_offset + 1); + } + if (node.IsTextNode()) { + if (text_state_.IsBeforePositionNode()) + return PositionTemplate<Strategy>(node, 0); + return PositionTemplate<Strategy>(node, ToText(node).length()); + } + if (text_state_.IsBeforePositionNode()) + return PositionTemplate<Strategy>::BeforeNode(node); + DCHECK(!text_state_.IsBeforeChildren()); + return PositionTemplate<Strategy>::AfterNode(node); +} + +template <typename Strategy> PositionTemplate<Strategy> TextIteratorAlgorithm<Strategy>::StartPositionInCurrentContainer() const { return PositionTemplate<Strategy>::EditingPositionOf(
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator.h b/third_party/blink/renderer/core/editing/iterators/text_iterator.h index 6bf64aca..75ddebc 100644 --- a/third_party/blink/renderer/core/editing/iterators/text_iterator.h +++ b/third_party/blink/renderer/core/editing/iterators/text_iterator.h
@@ -81,6 +81,12 @@ PositionTemplate<Strategy> StartPositionInCurrentContainer() const; PositionTemplate<Strategy> EndPositionInCurrentContainer() const; + // Returns the position before |char16_offset| in current text run. + PositionTemplate<Strategy> GetPositionBefore(int char16_offset) const; + + // Returns the position after |char16_offset| in current text run. + PositionTemplate<Strategy> GetPositionAfter(int char16_offset) const; + const TextIteratorTextState& GetText() const { return text_state_; } int length() const { return text_state_.length(); } UChar CharacterAt(unsigned index) const {
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc index 7d443a32..66c79b7 100644 --- a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc +++ b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc
@@ -144,6 +144,7 @@ position_start_offset_ = node_index; position_end_offset_ = node_index; return; + case PositionNodeType::kBeforeCharacter: case PositionNodeType::kBeforeChildren: case PositionNodeType::kInText: case PositionNodeType::kNone: @@ -191,7 +192,14 @@ void TextIteratorTextState::EmitChar16Before(UChar code_unit, const Text& text_node, unsigned offset) { - SetTextNodePosition(text_node, offset, offset); + // TODO(editing-dev): text-transform:uppercase can make text longer, e.g. + // "U+00DF" to "SS". See "fast/css/case-transform.html" + // DCHECK_LE(offset, text_node.length()); + position_node_type_ = PositionNodeType::kBeforeCharacter; + position_container_node_ = &text_node; + position_node_ = &text_node; + position_start_offset_ = offset; + position_end_offset_ = offset; PopulateStringBufferFromChar16(code_unit); } @@ -253,7 +261,7 @@ void TextIteratorTextState::SetTextNodePosition(const Text& text_node, unsigned position_start_offset, unsigned position_end_offset) { - DCHECK_LE(position_start_offset, position_end_offset); + DCHECK_LT(position_start_offset, position_end_offset); // TODO(editing-dev): text-transform:uppercase can make text longer, e.g. // "U+00DF" to "SS". See "fast/css/case-transform.html" // DCHECK_LE(position_end_offset, text_node.length());
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h index 8f1f040..e185b2f 100644 --- a/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h +++ b/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
@@ -91,6 +91,21 @@ unsigned PositionEndOffset() const; const Node* PositionNode() const { return position_node_; } const Node* PositionContainerNode() const { return position_container_node_; } + bool IsAfterPositionNode() const { + return position_node_type_ == PositionNodeType::kAfterNode; + } + bool IsBeforePositionNode() const { + return position_node_type_ == PositionNodeType::kBeforeNode; + } + bool IsBeforeCharacter() const { + return position_node_type_ == PositionNodeType::kBeforeCharacter; + } + bool IsBeforeChildren() const { + return position_node_type_ == PositionNodeType::kBeforeChildren; + } + bool IsInTextNode() const { + return position_node_type_ == PositionNodeType::kInText; + } bool HasEmitted() const { return has_emitted_; } UChar LastCharacter() const { return last_character_; } @@ -106,6 +121,7 @@ kAfterNode, kAltText, kAsNode, + kBeforeCharacter, kBeforeChildren, kBeforeNode, kInText,
diff --git a/third_party/blink/renderer/core/editing/rendered_position.cc b/third_party/blink/renderer/core/editing/rendered_position.cc index 2ce997d2..278c535 100644 --- a/third_party/blink/renderer/core/editing/rendered_position.cc +++ b/third_party/blink/renderer/core/editing/rendered_position.cc
@@ -46,32 +46,12 @@ namespace blink { -RenderedPosition::RenderedPosition(const VisiblePosition& position) - : RenderedPosition(position.DeepEquivalent(), position.Affinity()) {} - RenderedPosition::RenderedPosition(const VisiblePositionInFlatTree& position) - : RenderedPosition(position.DeepEquivalent(), position.Affinity()) {} - -// TODO(editing-dev): Stop duplicating code in the two constructors - -RenderedPosition::RenderedPosition(const Position& position, - TextAffinity affinity) : inline_box_(nullptr), offset_(0) { if (position.IsNull()) return; InlineBoxPosition box_position = - ComputeInlineBoxPosition(PositionWithAffinity(position, affinity)); - inline_box_ = box_position.inline_box; - offset_ = box_position.offset_in_box; -} - -RenderedPosition::RenderedPosition(const PositionInFlatTree& position, - TextAffinity affinity) - : inline_box_(nullptr), offset_(0) { - if (position.IsNull()) - return; - InlineBoxPosition box_position = ComputeInlineBoxPosition( - PositionInFlatTreeWithAffinity(position, affinity)); + ComputeInlineBoxPosition(position.ToPositionWithAffinity()); inline_box_ = box_position.inline_box; offset_ = box_position.offset_in_box; } @@ -182,28 +162,28 @@ return false; } -Position RenderedPosition::PositionAtLeftBoundaryOfBiDiRun() const { +PositionInFlatTree RenderedPosition::PositionAtLeftBoundaryOfBiDiRun() const { DCHECK(AtLeftBoundaryOfBidiRun()); if (AtLeftmostOffsetInBox()) { - return Position::EditingPositionOf( + return PositionInFlatTree::EditingPositionOf( inline_box_->GetLineLayoutItem().GetNode(), offset_); } - return Position::EditingPositionOf( + return PositionInFlatTree::EditingPositionOf( NextLeafChild()->GetLineLayoutItem().GetNode(), NextLeafChild()->CaretLeftmostOffset()); } -Position RenderedPosition::PositionAtRightBoundaryOfBiDiRun() const { +PositionInFlatTree RenderedPosition::PositionAtRightBoundaryOfBiDiRun() const { DCHECK(AtRightBoundaryOfBidiRun()); if (AtRightmostOffsetInBox()) { - return Position::EditingPositionOf( + return PositionInFlatTree::EditingPositionOf( inline_box_->GetLineLayoutItem().GetNode(), offset_); } - return Position::EditingPositionOf( + return PositionInFlatTree::EditingPositionOf( PrevLeafChild()->GetLineLayoutItem().GetNode(), PrevLeafChild()->CaretRightmostOffset()); }
diff --git a/third_party/blink/renderer/core/editing/rendered_position.h b/third_party/blink/renderer/core/editing/rendered_position.h index 21bf0c4d..af4ff994 100644 --- a/third_party/blink/renderer/core/editing/rendered_position.h +++ b/third_party/blink/renderer/core/editing/rendered_position.h
@@ -42,21 +42,19 @@ class FrameSelection; struct CompositedSelection; +// TODO(xiaochengh): RenderedPosition is deprecated. It's currently only used in +// |SelectionController| for bidi adjustment. We should break this class and +// move relevant code to |inline_box_traversal.cc|, and templatize it so that it +// can be reused in LayoutNG. class CORE_EXPORT RenderedPosition { STACK_ALLOCATED(); public: RenderedPosition(); - explicit RenderedPosition(const VisiblePosition&); explicit RenderedPosition(const VisiblePositionInFlatTree&); - RenderedPosition(const Position&, TextAffinity); - RenderedPosition(const PositionInFlatTree&, TextAffinity); bool IsEquivalent(const RenderedPosition&) const; bool IsNull() const { return !inline_box_; } - const RootInlineBox* RootBox() const { - return inline_box_ ? &inline_box_->Root() : nullptr; - } unsigned char BidiLevelOnLeft() const; unsigned char BidiLevelOnRight() const; @@ -79,8 +77,8 @@ return AtRightBoundaryOfBidiRun(kMatchBidiLevel, bidi_level_of_run); } - Position PositionAtLeftBoundaryOfBiDiRun() const; - Position PositionAtRightBoundaryOfBiDiRun() const; + PositionInFlatTree PositionAtLeftBoundaryOfBiDiRun() const; + PositionInFlatTree PositionAtRightBoundaryOfBiDiRun() const; // TODO(editing-dev): This function doesn't use RenderedPosition // instance anymore. Consider moving.
diff --git a/third_party/blink/renderer/core/editing/selection_adjuster.cc b/third_party/blink/renderer/core/editing/selection_adjuster.cc index 728e4330..af992e1 100644 --- a/third_party/blink/renderer/core/editing/selection_adjuster.cc +++ b/third_party/blink/renderer/core/editing/selection_adjuster.cc
@@ -766,4 +766,67 @@ return EditingBoundaryAdjuster::AdjustSelection(selection); } +class SelectionTypeAdjuster final { + STATIC_ONLY(SelectionTypeAdjuster); + + public: + template <typename Strategy> + static SelectionTemplate<Strategy> AdjustSelection( + const SelectionTemplate<Strategy>& selection) { + const EphemeralRangeTemplate<Strategy>& range = selection.ComputeRange(); + const SelectionType selection_type = ComputeSelectionType(range); + if (selection_type == kCaretSelection) { + return typename SelectionTemplate<Strategy>::Builder() + .Collapse(PositionWithAffinityTemplate<Strategy>( + range.StartPosition(), selection.Affinity())) + .Build(); + } + + DCHECK_EQ(selection_type, kRangeSelection); + // "Constrain" the selection to be the smallest equivalent range of + // nodes. This is a somewhat arbitrary choice, but experience shows that + // it is useful to make to make the selection "canonical" (if only for + // purposes of comparing selections). This is an ideal point of the code + // to do this operation, since all selection changes that result in a + // RANGE come through here before anyone uses it. + // TODO(editing-dev): Consider this canonicalization is really needed. + const EphemeralRangeTemplate<Strategy> minimal_range( + MostForwardCaretPosition(range.StartPosition()), + MostBackwardCaretPosition(range.EndPosition())); + if (selection.IsBaseFirst()) { + return typename SelectionTemplate<Strategy>::Builder() + .SetAsForwardSelection(minimal_range) + .Build(); + } + return typename SelectionTemplate<Strategy>::Builder() + .SetAsBackwardSelection(minimal_range) + .Build(); + } + + private: + template <typename Strategy> + static SelectionType ComputeSelectionType( + const EphemeralRangeTemplate<Strategy>& range) { + if (range.IsNull()) + return kNoSelection; + DCHECK(!NeedsLayoutTreeUpdate(range.StartPosition())) << range; + if (range.IsCollapsed()) + return kCaretSelection; + // TODO(editing-dev): Consider this canonicalization is really needed. + if (MostBackwardCaretPosition(range.StartPosition()) == + MostBackwardCaretPosition(range.EndPosition())) + return kCaretSelection; + return kRangeSelection; + } +}; + +SelectionInDOMTree SelectionAdjuster::AdjustSelectionType( + const SelectionInDOMTree& selection) { + return SelectionTypeAdjuster::AdjustSelection(selection); +} +SelectionInFlatTree SelectionAdjuster::AdjustSelectionType( + const SelectionInFlatTree& selection) { + return SelectionTypeAdjuster::AdjustSelection(selection); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/editing/selection_adjuster.h b/third_party/blink/renderer/core/editing/selection_adjuster.h index f1261cf..37c31e98 100644 --- a/third_party/blink/renderer/core/editing/selection_adjuster.h +++ b/third_party/blink/renderer/core/editing/selection_adjuster.h
@@ -33,6 +33,8 @@ const SelectionInDOMTree&); static SelectionInFlatTree AdjustSelectionToAvoidCrossingEditingBoundaries( const SelectionInFlatTree&); + static SelectionInDOMTree AdjustSelectionType(const SelectionInDOMTree&); + static SelectionInFlatTree AdjustSelectionType(const SelectionInFlatTree&); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/editing/selection_controller.cc b/third_party/blink/renderer/core/editing/selection_controller.cc index 176dd56..74fae13e 100644 --- a/third_party/blink/renderer/core/editing/selection_controller.cc +++ b/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -788,8 +788,7 @@ extent.LeftBoundaryOfBidiRun(base.BidiLevelOnRight()))) { return SelectionInFlatTree::Builder() .SetBaseAndExtent( - CreateVisiblePosition( - ToPositionInFlatTree(base.PositionAtLeftBoundaryOfBiDiRun())) + CreateVisiblePosition(base.PositionAtLeftBoundaryOfBiDiRun()) .DeepEquivalent(), visible_extent.DeepEquivalent()) .Build(); @@ -803,8 +802,7 @@ extent.RightBoundaryOfBidiRun(base.BidiLevelOnLeft()))) { return SelectionInFlatTree::Builder() .SetBaseAndExtent( - CreateVisiblePosition( - ToPositionInFlatTree(base.PositionAtRightBoundaryOfBiDiRun())) + CreateVisiblePosition(base.PositionAtRightBoundaryOfBiDiRun()) .DeepEquivalent(), visible_extent.DeepEquivalent()) .Build(); @@ -818,8 +816,7 @@ return SelectionInFlatTree::Builder() .SetBaseAndExtent( visible_base.DeepEquivalent(), - CreateVisiblePosition( - ToPositionInFlatTree(extent.PositionAtLeftBoundaryOfBiDiRun())) + CreateVisiblePosition(extent.PositionAtLeftBoundaryOfBiDiRun()) .DeepEquivalent()) .Build(); } @@ -830,8 +827,7 @@ return SelectionInFlatTree::Builder() .SetBaseAndExtent( visible_base.DeepEquivalent(), - CreateVisiblePosition( - ToPositionInFlatTree(extent.PositionAtRightBoundaryOfBiDiRun())) + CreateVisiblePosition(extent.PositionAtRightBoundaryOfBiDiRun()) .DeepEquivalent()) .Build(); }
diff --git a/third_party/blink/renderer/core/editing/visible_selection.cc b/third_party/blink/renderer/core/editing/visible_selection.cc index d9d9f606..a2aa495 100644 --- a/third_party/blink/renderer/core/editing/visible_selection.cc +++ b/third_party/blink/renderer/core/editing/visible_selection.cc
@@ -100,20 +100,6 @@ } template <typename Strategy> -static SelectionType ComputeSelectionType( - const EphemeralRangeTemplate<Strategy>& range) { - if (range.IsNull()) - return kNoSelection; - DCHECK(!NeedsLayoutTreeUpdate(range.StartPosition())) << range; - if (range.IsCollapsed()) - return kCaretSelection; - if (MostBackwardCaretPosition(range.StartPosition()) == - MostBackwardCaretPosition(range.EndPosition())) - return kCaretSelection; - return kRangeSelection; -} - -template <typename Strategy> VisibleSelectionTemplate<Strategy>::VisibleSelectionTemplate( const VisibleSelectionTemplate<Strategy>& other) : base_(other.base_), @@ -268,42 +254,13 @@ const SelectionTemplate<Strategy>& editing_adjusted_selection = SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries( shadow_adjusted_selection); - const EphemeralRangeTemplate<Strategy> editing_adjusted_range = - editing_adjusted_selection.ComputeRange(); - // TODO(editing-dev): Implement - // const SelectionTemplate<Strategy>& adjusted_selection = - // AdjustSelectionType(editing_adjusted_range); - const SelectionType selection_type = - ComputeSelectionType(editing_adjusted_range); - if (selection_type == kCaretSelection) { - return typename SelectionTemplate<Strategy>::Builder() - .Collapse(PositionWithAffinityTemplate<Strategy>( - editing_adjusted_range.StartPosition(), - passed_selection.Affinity())) - .Build(); - } - - DCHECK_EQ(selection_type, kRangeSelection); - // "Constrain" the selection to be the smallest equivalent range of - // nodes. This is a somewhat arbitrary choice, but experience shows that - // it is useful to make to make the selection "canonical" (if only for - // purposes of comparing selections). This is an ideal point of the code - // to do this operation, since all selection changes that result in a - // RANGE come through here before anyone uses it. - // TODO(yosin) Canonicalizing is good, but haven't we already done it - // (when we set these two positions to |VisiblePosition| - // |DeepEquivalent()|s above)? - const EphemeralRangeTemplate<Strategy> range( - MostForwardCaretPosition(editing_adjusted_range.StartPosition()), - MostBackwardCaretPosition(editing_adjusted_range.EndPosition())); - if (canonicalized_selection.IsBaseFirst()) { - return typename SelectionTemplate<Strategy>::Builder() - .SetAsForwardSelection(range) - .Build(); - } - return typename SelectionTemplate<Strategy>::Builder() - .SetAsBackwardSelection(range) - .Build(); + const SelectionTemplate<Strategy>& type_adjusted_selection = + SelectionAdjuster::AdjustSelectionType( + typename SelectionTemplate<Strategy>::Builder( + editing_adjusted_selection) + .SetAffinity(passed_selection.Affinity()) + .Build()); + return type_adjusted_selection; } template <typename Strategy>
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index 97e2c95f..2d3b21d 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -1062,7 +1062,7 @@ std::unique_ptr<blink::WebURLLoaderFactory> LocalFrameClientImpl::CreateURLLoaderFactory() { - return web_frame_->CreateURLLoaderFactory(); + return web_frame_->Client()->CreateURLLoaderFactory(); } service_manager::InterfaceProvider*
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index f58b973..41407a51b 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -143,6 +143,7 @@ #include "third_party/blink/renderer/platform/bindings/microtask.h" #include "third_party/blink/renderer/platform/cursor.h" #include "third_party/blink/renderer/platform/drag_image.h" +#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" @@ -4517,47 +4518,25 @@ } }; -TEST_P(ParameterizedWebFrameTest, ReloadWithOverrideURLPreservesState) { - const std::string first_url = "200-by-300.html"; - const std::string second_url = "content-width-1000.html"; - const std::string third_url = "very_tall_div.html"; +TEST_P(ParameterizedWebFrameTest, ReloadPreservesState) { + const std::string url = "200-by-300.html"; const float kPageScaleFactor = 1.1684f; const int kPageWidth = 120; const int kPageHeight = 100; - RegisterMockedHttpURLLoad(first_url); - RegisterMockedHttpURLLoad(second_url); - RegisterMockedHttpURLLoad(third_url); + RegisterMockedHttpURLLoad(url); ClearScrollStateOnCommitWebFrameClient client; FrameTestHelpers::WebViewHelper web_view_helper; - web_view_helper.InitializeAndLoad(base_url_ + first_url, &client); + web_view_helper.InitializeAndLoad(base_url_ + url, &client); web_view_helper.Resize(WebSize(kPageWidth, kPageHeight)); web_view_helper.LocalMainFrame()->SetScrollOffset( WebSize(kPageWidth / 4, kPageHeight / 4)); web_view_helper.GetWebView()->SetPageScaleFactor(kPageScaleFactor); // Reload the page and end up at the same url. State should not be propagated. - web_view_helper.GetWebView()->MainFrameImpl()->ReloadWithOverrideURL( - ToKURL(base_url_ + first_url), WebFrameLoadType::kReload); - FrameTestHelpers::PumpPendingRequestsForFrameToLoad( - web_view_helper.GetWebView()->MainFrame()); - EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().width); - EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().height); - EXPECT_EQ(1.0f, web_view_helper.GetWebView()->PageScaleFactor()); - - // Reload the page using the cache. State should not be propagated. - web_view_helper.GetWebView()->MainFrameImpl()->ReloadWithOverrideURL( - ToKURL(base_url_ + second_url), WebFrameLoadType::kReload); - FrameTestHelpers::PumpPendingRequestsForFrameToLoad( - web_view_helper.GetWebView()->MainFrame()); - EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().width); - EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().height); - EXPECT_EQ(1.0f, web_view_helper.GetWebView()->PageScaleFactor()); - - // Reload the page while bypassing the cache. State should not be propagated. - web_view_helper.GetWebView()->MainFrameImpl()->ReloadWithOverrideURL( - ToKURL(base_url_ + third_url), WebFrameLoadType::kReloadBypassingCache); + web_view_helper.GetWebView()->MainFrameImpl()->Reload( + WebFrameLoadType::kReload); FrameTestHelpers::PumpPendingRequestsForFrameToLoad( web_view_helper.GetWebView()->MainFrame()); EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().width); @@ -7692,9 +7671,11 @@ item.Initialize(); WebURL history_url(ToKURL(base_url_ + "white-1x1.png")); item.SetURLString(history_url.GetString()); - WebURLRequest request = - main_frame->RequestFromHistoryItem(item, mojom::FetchCacheMode::kDefault); - main_frame->Load(request, WebFrameLoadType::kBackForward, item, + HistoryItem* history_item = item; + ResourceRequest request = + history_item->GenerateResourceRequest(mojom::FetchCacheMode::kDefault); + main_frame->Load(WrappedResourceRequest(request), + WebFrameLoadType::kBackForward, item, kWebHistoryDifferentDocumentLoad, false, base::UnguessableToken::Create());
diff --git a/third_party/blink/renderer/core/frame/find_in_page.cc b/third_party/blink/renderer/core/frame/find_in_page.cc index da0b5f687..0447c2b 100644 --- a/third_party/blink/renderer/core/frame/find_in_page.cc +++ b/third_party/blink/renderer/core/frame/find_in_page.cc
@@ -229,11 +229,9 @@ } } -void WebLocalFrameImpl::ClearActiveFindMatch() { - find_in_page_->ClearActiveFindMatch(); -} - void FindInPage::ClearActiveFindMatch() { + // TODO(rakina): Do collapse selection as this currently does nothing. + frame_->ExecuteCommand(WebString::FromUTF8("CollapseSelection")); EnsureTextFinder().ClearActiveFindMatch(); } @@ -256,4 +254,13 @@ return *text_finder_; } +void FindInPage::BindToRequest( + mojom::blink::FindInPageAssociatedRequest request) { + binding_.Bind(std::move(request)); +} + +void FindInPage::Dispose() { + binding_.Close(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/find_in_page.h b/third_party/blink/renderer/core/frame/find_in_page.h index 8cc54e2f..21c3e40 100644 --- a/third_party/blink/renderer/core/frame/find_in_page.h +++ b/third_party/blink/renderer/core/frame/find_in_page.h
@@ -5,8 +5,12 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FIND_IN_PAGE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FIND_IN_PAGE_H_ +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h" +#include "third_party/blink/public/platform/interface_registry.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" namespace blink { @@ -16,10 +20,14 @@ struct WebFindOptions; struct WebFloatRect; -class FindInPage : public GarbageCollected<FindInPage> { +class FindInPage final : public GarbageCollectedFinalized<FindInPage>, + public mojom::blink::FindInPage { + USING_PRE_FINALIZER(FindInPage, Dispose); + public: - static FindInPage* Create(WebLocalFrameImpl& frame) { - return new FindInPage(frame); + static FindInPage* Create(WebLocalFrameImpl& frame, + InterfaceRegistry* interface_registry) { + return new FindInPage(frame, interface_registry); } void RequestFind(int identifier, @@ -48,7 +56,8 @@ void SetTickmarks(const WebVector<WebRect>&); - void ClearActiveFindMatch(); + // Clears the active find match in the frame, if one exists. + void ClearActiveFindMatch() override; TextFinder* GetTextFinder() const; @@ -56,19 +65,31 @@ // Otherwise creates it and then returns. TextFinder& EnsureTextFinder(); + void BindToRequest(mojom::blink::FindInPageAssociatedRequest request); + + void Dispose(); + void Trace(blink::Visitor* visitor) { visitor->Trace(text_finder_); visitor->Trace(frame_); } private: - FindInPage(WebLocalFrameImpl& frame) : frame_(&frame) {} + FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry) + : frame_(&frame), binding_(this) { + if (!interface_registry) + return; + interface_registry->AddAssociatedInterface(WTF::BindRepeating( + &FindInPage::BindToRequest, WrapWeakPersistent(this))); + } // Will be initialized after first call to ensureTextFinder(). Member<TextFinder> text_finder_; const Member<WebLocalFrameImpl> frame_; + mojo::AssociatedBinding<mojom::blink::FindInPage> binding_; + DISALLOW_COPY_AND_ASSIGN(FindInPage); };
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc index 094555f..bd7a833 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -120,10 +120,11 @@ const WebHistoryItem& item, WebHistoryLoadType load_type, mojom::FetchCacheMode cache_mode) { - WebURLRequest request = frame->RequestFromHistoryItem(item, cache_mode); - frame->Load(request, WebFrameLoadType::kBackForward, item, - kWebHistoryDifferentDocumentLoad, /*is_client_redirect=*/false, - base::UnguessableToken::Create()); + HistoryItem* history_item = item; + frame->Load( + WrappedResourceRequest(history_item->GenerateResourceRequest(cache_mode)), + WebFrameLoadType::kBackForward, item, kWebHistoryDifferentDocumentLoad, + /*is_client_redirect=*/false, base::UnguessableToken::Create()); PumpPendingRequestsForFrameToLoad(frame); }
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 891ebd1..60caa00 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -319,8 +319,8 @@ if (!loader_.GetDocumentLoader()->GetHistoryItem()) return; FrameLoadRequest request = FrameLoadRequest( - nullptr, loader_.ResourceRequestForReload(load_type, NullURL(), - client_redirect_policy)); + nullptr, + loader_.ResourceRequestForReload(load_type, client_redirect_policy)); request.SetClientRedirect(client_redirect_policy); loader_.Load(request, load_type); } else {
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 3d889cb..66b7e9b 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -3400,25 +3400,36 @@ if (!layer || layer->Client().ShouldThrottleRendering()) return; - if (layer->DrawsContent()) { - // TODO(trchen): Currently the GraphicsLayer hierarchy is still built - // during CompositingUpdate, and we have to clear them here to ensure no - // extraneous layers are still attached. In future we will disable all - // those layer hierarchy code so we won't need this line. - layer->PlatformLayer()->RemoveAllChildren(); - + WebLayer* contents_layer = layer->ContentsLayer(); + if (layer->DrawsContent() || contents_layer) { ScopedPaintChunkProperties scope(context.GetPaintController(), layer->GetPropertyTreeState(), *layer, DisplayItem::kForeignLayerWrapper); - RecordForeignLayer(context, *layer, DisplayItem::kForeignLayerWrapper, - layer->PlatformLayer(), - layer->GetOffsetFromTransformNode(), - RoundedIntSize(layer->Size())); + + if (layer->DrawsContent()) { + // TODO(trchen): Currently the GraphicsLayer hierarchy is still built + // during CompositingUpdate, and we have to clear them here to ensure no + // extraneous layers are still attached. In future we will disable all + // those layer hierarchy code so we won't need this line. + layer->PlatformLayer()->RemoveAllChildren(); + RecordForeignLayer(context, *layer, DisplayItem::kForeignLayerWrapper, + layer->PlatformLayer(), + layer->GetOffsetFromTransformNode(), + RoundedIntSize(layer->Size())); + } + if (contents_layer) { + auto position = contents_layer->GetPosition(); + auto size = contents_layer->Bounds(); + RecordForeignLayer(context, *layer, + DisplayItem::kForeignLayerContentsWrapper, + contents_layer, + layer->GetOffsetFromTransformNode() + + FloatSize(position.x(), position.y()), + IntSize(size.width(), size.height())); + } } - // TODO(trchen): layer->ContentLayer() should be collected too, - // but how do we derive their state? - + DCHECK(!layer->ContentsClippingMaskLayer()); for (const auto* child : layer->Children()) CollectDrawableLayersForLayerListRecursively(context, child); CollectDrawableLayersForLayerListRecursively(context, layer->MaskLayer()); @@ -5952,7 +5963,7 @@ // requires changing the UkmMetricNames enum. {"Compositing", "IntersectionObservation", "Paint", "PrePaint", "StyleAndLayout"}, - TimeDelta::FromSeconds(1))); + TimeDelta::FromSeconds(30))); } return *ukm_time_aggregator_; }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index dc84cbd8..9b1c5e89 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -914,22 +914,16 @@ void WebLocalFrameImpl::Reload(WebFrameLoadType load_type) { // TODO(clamy): Remove this function once RenderFrame calls load for all // requests. - ReloadWithOverrideURL(NullURL(), load_type); -} - -void WebLocalFrameImpl::ReloadWithOverrideURL(const WebURL& override_url, - WebFrameLoadType load_type) { - // TODO(clamy): Remove this function once RenderFrame calls load for all - // requests. DCHECK(GetFrame()); DCHECK(IsReloadLoadType(static_cast<FrameLoadType>(load_type))); - WebURLRequest request = RequestForReload(load_type, override_url); + ResourceRequest request = GetFrame()->Loader().ResourceRequestForReload( + static_cast<FrameLoadType>(load_type)); if (request.IsNull()) return; - request.SetRequestorOrigin( - WebSecurityOrigin(GetFrame()->GetDocument()->GetSecurityOrigin())); - Load(request, load_type, WebHistoryItem(), kWebHistoryDifferentDocumentLoad, - false, base::UnguessableToken::Create()); + request.SetRequestorOrigin(GetFrame()->GetDocument()->GetSecurityOrigin()); + Load(WrappedResourceRequest(request), load_type, WebHistoryItem(), + kWebHistoryDifferentDocumentLoad, false, + base::UnguessableToken::Create()); } void WebLocalFrameImpl::ReloadImage(const WebNode& web_node) { @@ -1760,7 +1754,7 @@ client_(client), local_frame_client_(LocalFrameClientImpl::Create(this)), autofill_client_(nullptr), - find_in_page_(FindInPage::Create(*this)), + find_in_page_(FindInPage::Create(*this, interface_registry)), input_events_scale_factor_for_emulation_(1), interface_registry_(interface_registry), input_method_controller_(*this), @@ -2043,23 +2037,6 @@ return GetFrame()->Loader().ShouldClose(is_reload); } -WebURLRequest WebLocalFrameImpl::RequestFromHistoryItem( - const WebHistoryItem& item, - mojom::FetchCacheMode cache_mode) const { - HistoryItem* history_item = item; - return WrappedResourceRequest( - history_item->GenerateResourceRequest(cache_mode)); -} - -WebURLRequest WebLocalFrameImpl::RequestForReload( - WebFrameLoadType load_type, - const WebURL& override_url) const { - DCHECK(GetFrame()); - ResourceRequest request = GetFrame()->Loader().ResourceRequestForReload( - static_cast<FrameLoadType>(load_type), override_url); - return WrappedResourceRequest(request); -} - void WebLocalFrameImpl::Load( const WebURLRequest& request, WebFrameLoadType web_frame_load_type, @@ -2370,11 +2347,6 @@ return frame_widget_; } -std::unique_ptr<WebURLLoaderFactory> -WebLocalFrameImpl::CreateURLLoaderFactory() { - return client_->CreateURLLoaderFactory(); -} - void WebLocalFrameImpl::CopyImageAt(const WebPoint& pos_in_viewport) { HitTestResult result = HitTestResultForVisualViewportPos(pos_in_viewport); if (!IsHTMLCanvasElement(result.InnerNodeOrImageMapImage()) &&
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index 9fccb40..1a7d04df 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -150,8 +150,6 @@ v8::Local<v8::Context> MainWorldScriptContext() const override; v8::Local<v8::Object> GlobalProxy() const override; void Reload(WebFrameLoadType) override; - void ReloadWithOverrideURL(const WebURL& override_url, - WebFrameLoadType) override; void ReloadImage(const WebNode&) override; void ReloadLoFiImages() override; void LoadRequest(const WebURLRequest&) override; @@ -263,10 +261,6 @@ WebFrame* FindFrameByName(const WebString& name) override; void SendPings(const WebURL& destination_url) override; bool DispatchBeforeUnloadEvent(bool) override; - WebURLRequest RequestFromHistoryItem(const WebHistoryItem&, - mojom::FetchCacheMode) const override; - WebURLRequest RequestForReload(WebFrameLoadType, - const WebURL&) const override; void Load(const WebURLRequest&, WebFrameLoadType, const WebHistoryItem&, @@ -332,7 +326,6 @@ void CopyImageAt(const WebPoint&) override; void SaveImageAt(const WebPoint&) override; void SetEngagementLevel(mojom::EngagementLevel) override; - void ClearActiveFindMatch() override; void UsageCountChromeLoadTimes(const WebString& metric) override; FrameScheduler* Scheduler() const override; scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override; @@ -438,8 +431,6 @@ void SetFrameWidget(WebFrameWidgetBase*); - std::unique_ptr<WebURLLoaderFactory> CreateURLLoaderFactory() override; - // TODO(dcheng): Remove this and make |FrameWidget()| always return something // useful. WebFrameWidgetBase* LocalRootFrameWidget();
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc index 32103a6..ce400a9 100644 --- a/third_party/blink/renderer/core/html/html_image_element.cc +++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -819,17 +819,4 @@ } } -bool HTMLImageElement::ShouldInvertColor() const { - return should_invert_color_; -} - -void HTMLImageElement::UpdateShouldInvertColor(bool value) { - if (should_invert_color_ != value) { - should_invert_color_ = value; - SetNeedsStyleRecalc(StyleChangeType::kLocalStyleChange, - StyleChangeReasonForTracing::Create( - StyleChangeReason::kPolicyViolation)); - } -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_image_element.h b/third_party/blink/renderer/core/html/html_image_element.h index 19d458ac..8f8524d 100644 --- a/third_party/blink/renderer/core/html/html_image_element.h +++ b/third_party/blink/renderer/core/html/html_image_element.h
@@ -136,12 +136,6 @@ FormAssociated* ToFormAssociatedOrNull() override { return this; }; void AssociateWith(HTMLFormElement*) override; - // When an image element violates feature policy optimized image policies, it - // should be rendered with inverted color. - // https://github.com/WICG/feature-policy/blob/gh-pages/policies/optimized-images.md - bool ShouldInvertColor() const; - void UpdateShouldInvertColor(bool); - protected: // Controls how an image element appears in the layout. See: // https://html.spec.whatwg.org/multipage/embedded-content.html#image-request
diff --git a/third_party/blink/renderer/core/html/html_image_loader.cc b/third_party/blink/renderer/core/html/html_image_loader.cc index f5ebd697..45bcc55 100644 --- a/third_party/blink/renderer/core/html/html_image_loader.cc +++ b/third_party/blink/renderer/core/html/html_image_loader.cc
@@ -75,30 +75,10 @@ bool load_error = cached_image->ErrorOccurred(); if (auto* image = ToHTMLImageElementOrNull(*element)) { - if (load_error) { + if (load_error) image->EnsureCollapsedOrFallbackContent(); - } else { + else image->EnsurePrimaryContent(); - // Check policies - if (auto* frame = image->GetDocument().GetFrame()) { - // Invert the image if the document does not have the - // 'legacy-image-formats' feature enabled, and the image is not one of - // the allowed formats. - if (!frame->IsFeatureEnabled( - mojom::FeaturePolicyFeature::kLegacyImageFormats)) { - if (!cached_image->IsAcceptableContentType()) - image->UpdateShouldInvertColor(true); - } - // Invert the image if the document does not have the - // 'image-compression' feature enabled and the image is not - // sufficiently-well-compressed. - if (!frame->IsFeatureEnabled( - mojom::FeaturePolicyFeature::kImageCompression)) { - if (!cached_image->IsAcceptableCompressionRatio()) - image->UpdateShouldInvertColor(true); - } - } - } } if (auto* input = ToHTMLInputElementOrNull(*element)) {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index c963902..d8ee5ccf 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -2485,6 +2485,16 @@ GetWebMediaPlayer()->RequestRemotePlaybackStop(); } +void HTMLMediaElement::FlingingStarted() { + if (GetWebMediaPlayer()) + GetWebMediaPlayer()->FlingingStarted(); +} + +void HTMLMediaElement::FlingingStopped() { + if (GetWebMediaPlayer()) + GetWebMediaPlayer()->FlingingStopped(); +} + void HTMLMediaElement::CloseMediaSource() { if (!media_source_) return;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index cbac044..f87d77f 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -192,6 +192,8 @@ void RequestRemotePlayback(); void RequestRemotePlaybackControl(); void RequestRemotePlaybackStop(); + void FlingingStarted(); + void FlingingStopped(); // statistics unsigned webkitAudioDecodedByteCount() const;
diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc index b9a98e2..9c7d8d61 100644 --- a/third_party/blink/renderer/core/input/scroll_manager.cc +++ b/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/platform/histogram.h" +#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/scroll/scroll_customization.h" namespace blink { @@ -282,6 +283,7 @@ } void ScrollManager::CustomizedScroll(ScrollState& scroll_state) { + TRACE_EVENT0("input", "ScrollManager::CustomizedScroll"); if (scroll_state.FullyConsumed()) return; @@ -356,6 +358,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollBegin( const WebGestureEvent& gesture_event) { + TRACE_EVENT0("input", "ScrollManager::handleGestureScrollBegin"); Document* document = frame_->GetDocument(); if (!document->GetLayoutView()) @@ -373,8 +376,11 @@ scroll_gesture_handling_node_ = frame_->GetDocument()->documentElement(); if (!scroll_gesture_handling_node_ || - !scroll_gesture_handling_node_->GetLayoutObject()) + !scroll_gesture_handling_node_->GetLayoutObject()) { + TRACE_EVENT_INSTANT0("input", "Dropping: No LayoutObject", + TRACE_EVENT_SCOPE_THREAD); return WebInputEventResult::kNotHandled; + } WebInputEventResult child_result = PassScrollGestureEvent( gesture_event, scroll_gesture_handling_node_->GetLayoutObject()); @@ -399,6 +405,10 @@ RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state, current_scroll_chain_); + TRACE_EVENT_INSTANT1("input", "Computed Scroll Chain", + TRACE_EVENT_SCOPE_THREAD, "length", + current_scroll_chain_.size()); + if (current_scroll_chain_.empty()) { // If a child has a non-empty scroll chain, we need to consider that instead // of simply returning WebInputEventResult::kNotHandled. @@ -419,10 +429,13 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate( const WebGestureEvent& gesture_event) { + TRACE_EVENT0("input", "ScrollManager::handleGestureScrollUpdate"); DCHECK_EQ(gesture_event.GetType(), WebInputEvent::kGestureScrollUpdate); Node* node = scroll_gesture_handling_node_.Get(); if (!node || !node->GetLayoutObject()) { + TRACE_EVENT_INSTANT0("input", "Lost scroll_gesture_handling_node", + TRACE_EVENT_SCOPE_THREAD); if (previous_gesture_scrolled_element_) { // When the scroll_gesture_handling_node_ gets deleted in the middle of // scrolling call HandleGestureScrollEvent to start scrolling a new node @@ -432,9 +445,14 @@ SynthesizeGestureScrollBegin(gesture_event); HandleGestureScrollEvent(scroll_begin); node = scroll_gesture_handling_node_.Get(); - if (!node || !node->GetLayoutObject()) + if (!node || !node->GetLayoutObject()) { + TRACE_EVENT_INSTANT0("input", "Failed to find new node", + TRACE_EVENT_SCOPE_THREAD); return WebInputEventResult::kNotHandled; + } } else { + TRACE_EVENT_INSTANT0("input", "No previously scrolled node", + TRACE_EVENT_SCOPE_THREAD); return WebInputEventResult::kNotHandled; } } @@ -463,8 +481,11 @@ return result; } - if (current_scroll_chain_.empty()) + if (current_scroll_chain_.empty()) { + TRACE_EVENT_INSTANT0("input", "Empty Scroll Chain", + TRACE_EVENT_SCOPE_THREAD); return WebInputEventResult::kNotHandled; + } std::unique_ptr<ScrollStateData> scroll_state_data = std::make_unique<ScrollStateData>(); @@ -538,6 +559,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollEnd( const WebGestureEvent& gesture_event) { + TRACE_EVENT0("input", "ScrollManager::handleGestureScrollEnd"); Node* node = scroll_gesture_handling_node_; if (node && node->GetLayoutObject()) { @@ -607,6 +629,8 @@ if (!frame_->View()) return WebInputEventResult::kNotHandled; + TRACE_EVENT0("input", "ScrollManager::handleGestureScrollEvent"); + Node* event_target = nullptr; Scrollbar* scrollbar = nullptr; if (gesture_event.GetType() != WebInputEvent::kGestureScrollBegin) { @@ -619,6 +643,9 @@ if (!document->GetLayoutView()) return WebInputEventResult::kNotHandled; + TRACE_EVENT_INSTANT0("input", "Retargeting Scroll", + TRACE_EVENT_SCOPE_THREAD); + LocalFrameView* view = frame_->View(); LayoutPoint view_point = view->RootFrameToContents( FlooredIntPoint(gesture_event.PositionInRootFrame()));
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 1e46e1b..1f1e3920 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -5528,6 +5528,12 @@ # The id of the context created. BrowserContextID browserContextId + # Returns all browser contexts created with `Target.createBrowserContext` method. + experimental command getBrowserContexts + returns + # An array of browser context ids. + array of BrowserContextID browserContextIds + # Creates a new page. command createTarget parameters @@ -5537,7 +5543,7 @@ optional integer width # Frame height in DIP (headless chrome only). optional integer height - # The browser context to create the page in (headless chrome only). + # The browser context to create the page in. optional BrowserContextID browserContextId # Whether BeginFrames for this target will be controlled via DevTools (headless chrome only, # not supported on MacOS yet, false by default). @@ -5554,12 +5560,11 @@ # Deprecated. deprecated optional TargetID targetId - # Deletes a BrowserContext, will fail of any open page uses it. + # Deletes a BrowserContext. All the belonging pages will be closed without calling their + # beforeunload hooks. experimental command disposeBrowserContext parameters BrowserContextID browserContextId - returns - boolean success # Returns information about a target. experimental command getTargetInfo
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc index 809e0f4..c5548c16 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -18,6 +18,7 @@ // Note that the spec says the initial value of m_lastThresholdIndex // should be -1, but since m_lastThresholdIndex is unsigned, we use a // different sentinel value. + last_is_visible_(false), last_threshold_index_(kMaxThresholdIndex - 1) { UpdateShouldReportRootBoundsAfterDomChange(); } @@ -72,16 +73,24 @@ // TODO(tkent): We can't use CHECK_LT due to a compile error. CHECK(new_threshold_index < kMaxThresholdIndex); - if (last_threshold_index_ != new_threshold_index) { + bool is_visible = false; + if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled() && + Observer()->trackVisibility()) { + // TODO(szager): Determine visibility. + } + + if (last_threshold_index_ != new_threshold_index || + last_is_visible_ != is_visible) { FloatRect snapped_root_bounds(geometry.RootRect()); FloatRect* root_bounds_pointer = should_report_root_bounds_ ? &snapped_root_bounds : nullptr; IntersectionObserverEntry* new_entry = new IntersectionObserverEntry( timestamp, new_visible_ratio, FloatRect(geometry.TargetRect()), root_bounds_pointer, FloatRect(geometry.IntersectionRect()), - geometry.DoesIntersect(), Target()); + geometry.DoesIntersect(), is_visible, Target()); Observer()->EnqueueIntersectionObserverEntry(*new_entry); SetLastThresholdIndex(new_threshold_index); + SetWasVisible(is_visible); } }
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.h b/third_party/blink/renderer/core/intersection_observer/intersection_observation.h index 1217ae43..1f364014d 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
@@ -33,14 +33,17 @@ private: void SetLastThresholdIndex(unsigned index) { last_threshold_index_ = index; } + void SetWasVisible(bool last_is_visible) { + last_is_visible_ = last_is_visible ? 1 : 0; + } Member<IntersectionObserver> observer_; WeakMember<Element> target_; unsigned should_report_root_bounds_ : 1; - - unsigned last_threshold_index_ : 30; - static const unsigned kMaxThresholdIndex = (unsigned)0x40000000; + unsigned last_is_visible_ : 1; + unsigned last_threshold_index_ : 29; + static const unsigned kMaxThresholdIndex = (unsigned)0x20000000; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc index ae9fc71..e604951 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
@@ -150,7 +150,12 @@ if (exception_state.HadException()) return nullptr; - return new IntersectionObserver(delegate, root, root_margin, thresholds); + bool track_visibility = false; + if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled()) + track_visibility = observer_init.trackVisibility(); + + return new IntersectionObserver(delegate, root, root_margin, thresholds, + track_visibility); } IntersectionObserver* IntersectionObserver::Create( @@ -168,18 +173,20 @@ const Vector<float>& thresholds, Document* document, EventCallback callback, + bool track_visibility, ExceptionState& exception_state) { IntersectionObserverDelegateImpl* intersection_observer_delegate = new IntersectionObserverDelegateImpl(document, std::move(callback)); return new IntersectionObserver(*intersection_observer_delegate, nullptr, - root_margin, thresholds); + root_margin, thresholds, track_visibility); } IntersectionObserver::IntersectionObserver( IntersectionObserverDelegate& delegate, Element* root, const Vector<Length>& root_margin, - const Vector<float>& thresholds) + const Vector<float>& thresholds, + bool track_visibility) : ContextClient(delegate.GetExecutionContext()), delegate_(&delegate), root_(root), @@ -188,7 +195,8 @@ right_margin_(kFixed), bottom_margin_(kFixed), left_margin_(kFixed), - root_is_implicit_(root ? 0 : 1) { + root_is_implicit_(root ? 0 : 1), + track_visibility_(track_visibility ? 1 : 0) { switch (root_margin.size()) { case 0: break;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer.h index 8301a33..3aca247 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
@@ -50,6 +50,7 @@ const Vector<float>& thresholds, Document*, EventCallback, + bool track_visbility = false, ExceptionState& = ASSERT_NO_EXCEPTION); static void ResumeSuspendedObservers(); @@ -63,6 +64,7 @@ Element* root() const { return root_.Get(); } String rootMargin() const; const Vector<float>& thresholds() const { return thresholds_; } + bool trackVisibility() const { return track_visibility_; } // An observer can either track intersections with an explicit root Element, // or with the the top-level frame's viewport (the "implicit root"). When @@ -100,7 +102,8 @@ explicit IntersectionObserver(IntersectionObserverDelegate&, Element*, const Vector<Length>& root_margin, - const Vector<float>& thresholds); + const Vector<float>& thresholds, + bool track_visibility); void ClearWeakMembers(Visitor*); // Returns false if this observer has an explicit root element which has been @@ -117,6 +120,7 @@ Length bottom_margin_; Length left_margin_; unsigned root_is_implicit_ : 1; + unsigned track_visibility_ : 1; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl b/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl index 180b996..fc1bd4494 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl
@@ -19,6 +19,7 @@ readonly attribute DOMString rootMargin; // https://github.com/WICG/IntersectionObserver/issues/114 readonly attribute FrozenArray<double> thresholds; + [RuntimeEnabled=IntersectionObserverV2] readonly attribute boolean trackVisibility; [RaisesException] void observe(Element target); [RaisesException] void unobserve(Element target); [RaisesException] void disconnect();
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.cc index 2ddfe3a..7707b151 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.cc
@@ -15,6 +15,7 @@ const FloatRect* root_bounds, const FloatRect& intersection_rect, bool is_intersecting, + bool is_visible, Element* target) : time_(time), intersection_ratio_(intersection_ratio), @@ -24,7 +25,8 @@ : nullptr), intersection_rect_(DOMRectReadOnly::FromFloatRect(intersection_rect)), target_(target), - is_intersecting_(is_intersecting) + is_intersecting_(is_intersecting), + is_visible_(is_visible) {}
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h index 95d6bcd..0805035 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h
@@ -25,6 +25,7 @@ const FloatRect* root_bounds, const FloatRect& intersection_rect, bool is_intersecting, + bool is_visible, Element*); double time() const { return time_; } @@ -33,6 +34,7 @@ DOMRectReadOnly* rootBounds() const { return root_bounds_; } DOMRectReadOnly* intersectionRect() const { return intersection_rect_; } bool isIntersecting() const { return is_intersecting_; } + bool isVisible() const { return is_visible_; } Element* target() const { return target_.Get(); } void Trace(blink::Visitor*) override; @@ -45,6 +47,7 @@ Member<DOMRectReadOnly> intersection_rect_; Member<Element> target_; bool is_intersecting_; + bool is_visible_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl b/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl index fb26cf2..ec82d861 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.idl
@@ -11,6 +11,7 @@ readonly attribute DOMRectReadOnly boundingClientRect; readonly attribute DOMRectReadOnly intersectionRect; readonly attribute boolean isIntersecting; + [RuntimeEnabled=IntersectionObserverV2] readonly attribute boolean isVisible; readonly attribute double intersectionRatio; readonly attribute Element target; };
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl b/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl index ef0de4ab..0dbb57a 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl
@@ -8,4 +8,5 @@ Element? root = null; DOMString rootMargin = "0px"; (double or sequence<double>) threshold = 0; + [RuntimeEnabled=IntersectionObserverV2] boolean trackVisibility = false; };
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc index 426e411..332f3879 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/time.h" @@ -234,4 +235,19 @@ EXPECT_TRUE(observer_delegate->LastIntersectionRect().IsEmpty()); } +TEST_F(IntersectionObserverTest, TrackVisibilityInit) { + ScopedIntersectionObserverV2ForTest iov2_enabled(true); + IntersectionObserverInit observer_init; + DummyExceptionStateForTesting exception_state; + TestIntersectionObserverDelegate* observer_delegate = + new TestIntersectionObserverDelegate(GetDocument()); + IntersectionObserver* observer = IntersectionObserver::Create( + observer_init, *observer_delegate, exception_state); + EXPECT_FALSE(observer->trackVisibility()); + observer_init.setTrackVisibility(true); + observer = IntersectionObserver::Create(observer_init, *observer_delegate, + exception_state); + EXPECT_TRUE(observer->trackVisibility()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index 3e07e42..49b5663 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -2148,11 +2148,11 @@ (!style.LogicalTop().IsAuto() && !style.LogicalBottom().IsAuto())); LayoutUnit stretched_flex_height(-1); - if (IsFlexItem()) - stretched_flex_height = - ToLayoutFlexibleBox(Parent()) - ->ChildLogicalHeightForPercentageResolution(*this); - + if (IsFlexItem()) { + const LayoutFlexibleBox* flex_box = ToLayoutFlexibleBox(Parent()); + if (flex_box->UseOverrideLogicalHeightForPerentageResolution(*this)) + stretched_flex_height = OverrideContentLogicalHeight(); + } if (stretched_flex_height != LayoutUnit(-1)) { available_height = stretched_flex_height; } else if (IsGridItem() && HasOverrideLogicalHeight()) {
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index 00ed0491..5ec22ee 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -51,7 +51,9 @@ #include "third_party/blink/renderer/core/layout/line/inline_iterator.h" #include "third_party/blink/renderer/core/layout/line/inline_text_box.h" #include "third_party/blink/renderer/core/layout/line/line_width.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h" #include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h" +#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h" #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h" #include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h" @@ -2659,6 +2661,20 @@ return FirstLineBox()->LogicalTop() + font_data->GetFontMetrics().Ascent(FirstRootBox()->BaselineType()); } + if (RuntimeEnabledFeatures::LayoutNGEnabled()) { + if (const NGPaintFragment* paint_fragment = PaintFragment()) { + NGBoxFragment box_fragment( + StyleRef().GetWritingMode(), + ToNGPhysicalBoxFragment(paint_fragment->PhysicalFragment())); + NGLineHeightMetrics metrics = + box_fragment.BaselineMetricsWithoutSynthesize( + {NGBaselineAlgorithmType::kFirstLine, + IsHorizontalWritingMode() ? kAlphabeticBaseline + : kIdeographicBaseline}); + if (!metrics.IsEmpty()) + return metrics.ascent; + } + } return LayoutUnit(-1); }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 3dcc368..c185a1de 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -3633,9 +3633,10 @@ LayoutBlock* block = ToLayoutBlock(cb); block->AddPercentHeightDescendant(const_cast<LayoutBox*>(this)); if (block->IsFlexItem()) { - stretched_height = - ToLayoutFlexibleBox(block->Parent()) - ->ChildLogicalHeightForPercentageResolution(*block); + const LayoutFlexibleBox* flex_box = + ToLayoutFlexibleBox(block->Parent()); + if (flex_box->UseOverrideLogicalHeightForPerentageResolution(*block)) + stretched_height = block->OverrideContentLogicalHeight(); } else if (block->IsGridItem() && block->HasOverrideLogicalHeight() && !has_perpendicular_containing_block) { stretched_height = block->OverrideContentLogicalHeight(); @@ -3740,11 +3741,9 @@ } if (IsFlexItem()) { - LayoutFlexibleBox& flex_box = ToLayoutFlexibleBox(*Parent()); - LayoutUnit stretched_height = - flex_box.ChildLogicalHeightForPercentageResolution(*this); - if (stretched_height != LayoutUnit(-1)) - return stretched_height; + const LayoutFlexibleBox& flex_box = ToLayoutFlexibleBox(*Parent()); + if (flex_box.UseOverrideLogicalHeightForPerentageResolution(*this)) + return OverrideContentLogicalHeight(); } if (h.IsPercentOrCalc() && IsOutOfFlowPositioned()) {
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index c2f6015..712392e 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -678,9 +678,8 @@ if (logical_height_length.IsPercentOrCalc() && cb && IsBox()) cb->AddPercentHeightDescendant(const_cast<LayoutBox*>(ToLayoutBox(this))); if (this_box && this_box->IsFlexItem()) { - LayoutFlexibleBox& flex_box = ToLayoutFlexibleBox(*Parent()); - if (flex_box.ChildLogicalHeightForPercentageResolution(*this_box) != - LayoutUnit(-1)) + const LayoutFlexibleBox& flex_box = ToLayoutFlexibleBox(*Parent()); + if (flex_box.UseOverrideLogicalHeightForPerentageResolution(*this_box)) return false; } if (this_box && this_box->IsGridItem() &&
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 952fb88..5afeba3e 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -1119,17 +1119,17 @@ return sizes; } -LayoutUnit LayoutFlexibleBox::CrossSizeForPercentageResolution( - const LayoutBox& child) { +bool LayoutFlexibleBox::CrossSizeIsDefiniteForPercentageResolution( + const LayoutBox& child) const { if (FlexLayoutAlgorithm::AlignmentForChild(StyleRef(), child.StyleRef()) != ItemPosition::kStretch) - return LayoutUnit(-1); + return false; // Here we implement https://drafts.csswg.org/css-flexbox/#algo-stretch if (HasOrthogonalFlow(child) && child.HasOverrideLogicalWidth()) - return child.OverrideContentLogicalWidth(); + return true; if (!HasOrthogonalFlow(child) && child.HasOverrideLogicalHeight()) - return child.OverrideContentLogicalHeight(); + return true; // We don't currently implement the optimization from // https://drafts.csswg.org/css-flexbox/#definite-sizes case 1. While that @@ -1137,39 +1137,36 @@ // definite size, which itself is not cheap. We can consider implementing it // at a later time. (The correctness is ensured by redoing layout in // applyStretchAlignmentToChild) - return LayoutUnit(-1); + return false; } -LayoutUnit LayoutFlexibleBox::MainSizeForPercentageResolution( - const LayoutBox& child) { +bool LayoutFlexibleBox::MainSizeIsDefiniteForPercentageResolution( + const LayoutBox& child) const { // This function implements section 9.8. Definite and Indefinite Sizes, case // 2) of the flexbox spec. // We need to check for the flexbox to have a definite main size, and for the // flex item to have a definite flex basis. const Length& flex_basis = FlexBasisForChild(child); if (!MainAxisLengthIsDefinite(child, flex_basis)) - return LayoutUnit(-1); + return false; if (!flex_basis.IsPercentOrCalc()) { // If flex basis had a percentage, our size is guaranteed to be definite or // the flex item's size could not be definite. Otherwise, we make up a // percentage to check whether we have a definite size. if (!MainAxisLengthIsDefinite(child, Length(0, kPercent))) - return LayoutUnit(-1); + return false; } if (HasOrthogonalFlow(child)) - return child.HasOverrideLogicalHeight() - ? child.OverrideContentLogicalHeight() - : LayoutUnit(-1); - return child.HasOverrideLogicalWidth() ? child.OverrideContentLogicalWidth() - : LayoutUnit(-1); + return child.HasOverrideLogicalHeight(); + return child.HasOverrideLogicalWidth(); } -LayoutUnit LayoutFlexibleBox::ChildLogicalHeightForPercentageResolution( - const LayoutBox& child) { +bool LayoutFlexibleBox::UseOverrideLogicalHeightForPerentageResolution( + const LayoutBox& child) const { if (!HasOrthogonalFlow(child)) - return CrossSizeForPercentageResolution(child); - return MainSizeForPercentageResolution(child); + return CrossSizeIsDefiniteForPercentageResolution(child); + return MainSizeIsDefiniteForPercentageResolution(child); } LayoutUnit LayoutFlexibleBox::AdjustChildSizeForAspectRatioCrossAxisMinAndMax(
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.h b/third_party/blink/renderer/core/layout/layout_flexible_box.h index 9e78323..33b1aa9 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.h +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.h
@@ -75,9 +75,14 @@ const OrderIterator& GetOrderIterator() const { return order_iterator_; } - LayoutUnit CrossSizeForPercentageResolution(const LayoutBox& child); - LayoutUnit MainSizeForPercentageResolution(const LayoutBox& child); - LayoutUnit ChildLogicalHeightForPercentageResolution(const LayoutBox& child); + // These three functions are used when resolving percentages against a + // flex item's logical height. In flexbox, sometimes a logical height + // should be considered definite even though it normally shouldn't be, + // and these functions implement that logic. + bool CrossSizeIsDefiniteForPercentageResolution(const LayoutBox& child) const; + bool MainSizeIsDefiniteForPercentageResolution(const LayoutBox& child) const; + bool UseOverrideLogicalHeightForPerentageResolution( + const LayoutBox& child) const; void ClearCachedMainSizeForChild(const LayoutBox& child);
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc index 3b33eee..4c1bf82 100644 --- a/third_party/blink/renderer/core/layout/layout_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -39,17 +39,48 @@ #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h" #include "third_party/blink/renderer/core/paint/image_painter.h" +#include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/svg/graphics/svg_image.h" +#include "third_party/blink/renderer/platform/feature_policy/feature_policy.h" namespace blink { +namespace { + +void CheckForOptimizedImagePolicy(const LocalFrame& frame, + LayoutImage* layout_image, + ImageResourceContent* new_image) { + // Invert the image if the document does not have the 'legacy-image-formats' + // feature enabled, and the image is not one of the allowed formats. + if (IsSupportedInFeaturePolicy( + mojom::FeaturePolicyFeature::kLegacyImageFormats) && + !frame.IsFeatureEnabled( + mojom::FeaturePolicyFeature::kLegacyImageFormats)) { + if (!new_image->IsAcceptableContentType()) { + layout_image->UpdateShouldInvertColor(true); + return; + } + } + // Invert the image if the document does not have the image-compression' + // feature enabled and the image is not sufficiently-well-compressed. + if (IsSupportedInFeaturePolicy( + mojom::FeaturePolicyFeature::kImageCompression) && + !frame.IsFeatureEnabled(mojom::FeaturePolicyFeature::kImageCompression)) { + if (!new_image->IsAcceptableCompressionRatio()) + layout_image->UpdateShouldInvertColor(true); + } +} + +} // namespace + using namespace HTMLNames; LayoutImage::LayoutImage(Element* element) : LayoutReplaced(element, LayoutSize()), did_increment_visually_non_empty_pixel_count_(false), is_generated_content_(false), - image_device_pixel_ratio_(1.0f) {} + image_device_pixel_ratio_(1.0f), + should_invert_color_(false) {} LayoutImage* LayoutImage::CreateAnonymous(PseudoElement& pseudo) { LayoutImage* image = new LayoutImage(nullptr); @@ -197,6 +228,12 @@ InvalidateBackgroundObscurationStatus(); + // Check for optimized image policies. + if (View() && View()->GetFrameView()) { + CheckForOptimizedImagePolicy(View()->GetFrameView()->GetFrame(), this, + new_image); + } + if (new_image == image_resource_->CachedImage()) { // tell any potential compositing layers // that the image is done and they can reference it directly. @@ -352,4 +389,18 @@ return ToSVGImage(image)->EmbeddedReplacedContent(); } +bool LayoutImage::ShouldInvertColor() const { + return should_invert_color_; +} + +void LayoutImage::UpdateShouldInvertColor(bool value) { + if (should_invert_color_ != value) { + should_invert_color_ = value; + SetNeedsPaintPropertyUpdate(); + // If composited image, update compositing layer. + if (Layer()) + Layer()->SetNeedsCompositingInputsUpdate(); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_image.h b/third_party/blink/renderer/core/layout/layout_image.h index d2e24d9..f43982b 100644 --- a/third_party/blink/renderer/core/layout/layout_image.h +++ b/third_party/blink/renderer/core/layout/layout_image.h
@@ -87,6 +87,12 @@ const char* GetName() const override { return "LayoutImage"; } + // When an image element violates feature policy optimized image policies, it + // should be rendered with inverted color. + // https://github.com/WICG/feature-policy/blob/gh-pages/policies/optimized-images.md + bool ShouldInvertColor() const; + void UpdateShouldInvertColor(bool); + protected: bool NeedsPreferredWidthsRecalculation() const final; LayoutReplaced* EmbeddedReplacedContent() const; @@ -147,6 +153,8 @@ // This field stores whether this image is generated with 'content'. bool is_generated_content_; float image_device_pixel_ratio_; + + bool should_invert_color_; }; DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutImage, IsLayoutImage());
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index a711c24..28acc6f2 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1460,6 +1460,10 @@ // |ancestor| itself if |ancestor| scrolls overflow. // The output rect is suitable for purposes such as paint invalidation. // + // The ancestor can be nullptr which, if |this| is not the root view, will map + // the rect to the main frame's space which includes the root view's scroll + // and clip. This is even true if the main frame is remote. + // // If visualRectFlags has the EdgeInclusive bit set, clipping operations will // use/ LayoutRect::inclusiveIntersect, and the return value of // inclusiveIntersect will be propagated to the return value of this method.
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index fd1500b..c78ee35 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/text/bidi_resolver.h" +#include "third_party/blink/renderer/platform/text/capitalize.h" #include "third_party/blink/renderer/platform/text/character.h" #include "third_party/blink/renderer/platform/text/hyphenation.h" #include "third_party/blink/renderer/platform/text/text_break_iterator.h" @@ -112,51 +113,6 @@ int last_typed_character_offset_; }; -static void MakeCapitalized(String* string, UChar previous) { - if (string->IsNull()) - return; - - unsigned length = string->length(); - const StringImpl& input = *string->Impl(); - - CHECK_LT(length, std::numeric_limits<unsigned>::max()); - StringBuffer<UChar> string_with_previous(length + 1); - string_with_previous[0] = - previous == kNoBreakSpaceCharacter ? kSpaceCharacter : previous; - for (unsigned i = 1; i < length + 1; i++) { - // Replace   with a real space since ICU no longer treats   as a - // word separator. - if (input[i - 1] == kNoBreakSpaceCharacter) - string_with_previous[i] = kSpaceCharacter; - else - string_with_previous[i] = input[i - 1]; - } - - TextBreakIterator* boundary = - WordBreakIterator(string_with_previous.Characters(), length + 1); - if (!boundary) - return; - - StringBuilder result; - result.ReserveCapacity(length); - - int32_t end_of_word; - int32_t start_of_word = boundary->first(); - for (end_of_word = boundary->next(); end_of_word != kTextBreakDone; - start_of_word = end_of_word, end_of_word = boundary->next()) { - if (start_of_word) { // Ignore first char of previous string - result.Append( - input[start_of_word - 1] == kNoBreakSpaceCharacter - ? kNoBreakSpaceCharacter - : WTF::Unicode::ToTitleCase(string_with_previous[start_of_word])); - } - for (int i = start_of_word + 1; i < end_of_word; i++) - result.Append(input[i - 1]); - } - - *string = result.ToString(); -} - LayoutText::LayoutText(Node* node, scoped_refptr<StringImpl> str) : LayoutObject(node), has_tab_(false), @@ -1717,7 +1673,7 @@ case ETextTransform::kNone: break; case ETextTransform::kCapitalize: - MakeCapitalized(&text, previous_character); + text = Capitalize(text, previous_character); break; case ETextTransform::kUppercase: text = text.UpperUnicode(style->Locale());
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc index 6307baeb..a4fa84b2 100644 --- a/third_party/blink/renderer/core/layout/layout_view.cc +++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -440,6 +440,13 @@ transform_state.Move(OffsetForFixedPosition()); } +bool LayoutView::ShouldClipOverflow() const { + bool is_main_frame = GetFrameView()->GetFrame().IsMainFrame(); + if (is_main_frame && !GetDocument().GetSettings()->GetMainFrameClipsContent()) + return false; + return LayoutBox::ShouldClipOverflow(); +} + void LayoutView::ComputeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutPoint&) const { // Record the entire size of the contents of the frame. Note that we don't
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h index df11eaf..a60ea33 100644 --- a/third_party/blink/renderer/core/layout/layout_view.h +++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -259,6 +259,7 @@ void MapAncestorToLocal(const LayoutBoxModelObject*, TransformState&, MapCoordinatesFlags) const override; + bool ShouldClipOverflow() const final; void ComputeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layer_offset) const override;
diff --git a/third_party/blink/renderer/core/layout/line/inline_box.h b/third_party/blink/renderer/core/layout/line/inline_box.h index ddc8753..ae29ffb 100644 --- a/third_party/blink/renderer/core/layout/line/inline_box.h +++ b/third_party/blink/renderer/core/layout/line/inline_box.h
@@ -202,9 +202,6 @@ InlineBox* PrevLeafChild() const; // Helper functions for editing and hit-testing code. - // FIXME: These two functions should be moved to RenderedPosition once the - // code to convert between Position and inline box, offset pair is moved to - // RenderedPosition. InlineBox* NextLeafChildIgnoringLineBreak() const; InlineBox* PrevLeafChildIgnoringLineBreak() const;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h index f3111c7..2abfb2f 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -6,6 +6,7 @@ #define NGInlineItem_h #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h" #include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h" #include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" @@ -172,6 +173,25 @@ DCHECK_LE(offset, end_offset_); } +// Represents a text content with a list of NGInlineItem. A node may have an +// additional NGInlineItemsData for ::first-line pseudo element. +struct CORE_EXPORT NGInlineItemsData { + // Text content for all inline items represented by a single NGInlineNode. + // Encoded either as UTF-16 or latin-1 depending on the content. + String text_content; + Vector<NGInlineItem> items; + + // The DOM to text content offset mapping of this inline node. + std::unique_ptr<NGOffsetMapping> offset_mapping; + + void AssertOffset(unsigned index, unsigned offset) const { + items[index].AssertOffset(offset); + } + void AssertEndOffset(unsigned index, unsigned offset) const { + items[index].AssertEndOffset(offset); + } +}; + } // namespace blink #endif // NGInlineItem_h
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc index 74e3e3c..43cdd7b 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
@@ -19,14 +19,14 @@ : item(item), item_index(index), start_offset(start), end_offset(end) {} void NGLineInfo::SetLineStyle(const NGInlineNode& node, + const NGInlineItemsData& items_data, const NGConstraintSpace& constraint_space, bool is_first_line, + bool use_first_line_style, bool is_after_forced_break) { - LayoutObject* layout_object = node.GetLayoutObject(); - use_first_line_style_ = - is_first_line && - layout_object->GetDocument().GetStyleEngine().UsesFirstLineRules(); - line_style_ = layout_object->Style(use_first_line_style_); + use_first_line_style_ = use_first_line_style; + items_data_ = &items_data; + line_style_ = node.GetLayoutObject()->Style(use_first_line_style_); if (line_style_->ShouldUseTextIndent(is_first_line, is_after_forced_break)) { // 'text-indent' applies to block container, and percentage is of its
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h index 401e52a..514ae110 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
@@ -19,6 +19,8 @@ class NGInlineItem; class NGInlineNode; +struct NGInlineItemsData; + // The result of measuring NGInlineItem. // // This is a transient context object only while building line boxes. @@ -106,14 +108,21 @@ NGLineInfo() = default; explicit NGLineInfo(size_t capacity) : results_(capacity) {} + const NGInlineItemsData& ItemsData() const { + DCHECK(items_data_); + return *items_data_; + } + // The style to use for the line. const ComputedStyle& LineStyle() const { DCHECK(line_style_); return *line_style_; } void SetLineStyle(const NGInlineNode&, + const NGInlineItemsData&, const NGConstraintSpace&, - bool is_first_line, + bool is_first_formatted_line, + bool use_first_line_style, bool is_after_forced_break); // Use ::first-line style if true. @@ -158,6 +167,7 @@ void SetLineEndFragment(scoped_refptr<NGPhysicalTextFragment>); private: + const NGInlineItemsData* items_data_ = nullptr; const ComputedStyle* line_style_ = nullptr; NGInlineItemResults results_; scoped_refptr<NGPhysicalTextFragment> line_end_fragment_;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc index a64b7fa..f2c0b8c 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -127,7 +127,7 @@ DCHECK(break_token->UseFirstLineStyle()); // Compute which tags are not closed at the beginning of this line. - const Vector<NGInlineItem>& items = Node().Items(); + const Vector<NGInlineItem>& items = line_info.ItemsData().items; Vector<const NGInlineItem*, 16> open_items; for (unsigned i = 0; i < break_token->ItemIndex(); i++) { const NGInlineItem& item = items[i]; @@ -191,12 +191,13 @@ baseline_type_); } - text_builder.SetItem(NGPhysicalTextFragment::kNormalText, &item_result, + text_builder.SetItem(NGPhysicalTextFragment::kNormalText, + line_info->ItemsData(), &item_result, box->text_height); line_box_.AddChild(text_builder.ToTextFragment(), box->text_top, item_result.inline_size, item.BidiLevel()); } else if (item.Type() == NGInlineItem::kControl) { - PlaceControlItem(item, &item_result, box); + PlaceControlItem(item, *line_info, &item_result, box); } else if (item.Type() == NGInlineItem::kOpenTag) { box = HandleOpenTag(item, item_result); } else if (item.Type() == NGInlineItem::kCloseTag) { @@ -301,12 +302,13 @@ } void NGInlineLayoutAlgorithm::PlaceControlItem(const NGInlineItem& item, + const NGLineInfo& line_info, NGInlineItemResult* item_result, NGInlineBoxState* box) { DCHECK_EQ(item.Type(), NGInlineItem::kControl); DCHECK_EQ(item.Length(), 1u); DCHECK(!item.TextShapeResult()); - UChar character = Node().Text()[item.StartOffset()]; + UChar character = line_info.ItemsData().text_content[item.StartOffset()]; NGPhysicalTextFragment::NGTextType type; switch (character) { case kNewlineCharacter: @@ -334,7 +336,8 @@ NGTextFragmentBuilder text_builder(Node(), ConstraintSpace().GetWritingMode()); - text_builder.SetItem(type, item_result, box->text_height); + text_builder.SetItem(type, line_info.ItemsData(), item_result, + box->text_height); line_box_.AddChild(text_builder.ToTextFragment(), box->text_top, item_result->inline_size, item.BidiLevel()); } @@ -463,7 +466,9 @@ // Construct the line text to compute spacing for. String line_text = - Node().Text(line_info->StartOffset(), align.end_offset).ToString(); + StringView(line_info->ItemsData().text_content, line_info->StartOffset(), + align.end_offset - line_info->StartOffset()) + .ToString(); // Append a hyphen if the last word is hyphenated. The hyphen is in // |ShapeResult|, but not in text. |ShapeResultSpacing| needs the text that @@ -575,7 +580,7 @@ // If we are an empty inline, we don't have to run the full algorithm, we can // return now as we should have positioned all of our floats. if (is_empty_inline) { - DCHECK_EQ(handled_item_index, Node().Items().size()); + DCHECK_EQ(handled_item_index, Node().ItemsData(false).items.size()); container_builder_.SwapPositionedFloats(&positioned_floats_); container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut()); @@ -685,7 +690,7 @@ // TODO(ikilpatrick): Do we need to always add the OOFs here? unsigned NGInlineLayoutAlgorithm::PositionLeadingItems( NGExclusionSpace* exclusion_space) { - const Vector<NGInlineItem>& items = Node().Items(); + const Vector<NGInlineItem>& items = Node().ItemsData(false).items; bool is_empty_inline = Node().IsEmptyInline(); LayoutUnit bfc_line_offset = ConstraintSpace().BfcOffset().line_offset;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h index b0c9a2e..b714128 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -59,6 +59,7 @@ void BidiReorder(); void PlaceControlItem(const NGInlineItem&, + const NGLineInfo&, NGInlineItemResult*, NGInlineBoxState*); void PlaceGeneratedContent(scoped_refptr<NGPhysicalFragment>,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc index 29dfb0a..51831f7 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -183,13 +183,29 @@ return GetDocument().InLineHeightQuirksMode(); } +bool NGInlineNode::CanContainFirstFormattedLine() const { + // TODO(kojii): In LayoutNG, leading OOF creates an anonymous block box, + // and that |LayoutBlockFlow::CanContainFirstFormattedLine()| does not work. + // crbug.com/734554 + LayoutObject* layout_object = GetLayoutBlockFlow(); + if (!layout_object->IsAnonymousBlock()) + return true; + for (;;) { + layout_object = layout_object->PreviousSibling(); + if (!layout_object) + return true; + if (!layout_object->IsFloatingOrOutOfFlowPositioned()) + return false; + } +} + NGInlineNodeData* NGInlineNode::MutableData() { return ToLayoutBlockFlow(box_)->GetNGInlineNodeData(); } bool NGInlineNode::IsPrepareLayoutFinished() const { const NGInlineNodeData* data = ToLayoutBlockFlow(box_)->GetNGInlineNodeData(); - return data && !data->text_content_.IsNull(); + return data && !data->text_content.IsNull(); } const NGInlineNodeData& NGInlineNode::Data() const { @@ -198,13 +214,6 @@ return *ToLayoutBlockFlow(box_)->GetNGInlineNodeData(); } -const Vector<NGInlineItem>& NGInlineNode::Items(bool is_first_line) const { - const NGInlineNodeData& data = Data(); - if (!is_first_line || !data.first_line_items_) - return data.items_; - return *data.first_line_items_; -} - void NGInlineNode::InvalidatePrepareLayoutForTest() { GetLayoutBlockFlow()->ResetNGInlineNodeData(); DCHECK(!IsPrepareLayoutFinished()); @@ -228,6 +237,7 @@ CollectInlines(data, previous_data.get()); SegmentText(data); ShapeText(data, previous_data.get()); + ShapeTextForFirstLineIfNeeded(data); AssociateItemsWithInlines(data); DCHECK_EQ(data, MutableData()); @@ -236,10 +246,10 @@ #if DCHECK_IS_ON() // ComputeOffsetMappingIfNeeded() runs some integrity checks as part of // creating offset mapping. Run the check, and discard the result. - DCHECK(!data->offset_mapping_); + DCHECK(!data->offset_mapping); ComputeOffsetMappingIfNeeded(); - DCHECK(data->offset_mapping_); - data->offset_mapping_.reset(); + DCHECK(data->offset_mapping); + data->offset_mapping.reset(); #endif } @@ -252,7 +262,7 @@ DCHECK(!GetLayoutBlockFlow()->GetDocument().NeedsLayoutTreeUpdate()); NGInlineNodeData* data = MutableData(); - if (!data->offset_mapping_) { + if (!data->offset_mapping) { // TODO(xiaochengh): ComputeOffsetMappingIfNeeded() discards the // NGInlineItems and text content built by |builder|, because they are // already there in NGInlineNodeData. For efficiency, we should make @@ -264,18 +274,18 @@ // The trailing space of the text for offset mapping may be removed. If not, // share the string instance. - if (text == data->text_content_) - text = data->text_content_; + if (text == data->text_content) + text = data->text_content; // TODO(xiaochengh): This doesn't compute offset mapping correctly when // text-transform CSS property changes text length. NGOffsetMappingBuilder& mapping_builder = builder.GetOffsetMappingBuilder(); mapping_builder.SetDestinationString(text); - data->offset_mapping_ = + data->offset_mapping = std::make_unique<NGOffsetMapping>(mapping_builder.Build()); } - return data->offset_mapping_.get(); + return data->offset_mapping.get(); } // Depth-first-scan of all LayoutInline and LayoutText nodes that make up this @@ -284,23 +294,23 @@ // string to allow bidi resolution and shaping of the entire block. void NGInlineNode::CollectInlines(NGInlineNodeData* data, NGInlineNodeData* previous_data) { - DCHECK(data->text_content_.IsNull()); - DCHECK(data->items_.IsEmpty()); + DCHECK(data->text_content.IsNull()); + DCHECK(data->items.IsEmpty()); LayoutBlockFlow* block = GetLayoutBlockFlow(); block->WillCollectInlines(); String* previous_text = - previous_data ? &previous_data->text_content_ : nullptr; - NGInlineItemsBuilder builder(&data->items_); + previous_data ? &previous_data->text_content : nullptr; + NGInlineItemsBuilder builder(&data->items); CollectInlinesInternal(block, &builder, previous_text); - data->text_content_ = builder.ToString(); + data->text_content = builder.ToString(); // Set |is_bidi_enabled_| for all UTF-16 strings for now, because at this // point the string may or may not contain RTL characters. // |SegmentText()| will analyze the text and reset |is_bidi_enabled_| if it // doesn't contain any RTL characters. data->is_bidi_enabled_ = - !data->text_content_.Is8Bit() || builder.HasBidiControls(); + !data->text_content.Is8Bit() || builder.HasBidiControls(); data->is_empty_inline_ = builder.IsEmptyInline(); } @@ -311,8 +321,8 @@ } NGBidiParagraph bidi; - data->text_content_.Ensure16Bit(); - if (!bidi.SetParagraph(data->text_content_, Style())) { + data->text_content.Ensure16Bit(); + if (!bidi.SetParagraph(data->text_content, Style())) { // On failure, give up bidi resolving and reordering. data->is_bidi_enabled_ = false; data->SetBaseDirection(TextDirection::kLtr); @@ -327,9 +337,9 @@ return; } - Vector<NGInlineItem>& items = data->items_; + Vector<NGInlineItem>& items = data->items; unsigned item_index = 0; - for (unsigned start = 0; start < data->text_content_.length();) { + for (unsigned start = 0; start < data->text_content.length();) { UBiDiLevel level; unsigned end = bidi.GetLogicalRun(start, &level); DCHECK_EQ(items[item_index].start_offset_, start); @@ -347,14 +357,12 @@ #endif } -void NGInlineNode::ShapeText(NGInlineNodeData* data, - NGInlineNodeData* previous_data) { +void NGInlineNode::ShapeText(NGInlineItemsData* data, + NGInlineItemsData* previous_data) { // TODO(eae): Add support for shaping latin-1 text? - data->text_content_.Ensure16Bit(); - ShapeText(data->text_content_, &data->items_, - previous_data ? &previous_data->text_content_ : nullptr); - - ShapeTextForFirstLineIfNeeded(data); + data->text_content.Ensure16Bit(); + ShapeText(data->text_content, &data->items, + previous_data ? &previous_data->text_content : nullptr); } void NGInlineNode::ShapeText(const String& text_content, @@ -485,9 +493,13 @@ if (block_style == first_line_style) return; - auto first_line_items = std::make_unique<Vector<NGInlineItem>>(); - first_line_items->AppendVector(data->items_); - for (auto& item : *first_line_items) { + auto first_line_items = std::make_unique<NGInlineItemsData>(); + // TODO(kojii): Support 'text-transform' to change the text_content. + // When the text changes, offsets in items are also changed. This might need + // to change this function a bit drastically. + first_line_items->text_content = data->text_content; + first_line_items->items.AppendVector(data->items); + for (auto& item : first_line_items->items) { if (item.style_) { DCHECK(item.layout_object_); item.style_ = item.layout_object_->FirstLineStyle(); @@ -498,16 +510,15 @@ // Re-shape if the font is different. const Font& font = block_style->GetFont(); const Font& first_line_font = first_line_style->GetFont(); - if (&font != &first_line_font && font != first_line_font) { - ShapeText(data->text_content_, first_line_items.get(), nullptr); - } + if (&font != &first_line_font && font != first_line_font) + ShapeText(first_line_items.get()); data->first_line_items_ = std::move(first_line_items); } void NGInlineNode::AssociateItemsWithInlines(NGInlineNodeData* data) { LayoutObject* last_object = nullptr; - for (auto& item : data->items_) { + for (auto& item : data->items) { LayoutObject* object = item.GetLayoutObject(); if (object && object->IsLayoutNGText()) { LayoutNGText* layout_text = ToLayoutNGText(object); @@ -656,7 +667,7 @@ void NGInlineNode::CheckConsistency() const { #if DCHECK_IS_ON() - const Vector<NGInlineItem>& items = Data().items_; + const Vector<NGInlineItem>& items = Data().items; for (const NGInlineItem& item : items) { DCHECK(!item.GetLayoutObject() || !item.Style() || item.Style() == item.GetLayoutObject()->Style());
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h index 81019b5..203ddf4 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -56,14 +56,10 @@ // Instruct to re-compute |PrepareLayout| on the next layout. void InvalidatePrepareLayoutForTest(); - const String& Text() const { return Data().text_content_; } - StringView Text(unsigned start_offset, unsigned end_offset) const { - return StringView(Data().text_content_, start_offset, - end_offset - start_offset); + const NGInlineItemsData& ItemsData(bool is_first_line) const { + return Data().ItemsData(is_first_line); } - const Vector<NGInlineItem>& Items(bool is_first_line = false) const; - // Returns the DOM to text content offset mapping of this block. If it is not // computed before, compute and store it in NGInlineNodeData. // This funciton must be called with clean layout. @@ -74,8 +70,10 @@ bool IsEmptyInline() { return EnsureData().is_empty_inline_; } - void AssertOffset(unsigned index, unsigned offset) const; - void AssertEndOffset(unsigned index, unsigned offset) const; + // @return if this node can contain the "first formatted line". + // https://www.w3.org/TR/CSS22/selector.html#first-formatted-line + bool CanContainFirstFormattedLine() const; + void CheckConsistency() const; String ToString() const; @@ -90,7 +88,8 @@ void CollectInlines(NGInlineNodeData*, NGInlineNodeData* previous_data = nullptr); void SegmentText(NGInlineNodeData*); - void ShapeText(NGInlineNodeData*, NGInlineNodeData* previous_data = nullptr); + void ShapeText(NGInlineItemsData*, + NGInlineItemsData* previous_data = nullptr); void ShapeText(const String& text, Vector<NGInlineItem>*, const String* previous_text); @@ -105,15 +104,6 @@ friend class NGInlineNodeLegacy; }; -inline void NGInlineNode::AssertOffset(unsigned index, unsigned offset) const { - Data().items_[index].AssertOffset(offset); -} - -inline void NGInlineNode::AssertEndOffset(unsigned index, - unsigned offset) const { - Data().items_[index].AssertEndOffset(offset); -} - DEFINE_TYPE_CASTS(NGInlineNode, NGLayoutInputNode, node,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h index 2d8efffd..f19defd 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
@@ -11,16 +11,19 @@ namespace blink { -class NGOffsetMapping; - // Data which is required for inline nodes. -struct CORE_EXPORT NGInlineNodeData { +struct CORE_EXPORT NGInlineNodeData : NGInlineItemsData { // The constructor and destructor can't be implicit or inlined, because they // need full definition of NGOffsetMapping. NGInlineNodeData(); ~NGInlineNodeData(); private: + const NGInlineItemsData& ItemsData(bool is_first_line) const { + return !is_first_line || !first_line_items_ + ? (const NGInlineItemsData&)*this + : *first_line_items_; + } TextDirection BaseDirection() const { return static_cast<TextDirection>(base_direction_); } @@ -33,18 +36,12 @@ friend class NGInlineNodeForTest; friend class NGOffsetMappingTest; - // Text content for all inline items represented by a single NGInlineNode. - // Encoded either as UTF-16 or latin-1 depending on the content. - String text_content_; - Vector<NGInlineItem> items_; - - // |items_| to use for the first line, when the node has :first-line rules. - // Items have different ComputedStyle, and may also have different ShapeResult - // if fonts are different. - std::unique_ptr<Vector<NGInlineItem>> first_line_items_; - - // The DOM to text content offset mapping of this inline node. - std::unique_ptr<NGOffsetMapping> offset_mapping_; + // Items to use for the first line, when the node has :first-line rules. + // + // Items have different ComputedStyle, and may also have different + // text_content and ShapeResult if 'text-transform' is applied or fonts are + // different. + std::unique_ptr<NGInlineItemsData> first_line_items_; unsigned is_bidi_enabled_ : 1; unsigned base_direction_ : 1; // TextDirection
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc index b209881b..f04e5e7 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -22,29 +22,29 @@ public: using NGInlineNode::NGInlineNode; - std::string Text() const { return Data().text_content_.Utf8().data(); } - Vector<NGInlineItem>& Items() { return MutableData()->items_; } + std::string Text() const { return Data().text_content.Utf8().data(); } + Vector<NGInlineItem>& Items() { return MutableData()->items; } static Vector<NGInlineItem>& Items(NGInlineNodeData& data) { - return data.items_; + return data.items; } void Append(const String& text, const ComputedStyle* style = nullptr, LayoutObject* layout_object = nullptr) { NGInlineNodeData* data = MutableData(); - unsigned start = data->text_content_.length(); - data->text_content_.append(text); - data->items_.push_back(NGInlineItem(NGInlineItem::kText, start, - start + text.length(), style, - layout_object)); + unsigned start = data->text_content.length(); + data->text_content.append(text); + data->items.push_back(NGInlineItem(NGInlineItem::kText, start, + start + text.length(), style, + layout_object)); data->is_empty_inline_ = false; } void Append(UChar character) { NGInlineNodeData* data = MutableData(); - data->text_content_.append(character); - unsigned end = data->text_content_.length(); - data->items_.push_back( + data->text_content.append(character); + unsigned end = data->text_content.length(); + data->items.push_back( NGInlineItem(NGInlineItem::kBidiControl, end - 1, end, nullptr)); data->is_bidi_enabled_ = true; data->is_empty_inline_ = false; @@ -52,8 +52,8 @@ void ClearText() { NGInlineNodeData* data = MutableData(); - data->text_content_ = String(); - data->items_.clear(); + data->text_content = String(); + data->items.clear(); data->is_empty_inline_ = true; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc index 6e576cf..76fa8e0 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -35,6 +35,17 @@ } // namespace +NGLineBreaker::LineData::LineData(NGInlineNode node, + const NGInlineBreakToken* break_token) { + is_first_formatted_line = (!break_token || (!break_token->ItemIndex() && + !break_token->TextOffset())) && + node.CanContainFirstFormattedLine(); + use_first_line_style = is_first_formatted_line && node.GetLayoutObject() + ->GetDocument() + .GetStyleEngine() + .UsesFirstLineRules(); +} + NGLineBreaker::NGLineBreaker( NGInlineNode node, NGLineBreakerMode mode, @@ -45,16 +56,19 @@ NGExclusionSpace* exclusion_space, unsigned handled_float_index, const NGInlineBreakToken* break_token) - : node_(node), + : line_(node, break_token), + node_(node), + items_data_(node.ItemsData(line_.use_first_line_style)), mode_(mode), constraint_space_(space), positioned_floats_(positioned_floats), unpositioned_floats_(unpositioned_floats), container_builder_(container_builder), exclusion_space_(exclusion_space), - break_iterator_(node.Text()), - shaper_(node.Text().Characters16(), node.Text().length()), - spacing_(node.Text()), + break_iterator_(items_data_.text_content), + shaper_(items_data_.text_content.Characters16(), + items_data_.text_content.length()), + spacing_(items_data_.text_content), handled_floats_end_item_index_(handled_float_index), base_direction_(node_.BaseDirection()), in_line_height_quirks_mode_(node.InLineHeightQuirksMode()) { @@ -65,7 +79,7 @@ item_index_ = break_token->ItemIndex(); offset_ = break_token->TextOffset(); previous_line_had_forced_break_ = break_token->IsForcedBreak(); - node.AssertOffset(item_index_, offset_); + items_data_.AssertOffset(item_index_, offset_); ignore_floats_ = break_token->IgnoreFloats(); } } @@ -112,8 +126,7 @@ // whitespace collapsing. bool NGLineBreaker::IsTrailing(const NGInlineItem& item, const NGLineInfo& line_info) const { - const Vector<NGInlineItem>& items = - node_.Items(line_info.UseFirstLineStyle()); + const Vector<NGInlineItem>& items = line_info.ItemsData().items; for (const NGInlineItem* it = &item; it != items.end(); ++it) { if (it->EndCollapseType() != NGInlineItem::kOpaqueToCollapsing) return false; @@ -121,42 +134,22 @@ return true; } -// @return if this is the "first formatted line". -// https://www.w3.org/TR/CSS22/selector.html#first-formatted-line -bool NGLineBreaker::IsFirstFormattedLine() const { - if (item_index_ || offset_) - return false; - - // TODO(kojii): In LayoutNG, leading OOF creates an anonymous block box, - // and that |CanContainFirstFormattedLine()| does not work. - // crbug.com/734554 - // return node_.GetLayoutBlockFlow()->CanContainFirstFormattedLine(); - LayoutObject* layout_object = node_.GetLayoutBlockFlow(); - if (!layout_object->IsAnonymousBlock()) - return true; - for (;;) { - layout_object = layout_object->PreviousSibling(); - if (!layout_object) - return true; - if (!layout_object->IsFloatingOrOutOfFlowPositioned()) - return false; - } -} - // Compute the base direction for bidi algorithm for this line. -void NGLineBreaker::ComputeBaseDirection() { +void NGLineBreaker::ComputeBaseDirection(const NGLineInfo& line_info) { // If 'unicode-bidi' is not 'plaintext', use the base direction of the block. if (!previous_line_had_forced_break_ || node_.Style().GetUnicodeBidi() != UnicodeBidi::kPlaintext) return; // If 'unicode-bidi: plaintext', compute the base direction for each paragraph // (separated by forced break.) - const String& text = node_.Text(); + const String& text = line_info.ItemsData().text_content; if (text.Is8Bit()) return; size_t end_offset = text.find(kNewlineCharacter, offset_); - base_direction_ = NGBidiParagraph::BaseDirectionForString(node_.Text( - offset_, end_offset == kNotFound ? text.length() : end_offset)); + base_direction_ = NGBidiParagraph::BaseDirectionForString( + end_offset == kNotFound + ? StringView(text, offset_) + : StringView(text, offset_, end_offset - offset_)); } // Initialize internal states for the next line. @@ -165,15 +158,16 @@ NGInlineItemResults* item_results = &line_info->Results(); item_results->clear(); line_info->SetStartOffset(offset_); - line_info->SetLineStyle(node_, constraint_space_, IsFirstFormattedLine(), - previous_line_had_forced_break_); + line_info->SetLineStyle( + node_, items_data_, constraint_space_, line_.is_first_formatted_line, + line_.use_first_line_style, previous_line_had_forced_break_); // Set the initial style of this line from the break token. Example: // <p>...<span>....</span></p> // When the line wraps in <span>, the 2nd line needs to start with the style // of the <span>. override_break_anywhere_ = false; SetCurrentStyle(current_style_ ? *current_style_ : line_info->LineStyle()); - ComputeBaseDirection(); + ComputeBaseDirection(*line_info); line_info->SetBaseDirection(base_direction_); line_.is_after_forced_break = false; @@ -209,8 +203,7 @@ void NGLineBreaker::BreakLine(NGLineInfo* line_info) { NGInlineItemResults* item_results = &line_info->Results(); - const Vector<NGInlineItem>& items = - node_.Items(line_info->UseFirstLineStyle()); + const Vector<NGInlineItem>& items = line_info->ItemsData().items; LineBreakState state = LineBreakState::kContinue; while (state != LineBreakState::kDone) { // Check overflow even if |item_index_| is at the end of the block, because @@ -841,7 +834,7 @@ // be a break opportunity after the space. The break_iterator cannot // compute this because it considers break opportunities are before a run // of spaces. - const String& text = node_.Text(); + const String& text = Text(); if (offset_ < text.length() && IsBreakableSpace(text[offset_])) { item_result->can_break_after = true; return; @@ -916,7 +909,7 @@ #endif item_index_ = item_result->item_index; offset_ = item_result->end_offset; - node_.AssertOffset(item_index_, offset_); + items_data_.AssertOffset(item_index_, offset_); } else { Rewind(line_info, i + 1); } @@ -976,8 +969,7 @@ // paint invalidations, hit testing, etc. LayoutObject* NGLineBreaker::CurrentLayoutObject( const NGLineInfo& line_info) const { - const Vector<NGInlineItem>& items = - node_.Items(line_info.UseFirstLineStyle()); + const Vector<NGInlineItem>& items = line_info.ItemsData().items; DCHECK_LE(item_index_, items.size()); // Find the next item that has LayoutObject. Some items such as bidi controls // do not have LayoutObject. @@ -1049,7 +1041,7 @@ scoped_refptr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken( const NGLineInfo& line_info, std::unique_ptr<const NGInlineLayoutStateStack> state_stack) const { - const Vector<NGInlineItem>& items = node_.Items(); + const Vector<NGInlineItem>& items = Items(); if (item_index_ >= items.size()) return NGInlineBreakToken::Create(node_); return NGInlineBreakToken::Create(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h index 5f2c6b4..01ff0d8 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
@@ -65,6 +65,8 @@ struct LineData { STACK_ALLOCATED(); + LineData(NGInlineNode node, const NGInlineBreakToken* break_token); + // The current position from inline_start. Unlike NGInlineLayoutAlgorithm // that computes position in visual order, this position in logical order. LayoutUnit position; @@ -75,6 +77,12 @@ LayoutUnit line_left_bfc_offset; LayoutUnit line_right_bfc_offset; + // True if this line is the "first formatted line". + // https://www.w3.org/TR/CSS22/selector.html#first-formatted-line + bool is_first_formatted_line; + + bool use_first_line_style; + // We don't create "certain zero-height line boxes". // https://drafts.csswg.org/css2/visuren.html#phantom-line-box // Such line boxes do not prevent two margins being "adjoining", and thus @@ -96,7 +104,9 @@ } }; - const String& Text() const { return break_iterator_.GetString(); } + const String& Text() const { return items_data_.text_content; } + const Vector<NGInlineItem>& Items() const { return items_data_.items; } + NGInlineItemResult* AddItem(const NGInlineItem&, unsigned end_offset, NGInlineItemResults*); @@ -156,12 +166,13 @@ void MoveToNextOf(const NGInlineItem&); void MoveToNextOf(const NGInlineItemResult&); - bool IsFirstFormattedLine() const; - void ComputeBaseDirection(); + void ComputeBaseDirection(const NGLineInfo&); bool IsTrailing(const NGInlineItem&, const NGLineInfo&) const; LineData line_; NGInlineNode node_; + const NGInlineItemsData& items_data_; + NGLineBreakerMode mode_; const NGConstraintSpace& constraint_space_; Vector<NGPositionedFloat>* positioned_floats_; @@ -172,12 +183,12 @@ unsigned item_index_ = 0; unsigned offset_ = 0; - bool previous_line_had_forced_break_ = false; - LayoutUnit bfc_line_offset_; - LayoutUnit bfc_block_offset_; LazyLineBreakIterator break_iterator_; HarfBuzzShaper shaper_; ShapeResultSpacing<String> spacing_; + bool previous_line_had_forced_break_ = false; + LayoutUnit bfc_line_offset_; + LayoutUnit bfc_block_offset_; const Hyphenation* hyphenation_ = nullptr; // Keep track of handled float items. See HandleFloat().
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc index 0394eadf..34e1835 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -70,8 +70,11 @@ String ToString(NGInlineItemResults line, NGInlineNode node) { StringBuilder builder; + const String& text = node.ItemsData(false).text_content; for (const auto& item_result : line) { - builder.Append(node.Text(item_result.start_offset, item_result.end_offset)); + builder.Append( + StringView(text, item_result.start_offset, + item_result.end_offset - item_result.start_offset)); } return builder.ToString(); } @@ -182,7 +185,7 @@ </style> <div id=container><span>123 456</span> 789</div> )HTML"); - const Vector<NGInlineItem>& items = node.Items(); + const Vector<NGInlineItem>& items = node.ItemsData(false).items; // While "123 456" can fit in a line, "456" has a right margin that cannot // fit. Since "456" and its right margin is not breakable, "456" should be on
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc index 38bb8d4..1036a00 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
@@ -40,7 +40,7 @@ } bool IsOffsetMappingStored() const { - return layout_block_flow_->GetNGInlineNodeData()->offset_mapping_.get(); + return layout_block_flow_->GetNGInlineNodeData()->offset_mapping.get(); } const LayoutText* GetLayoutTextUnder(const char* parent_id) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc index 8852bb2d..62c3347 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc
@@ -37,13 +37,14 @@ void NGTextFragmentBuilder::SetItem( NGPhysicalTextFragment::NGTextType text_type, + const NGInlineItemsData& items_data, NGInlineItemResult* item_result, LayoutUnit line_height) { DCHECK(item_result); DCHECK(item_result->item->Style()); text_type_ = text_type; - text_ = inline_node_.Text(); + text_ = items_data.text_content; item_index_ = item_result->item_index; start_offset_ = item_result->start_offset; end_offset_ = item_result->end_offset;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h index b53ca07..68efb30 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
@@ -26,6 +26,7 @@ // NOTE: Takes ownership of the shape result within the item result. void SetItem(NGPhysicalTextFragment::NGTextType, + const NGInlineItemsData&, NGInlineItemResult*, LayoutUnit line_height); void SetText(LayoutObject*,
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc index 3ff56c3..919a01fc 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -156,6 +156,14 @@ // The checks above should be enough to bail if layout is incomplete, but // let's verify: DCHECK(IsBlockLayoutComplete(*cached_constraint_space_, *cached_result_)); + // If we used to contain abspos items, we can't reuse the fragment, because + // we can't be sure that the list of items hasn't changed (as we bubble them + // up during layout). In the case of newly-added abspos items to this + // containing block, we will handle those by the NeedsLayout check above for + // now. + // TODO(layout-ng): Come up with a better solution for this + if (cached_result_->OutOfFlowPositionedDescendants().size()) + return nullptr; return cached_result_->CloneWithoutOffset(); }
diff --git a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc index 4990926..6981bf115 100644 --- a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc +++ b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
@@ -55,6 +55,10 @@ const NGPhysicalFragment& content, NGLogicalOffset* content_offset, NGFragmentBuilder* container_builder) const { + // Baselines from two different writing-mode cannot be aligned. + if (UNLIKELY(space.GetWritingMode() != content.Style().GetWritingMode())) + return false; + // Compute the baseline of the child content. FontBaseline baseline_type = IsHorizontalWritingMode(space.GetWritingMode()) ? kAlphabeticBaseline @@ -66,7 +70,7 @@ NGBoxFragment content_fragment(space.GetWritingMode(), ToNGPhysicalBoxFragment(content)); content_metrics = content_fragment.BaselineMetricsWithoutSynthesize( - {NGBaselineAlgorithmType::kFirstLine, baseline_type}, space); + {NGBaselineAlgorithmType::kFirstLine, baseline_type}); // If this child content does not have any line boxes, the list marker // should be aligned to the first line box of next child.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index c2ec41d..7aba5c9 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -669,9 +669,6 @@ // We reset the block offset here as it may have been affected by clearance. child_bfc_offset_estimate = ContainerBfcOffset().block_offset; - - // Position any pending floats since we've just updated our BFC offset. - PositionPendingFloats(child_bfc_offset_estimate); } // If the child has a non-zero block-start margin, our initial estimate will @@ -930,12 +927,13 @@ // to our parent. if (layout_result->Status() == NGLayoutResult::kBfcOffsetResolved && !container_builder_.BfcOffset()) { + // There's no need to do anything apart from resolving the BFC offset here, + // so make sure that it aborts before trying to position floats or anything + // like that, which would just be waste of time. This is simply propagating + // an abort up to a node which is able to restart the layout (a node that + // has resolved its BFC offset). + abort_when_bfc_offset_updated_ = true; ResolveBfcOffset(previous_inflow_position, child_bfc_offset->block_offset); - - // NOTE: Unlike other aborts, we don't try check if we *should* abort with - // NeedsAbortOnBfcOffsetChange(), this is simply propagating an abort up to - // a node which is able to restart the layout (a node that has resolved its - // BFC offset). return false; } @@ -1143,6 +1141,10 @@ bool is_empty_block = IsEmptyBlock(child, layout_result); if (is_empty_block) { + // The default behaviour for empty blocks is they just pass through the + // previous inflow position. + child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset; + if (empty_block_affected_by_clearance) { // If an empty block was affected by clearance (that is it got pushed // down past a float), we need to do something slightly bizarre. @@ -1154,18 +1156,46 @@ // Another way of thinking about this is that when you *add* back the // margin strut, you end up with the same position as you started with. // - // This behaviour isn't known to be in any CSS specification. - child_end_bfc_block_offset = child_bfc_offset.value().block_offset - - layout_result.EndMarginStrut().Sum(); - logical_block_offset = - logical_offset.block_offset - layout_result.EndMarginStrut().Sum(); - } else { - // The default behaviour for empty blocks is they just pass through the - // previous inflow position. - child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset; - logical_block_offset = previous_inflow_position.logical_block_offset; + // This is essentially what the spec refers to as clearance [1], and, + // while we normally don't have to calculate it directly, in the case of + // an empty cleared child like here, we actually have to. + // + // We have to calculate clearance for empty cleared children, because we + // need the margin that's between the clearance and this block to collapse + // correctly with subsequent content. This is something that needs to take + // place after the margin strut preceding and following the clearance have + // been separated. Clearance may be positive, negative or zero, depending + // on what it takes to (hypothetically) place this child just below the + // last relevant float. Since the margins before and after the clearance + // have been separated, we may have to pull the child back, and that's an + // example of negative clearance. + // + // (In the other case, when a cleared child is non-empty (i.e. when we + // don't end up here), we don't need to explicitly calculate clearance, + // because then we just place its border edge where it should be and we're + // done with it.) + // + // [1] https://www.w3.org/TR/CSS22/visuren.html#flow-control + + // First move past the margin that is to precede the clearance. It will + // not participate in any subsequent margin collapsing. + LayoutUnit margin_before_clearance = + previous_inflow_position.margin_strut.Sum(); + child_end_bfc_block_offset += margin_before_clearance; + + // Calculate and apply actual clearance. + LayoutUnit clearance = child_bfc_offset.value().block_offset - + layout_result.EndMarginStrut().Sum() - + previous_inflow_position.NextBorderEdge(); + child_end_bfc_block_offset += clearance; } + // The logical block offset needs to go through exactly the same change as + // the BFC block offset here. + logical_block_offset = previous_inflow_position.logical_block_offset + + child_end_bfc_block_offset - + previous_inflow_position.bfc_block_offset; + if (!container_builder_.BfcOffset()) { DCHECK_EQ(child_end_bfc_block_offset, ConstraintSpace().BfcOffset().block_offset);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 1829ab8..5b69e27 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -594,44 +594,53 @@ if (requests.IsEmpty()) return; + if (UNLIKELY(constraint_space.GetWritingMode() != Style().GetWritingMode())) + return; + for (const auto& request : requests) { switch (request.algorithm_type) { - case NGBaselineAlgorithmType::kAtomicInline: - AddAtomicInlineBaselineFromOldLayout( - request, constraint_space.UseFirstLineStyle(), builder); + case NGBaselineAlgorithmType::kAtomicInline: { + LayoutUnit position = + AtomicInlineBaselineFromOldLayout(request, constraint_space); + if (position != -1) + builder->AddBaseline(request, position); break; + } case NGBaselineAlgorithmType::kFirstLine: { LayoutUnit position = box_->FirstLineBoxBaseline(); - if (position != -1) { + if (position != -1) builder->AddBaseline(request, position); - } break; } } } } -void NGBlockNode::AddAtomicInlineBaselineFromOldLayout( +LayoutUnit NGBlockNode::AtomicInlineBaselineFromOldLayout( const NGBaselineRequest& request, - bool is_first_line, - NGFragmentBuilder* builder) { - // Block-level boxes do not have atomic inline baseline. - // This includes form controls when 'display:block' is applied. - if (box_->IsLayoutBlock() && !box_->IsInline()) - return; + const NGConstraintSpace& constraint_space) { + LineDirectionMode line_direction = box_->IsHorizontalWritingMode() + ? LineDirectionMode::kHorizontalLine + : LineDirectionMode::kVerticalLine; - LineDirectionMode line_direction = - IsHorizontalWritingMode(builder->GetWritingMode()) - ? LineDirectionMode::kHorizontalLine - : LineDirectionMode::kVerticalLine; - LayoutUnit position = LayoutUnit(box_->BaselinePosition( - request.baseline_type, is_first_line, line_direction)); + // If this is an inline box, use |BaselinePosition()|. Some LayoutObject + // classes override it assuming inline layout calls |BaselinePosition()|. + if (box_->IsInline()) { + LayoutUnit position = LayoutUnit(box_->BaselinePosition( + request.baseline_type, constraint_space.UseFirstLineStyle(), + line_direction, kPositionOnContainingLine)); - // BaselinePosition() uses margin edge for atomic inlines. - if (box_->IsAtomicInlineLevel()) - position -= box_->MarginOver(); + // BaselinePosition() uses margin edge for atomic inlines. Subtract + // margin-over so that the position is relative to the border box. + if (box_->IsAtomicInlineLevel()) + position -= box_->MarginOver(); - builder->AddBaseline(request, position); + return position; + } + + // If this is a block box, use |InlineBlockBaseline()|. When an inline block + // has block children, their inline block baselines need to be propagated. + return box_->InlineBlockBaseline(line_direction); } void NGBlockNode::UseOldOutOfFlowPositioning() {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h index 05f50c3..25c27d7 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -89,9 +89,8 @@ const NGPhysicalOffset& additional_offset = NGPhysicalOffset()); void CopyBaselinesFromOldLayout(const NGConstraintSpace&, NGFragmentBuilder*); - void AddAtomicInlineBaselineFromOldLayout(const NGBaselineRequest&, - bool, - NGFragmentBuilder*); + LayoutUnit AtomicInlineBaselineFromOldLayout(const NGBaselineRequest&, + const NGConstraintSpace&); }; DEFINE_TYPE_CASTS(NGBlockNode,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc index 3ee4744..c43e846 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
@@ -14,29 +14,36 @@ namespace blink { NGLineHeightMetrics NGBoxFragment::BaselineMetricsWithoutSynthesize( - const NGBaselineRequest& request, - const NGConstraintSpace& constraint_space) const { + const NGBaselineRequest& request) const { + // For "leaf" theme objects, let the theme decide what the baseline position + // is. The theme baseline wins over the propagated baselines. const auto& physical_fragment = ToNGPhysicalBoxFragment(physical_fragment_); - bool is_parallel_writing_mode = - IsParallelWritingMode(constraint_space.GetWritingMode(), - physical_fragment.Style().GetWritingMode()); - if (is_parallel_writing_mode) { - // Find the baseline from the computed results. - if (const NGBaseline* baseline = physical_fragment.Baseline(request)) { - LayoutUnit ascent = baseline->offset; - LayoutUnit descent = BlockSize() - ascent; + DCHECK(physical_fragment_.GetLayoutObject()); + const LayoutBox& layout_box = + ToLayoutBox(*physical_fragment_.GetLayoutObject()); + const ComputedStyle& style = physical_fragment.Style(); + if (style.HasAppearance() && + !LayoutTheme::GetTheme().IsControlContainer(style.Appearance())) { + return NGLineHeightMetrics( + BlockSize() + layout_box.MarginOver() + + LayoutTheme::GetTheme().BaselinePositionAdjustment(style), + layout_box.MarginUnder()); + } - // For replaced elements, inline-block elements, and inline-table - // elements, the height is the height of their margin box. - // https://drafts.csswg.org/css2/visudet.html#line-height - LayoutBox* layout_box = ToLayoutBox(physical_fragment_.GetLayoutObject()); - if (layout_box->IsAtomicInlineLevel()) { - ascent += layout_box->MarginOver(); - descent += layout_box->MarginUnder(); - } + // Check if we have a propagated baseline. + if (const NGBaseline* baseline = physical_fragment.Baseline(request)) { + LayoutUnit ascent = baseline->offset; + LayoutUnit descent = BlockSize() - ascent; - return NGLineHeightMetrics(ascent, descent); + // For replaced elements, inline-block elements, and inline-table + // elements, the height is the height of their margin box. + // https://drafts.csswg.org/css2/visudet.html#line-height + if (layout_box.IsAtomicInlineLevel()) { + ascent += layout_box.MarginOver(); + descent += layout_box.MarginUnder(); } + + return NGLineHeightMetrics(ascent, descent); } return NGLineHeightMetrics(); @@ -45,36 +52,31 @@ NGLineHeightMetrics NGBoxFragment::BaselineMetrics( const NGBaselineRequest& request, const NGConstraintSpace& constraint_space) const { - NGLineHeightMetrics metrics = - BaselineMetricsWithoutSynthesize(request, constraint_space); - if (!metrics.IsEmpty()) - return metrics; + // Try to compute the baseline if the writing-modes are the same. + if (constraint_space.GetWritingMode() == GetWritingMode()) { + NGLineHeightMetrics metrics = BaselineMetricsWithoutSynthesize(request); + if (!metrics.IsEmpty()) + return metrics; + } // The baseline type was not found. This is either this box should synthesize // box-baseline without propagating from children, or caller forgot to add // baseline requests to constraint space when it called Layout(). LayoutUnit block_size = BlockSize(); - const auto& physical_fragment = ToNGPhysicalBoxFragment(physical_fragment_); - const ComputedStyle& style = physical_fragment.Style(); - LayoutBox* layout_box = ToLayoutBox(physical_fragment_.GetLayoutObject()); - if (style.HasAppearance() && - !LayoutTheme::GetTheme().IsControlContainer(style.Appearance())) { - return NGLineHeightMetrics( - block_size + layout_box->MarginOver() + - LayoutTheme::GetTheme().BaselinePositionAdjustment(style), - layout_box->MarginUnder()); - } - // If atomic inline, use the margin box. See above. - if (layout_box->IsAtomicInlineLevel()) { + const auto& physical_fragment = ToNGPhysicalBoxFragment(physical_fragment_); + DCHECK(physical_fragment_.GetLayoutObject()); + const LayoutBox& layout_box = + ToLayoutBox(*physical_fragment_.GetLayoutObject()); + if (layout_box.IsAtomicInlineLevel()) { bool is_parallel_writing_mode = IsParallelWritingMode(constraint_space.GetWritingMode(), physical_fragment.Style().GetWritingMode()); if (is_parallel_writing_mode) - block_size += layout_box->MarginLogicalHeight(); + block_size += layout_box.MarginLogicalHeight(); else - block_size += layout_box->MarginLogicalWidth(); + block_size += layout_box.MarginLogicalWidth(); } if (request.baseline_type == kAlphabeticBaseline)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h index 3f3b3dbe..bd7e6453 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
@@ -31,8 +31,7 @@ // not have any baselines, while the other version synthesize the baseline // from the box. NGLineHeightMetrics BaselineMetricsWithoutSynthesize( - const NGBaselineRequest&, - const NGConstraintSpace&) const; + const NGBaselineRequest&) const; NGLineHeightMetrics BaselineMetrics(const NGBaselineRequest&, const NGConstraintSpace&) const; };
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc index 187a194..56477f84 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc
@@ -15,19 +15,6 @@ namespace blink { -namespace { - -bool ShouldComputeBaseline(const LayoutBox& box) { - if (box.IsLayoutBlock() && - ToLayoutBlock(box).UseLogicalBottomMarginEdgeForInlineBlockBaseline()) - return false; - if (box.IsWritingModeRoot()) - return false; - return true; -} - -} // namespace - NGConstraintSpace::NGConstraintSpace( WritingMode writing_mode, bool is_orthogonal_writing_mode_root, @@ -146,16 +133,10 @@ available_size.block_size = box.OverrideLogicalHeight(); fixed_block = true; } - if (box.IsFlexItem()) { - LayoutUnit for_percentage = + if (box.IsFlexItem() && fixed_block) { + fixed_block_is_definite = ToLayoutFlexibleBox(box.Parent()) - ->ChildLogicalHeightForPercentageResolution(box); - fixed_block_is_definite = for_percentage != LayoutUnit(-1); - if (fixed_block_is_definite) { - DCHECK_EQ(available_size.block_size, - for_percentage + box.BorderAndPaddingLogicalHeight() + - box.ScrollbarLogicalHeight()); - } + ->UseOverrideLogicalHeightForPerentageResolution(box); } bool is_new_fc = true; @@ -178,16 +159,20 @@ NGConstraintSpaceBuilder builder(writing_mode, initial_containing_block_size); - if (ShouldComputeBaseline(box)) { + if (!box.IsWritingModeRoot()) { FontBaseline baseline_type = IsHorizontalWritingMode(writing_mode) ? kAlphabeticBaseline : kIdeographicBaseline; // Add all types because we don't know which baselines will be requested. - builder - .AddBaselineRequest( - {NGBaselineAlgorithmType::kAtomicInline, baseline_type}) - .AddBaselineRequest( - {NGBaselineAlgorithmType::kFirstLine, baseline_type}); + bool synthesize_inline_block_baseline = + box.IsLayoutBlock() && + ToLayoutBlock(box).UseLogicalBottomMarginEdgeForInlineBlockBaseline(); + if (!synthesize_inline_block_baseline) { + builder.AddBaselineRequest( + {NGBaselineAlgorithmType::kAtomicInline, baseline_type}); + } + builder.AddBaselineRequest( + {NGBaselineAlgorithmType::kFirstLine, baseline_type}); } return builder.SetAvailableSize(available_size)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc b/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc index 03b89dc..f33be5c 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc
@@ -54,7 +54,9 @@ EXPECT_TRUE(result); String expected_text("Hello World!"); - EXPECT_EQ(expected_text, ToNGInlineNode(node.FirstChild()).Text(0, 12)); + NGInlineNode first_child = ToNGInlineNode(node.FirstChild()); + EXPECT_EQ(expected_text, + StringView(first_child.ItemsData(false).text_content, 0, 12)); } TEST_F(NGInlineLayoutTest, BlockWithTextAndAtomicInline) { @@ -80,7 +82,9 @@ String expected_text("Hello "); expected_text.append(kObjectReplacementCharacter); expected_text.append("."); - EXPECT_EQ(expected_text, ToNGInlineNode(node.FirstChild()).Text(0, 8)); + NGInlineNode first_child = ToNGInlineNode(node.FirstChild()); + EXPECT_EQ(expected_text, + StringView(first_child.ItemsData(false).text_content, 0, 8)); // Delete the line box tree to avoid leaks in the test. block_flow->DeleteLineBoxTree();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc index 15978cd..ab19f30 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
@@ -42,7 +42,8 @@ } if (node.IsInline()) { - for (const NGInlineItem& inline_item : ToNGInlineNode(node).Items()) { + const auto& items = ToNGInlineNode(node).ItemsData(false).items; + for (const NGInlineItem& inline_item : items) { string_builder->Append(indent_builder.ToString()); string_builder->Append(inline_item.ToString()); string_builder->Append("\n");
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index d154a67fe..84ff0cc 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -178,7 +178,6 @@ ResourceRequest FrameLoader::ResourceRequestForReload( FrameLoadType frame_load_type, - const KURL& override_url, ClientRedirectPolicy client_redirect_policy) { DCHECK(IsReloadLoadType(frame_load_type)); const auto cache_mode = frame_load_type == kFrameLoadTypeReloadBypassingCache @@ -205,10 +204,6 @@ frame_->GetDocument()->OutgoingReferrer())); } - if (!override_url.IsEmpty()) { - request.SetURL(override_url); - request.ClearHTTPReferrer(); - } request.SetSkipServiceWorker(frame_load_type == kFrameLoadTypeReloadBypassingCache); return request;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.h b/third_party/blink/renderer/core/loader/frame_loader.h index 851a1bd2..b334584 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.h +++ b/third_party/blink/renderer/core/loader/frame_loader.h
@@ -85,7 +85,6 @@ ResourceRequest ResourceRequestForReload( FrameLoadType, - const KURL& override_url = KURL(), ClientRedirectPolicy = ClientRedirectPolicy::kNotClientRedirect); ProgressTracker& Progress() const { return *progress_tracker_; }
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc index 2ef9b731c..0b41dcdf 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
@@ -18,12 +18,13 @@ namespace blink { ModuleTreeLinker* ModuleTreeLinker::Fetch(const KURL& url, + const KURL& base_url, const ScriptFetchOptions& options, Modulator* modulator, ModuleTreeLinkerRegistry* registry, ModuleTreeClient* client) { ModuleTreeLinker* fetcher = new ModuleTreeLinker(modulator, registry, client); - fetcher->FetchRoot(url, options); + fetcher->FetchRoot(url, base_url, options); return fetcher; } @@ -131,6 +132,7 @@ // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree void ModuleTreeLinker::FetchRoot(const KURL& original_url, + const KURL& base_url, const ScriptFetchOptions& options) { #if DCHECK_IS_ON() original_url_ = original_url; @@ -142,9 +144,10 @@ KURL url = original_url; // <spec // href="https://github.com/drufball/layered-apis/blob/master/spec.md#fetch-a-module-script-graph" - // step="1">Set url to the layered API fetching URL for url.</spec> + // step="1">Set url to the layered API fetching URL given url and the current + // settings object's API base URL.</spec> if (RuntimeEnabledFeatures::LayeredAPIEnabled()) - url = blink::layered_api::ResolveFetchingURL(url); + url = blink::layered_api::ResolveFetchingURL(url, base_url); #if DCHECK_IS_ON() url_ = url;
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h index ee7d659130..771ed40 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h
@@ -35,7 +35,11 @@ class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient { public: // https://html.spec.whatwg.org/#fetch-a-module-script-tree + // + // TODO(hiroshige): |base_url| is used only for Layered APIs and will be + // removed soon once an upcoming spec change lands. static ModuleTreeLinker* Fetch(const KURL&, + const KURL& base_url, const ScriptFetchOptions&, Modulator*, ModuleTreeLinkerRegistry*, @@ -75,7 +79,7 @@ #endif void AdvanceState(State); - void FetchRoot(const KURL&, const ScriptFetchOptions&); + void FetchRoot(const KURL&, const KURL& base_url, const ScriptFetchOptions&); void FetchRootInline(ModuleScript*); // Steps 1--2 of [IMSGF].
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc index 47dd025..e7aafad 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc
@@ -22,11 +22,12 @@ ModuleTreeLinker* ModuleTreeLinkerRegistry::Fetch( const KURL& url, + const KURL& base_url, const ScriptFetchOptions& options, Modulator* modulator, ModuleTreeClient* client) { ModuleTreeLinker* fetcher = - ModuleTreeLinker::Fetch(url, options, modulator, this, client); + ModuleTreeLinker::Fetch(url, base_url, options, modulator, this, client); DCHECK(fetcher->IsFetching()); active_tree_linkers_.insert(fetcher); return fetcher;
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h index 64e8084..fc19589 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h
@@ -34,6 +34,7 @@ } ModuleTreeLinker* Fetch(const KURL&, + const KURL& base_url, const ScriptFetchOptions&, Modulator*, ModuleTreeClient*);
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc index 8b7a1ee..a6662c3 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
@@ -199,7 +199,7 @@ KURL url("http://example.com/root.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously."; @@ -218,7 +218,7 @@ KURL url("http://example.com/root.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously."; @@ -241,7 +241,7 @@ KURL url("http://example.com/root.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously."; @@ -265,7 +265,7 @@ KURL url("http://example.com/root.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously."; @@ -302,7 +302,7 @@ KURL url("http://example.com/root.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously."; @@ -358,7 +358,7 @@ KURL url("http://example.com/depth1.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously."; @@ -381,7 +381,7 @@ KURL url("http://example.com/a.js"); TestModuleTreeClient* client = new TestModuleTreeClient; - registry->Fetch(url, ScriptFetchOptions(), GetModulator(), client); + registry->Fetch(url, NullURL(), ScriptFetchOptions(), GetModulator(), client); EXPECT_FALSE(client->WasNotifyFinished()) << "ModuleTreeLinker should always finish asynchronously.";
diff --git a/third_party/blink/renderer/core/loader/navigation_scheduler.cc b/third_party/blink/renderer/core/loader/navigation_scheduler.cc index 94b6516..c062d49 100644 --- a/third_party/blink/renderer/core/loader/navigation_scheduler.cc +++ b/third_party/blink/renderer/core/loader/navigation_scheduler.cc
@@ -259,7 +259,7 @@ std::unique_ptr<UserGestureIndicator> gesture_indicator = CreateUserGestureIndicator(); ResourceRequest resource_request = frame->Loader().ResourceRequestForReload( - kFrameLoadTypeReload, KURL(), ClientRedirectPolicy::kClientRedirect); + kFrameLoadTypeReload, ClientRedirectPolicy::kClientRedirect); if (resource_request.IsNull()) return; FrameLoadRequest request = FrameLoadRequest(nullptr, resource_request);
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc index c2406ea..825df41 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -445,10 +445,11 @@ data.selection_start_offset = 0; // HitTestResult::isSelected() ensures clean layout by performing a hit test. - // If source_type is |kMenuSourceAdjustSelectionReset| we know the original - // HitTestResult in SelectionController passed the inside check already, so - // let it pass. - if (r.IsSelected() || source_type == kMenuSourceAdjustSelectionReset) { + // If source_type is |kMenuSourceAdjustSelection| or + // |kMenuSourceAdjustSelectionReset| we know the original HitTestResult in + // SelectionController passed the inside check already, so let it pass. + if (r.IsSelected() || source_type == kMenuSourceAdjustSelection || + source_type == kMenuSourceAdjustSelectionReset) { data.selected_text = selected_frame->SelectedText(); WebRange range = selected_frame->GetInputMethodController().GetSelectionOffsets();
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index cec17a4..00b7de34 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -318,6 +318,13 @@ void CompositedLayerMapping::UpdateFilters() { CompositorFilterOperations operations; OwningLayer().UpdateCompositorFilterOperationsForFilter(operations); + + // If the image violates some feature policy optimized image policies, render + // with inverted color. + if (GetLayoutObject().IsLayoutImage() && + ToLayoutImage(GetLayoutObject()).ShouldInvertColor()) + operations.AppendInvertFilter(1.0f); + graphics_layer_->SetFilters(std::move(operations)); } @@ -3369,27 +3376,19 @@ LayoutRect graphics_layer_bounds_in_root_view_space( graphics_layer_bounds_in_object_space); + // MapToVisualRectInAncestorSpace is exclusive of the scroll and clip on the + // ancestor, so we map to nullptr instead of |root_view| to include these. anchor_layout_object->MapToVisualRectInAncestorSpace( - root_view, graphics_layer_bounds_in_root_view_space); + nullptr, graphics_layer_bounds_in_root_view_space); - // In RLS, the root_view is scrolled. However, MapToVisualRectInAncestorSpace - // doesn't account for this scroll, since it earlies out as soon as we reach - // this ancestor. That is, it only maps to the space of the root_view, not - // accounting for the fact that the root_view itself can be scrolled. If the - // root_view is our anchor_layout_object, then this extra offset is counted in - // offset_from_anchor_layout_object. In other cases, we need to account for it - // here. Otherwise, the paint clip below might clip the whole (visible) rect - // out. - if (RuntimeEnabledFeatures::RootLayerScrollingEnabled() && - root_view != anchor_layout_object) { - if (auto* scrollable_area = root_view->GetScrollableArea()) { - graphics_layer_bounds_in_root_view_space.MoveBy( - -scrollable_area->VisibleContentRect().Location()); - } - } - + // MapToVisualRectInAncestorSpace will not clip if the anchor is the root + // view, because the rect is assumed to already be in the clipped space of + // the root view. We need to manually apply the root view's clip in this case. FloatRect visible_content_rect(graphics_layer_bounds_in_root_view_space); - root_view->GetFrameView()->ClipPaintRect(&visible_content_rect); + if (anchor_layout_object == root_view || + !RuntimeEnabledFeatures::RootLayerScrollingEnabled()) { + root_view->GetFrameView()->ClipPaintRect(&visible_content_rect); + } FloatRect enclosing_graphics_layer_bounds( EnclosingIntRect(graphics_layer_bounds));
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc index c4c8690..b7ab205 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/public/platform/web_content_layer.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" +#include "third_party/blink/renderer/core/layout/layout_image.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" @@ -986,6 +987,32 @@ EXPECT_EQ(IntRect(1000, 0, 4400, 300), RecomputeInterestRect(graphics_layer)); } +TEST_P(CompositedLayerMappingTest, ScrolledFixedPositionInterestRect) { + GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled( + true); + SetBodyInnerHTML(R"HTML( + <style>body { margin:0; } ::-webkit-scrollbar { display:none; }</style> + <div id="fixed" style="position: fixed;"> + <div style="background: blue; width: 30px; height: 30px;"></div> + <div style="position: absolute; transform: translateY(-4500px); + top: 0; left: 0; width: 100px; height: 100px;"></div> + </div> + <div id="forcescroll" style="height: 2000px;"></div> + )HTML"); + + GetDocument().View()->UpdateAllLifecyclePhases(); + auto* fixed = GetDocument().getElementById("fixed")->GetLayoutObject(); + auto* graphics_layer = fixed->EnclosingLayer()->GraphicsLayerBacking(fixed); + EXPECT_EQ(IntRect(0, 500, 100, 4030), RecomputeInterestRect(graphics_layer)); + + GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset( + ScrollOffset(0.0, 200.0), kProgrammaticScroll); + GetDocument().View()->UpdateAllLifecyclePhases(); + + // Because the fixed element does not scroll, the interest rect is unchanged. + EXPECT_EQ(IntRect(0, 500, 100, 4030), RecomputeInterestRect(graphics_layer)); +} + TEST_P(CompositedLayerMappingTest, ScrollingContentsAndForegroundLayerPaintingPhase) { GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled( @@ -2687,4 +2714,45 @@ squashed->GraphicsLayerBacking()->GetPosition()); } +TEST_P(CompositedLayerMappingTest, ImageWithInvertFilterLayer) { + SetBodyInnerHTML("<img id='image' style='will-change: transform;' src='x'>"); + ToLayoutImage(GetLayoutObjectByElementId("image")) + ->UpdateShouldInvertColor(true); + GetDocument().View()->UpdateAllLifecyclePhases(); + cc::FilterOperations filters; + filters.Append(cc::FilterOperation::CreateInvertFilter(1.0f)); + EXPECT_EQ(filters, ToLayoutBoxModelObject(GetLayoutObjectByElementId("image")) + ->Layer() + ->GraphicsLayerBacking() + ->PlatformLayer() + ->CcLayer() + ->filters()); +} + +TEST_P(CompositedLayerMappingTest, ImageWithInvertFilterLayerUpdated) { + SetBodyInnerHTML("<img id='image' style='will-change: transform;' src='x'>"); + ToLayoutImage(GetLayoutObjectByElementId("image")) + ->UpdateShouldInvertColor(true); + GetDocument().View()->UpdateAllLifecyclePhases(); + cc::FilterOperations filters0, filters1; + filters0.Append(cc::FilterOperation::CreateInvertFilter(1.0f)); + EXPECT_EQ(filters0, + ToLayoutBoxModelObject(GetLayoutObjectByElementId("image")) + ->Layer() + ->GraphicsLayerBacking() + ->PlatformLayer() + ->CcLayer() + ->filters()); + ToLayoutImage(GetLayoutObjectByElementId("image")) + ->UpdateShouldInvertColor(false); + GetDocument().View()->UpdateAllLifecyclePhases(); + EXPECT_EQ(filters1, + ToLayoutBoxModelObject(GetLayoutObjectByElementId("image")) + ->Layer() + ->GraphicsLayerBacking() + ->PlatformLayer() + ->CcLayer() + ->filters()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index f78ed48..250714d 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h" +#include "third_party/blink/renderer/core/layout/layout_image.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_table_row.h" #include "third_party/blink/renderer/core/layout/layout_table_section.h" @@ -909,8 +910,12 @@ static bool NeedsFilter(const LayoutObject& object) { // TODO(trchen): SVG caches filters in SVGResources. Implement it. - return object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() && - (object.StyleRef().HasFilter() || object.HasReflection()); + if (object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() && + (object.StyleRef().HasFilter() || object.HasReflection())) + return true; + if (object.IsLayoutImage() && ToLayoutImage(object).ShouldInvertColor()) + return true; + return false; } void FragmentPaintPropertyTreeBuilder::UpdateFilter() { @@ -923,12 +928,24 @@ state.local_transform_space = context_.current.transform; state.paint_offset = FloatPoint(context_.current.paint_offset); - // Try to use the cached filter. - if (properties_->Filter()) - state.filter = properties_->Filter()->Filter(); - auto& layer = *ToLayoutBoxModelObject(object_).Layer(); - layer.UpdateCompositorFilterOperationsForFilter(state.filter); - layer.ClearFilterOnEffectNodeDirty(); + auto* layer = ToLayoutBoxModelObject(object_).Layer(); + if (layer) { + // Try to use the cached filter. + if (properties_->Filter()) + state.filter = properties_->Filter()->Filter(); + + if (object_.IsLayoutImage() && + ToLayoutImage(object_).ShouldInvertColor()) + state.filter.AppendInvertFilter(1.0f); + + layer->UpdateCompositorFilterOperationsForFilter(state.filter); + layer->ClearFilterOnEffectNodeDirty(); + } else { + DCHECK(object_.IsLayoutImage() && + ToLayoutImage(object_).ShouldInvertColor()); + state.filter = CompositorFilterOperations(); + state.filter.AppendInvertFilter(1.0f); + } // The CSS filter spec didn't specify how filters interact with overflow // clips. The implementation here mimics the old Blink/WebKit behavior for @@ -1075,7 +1092,8 @@ if (!NeedsPaintPropertyUpdate()) return; - if (!object_.HasLayer() && !NeedsPaintOffsetTranslation(object_)) { + if (!object_.HasLayer() && !NeedsPaintOffsetTranslation(object_) && + !NeedsFilter(object_)) { fragment_data_.ClearLocalBorderBoxProperties(); } else { PropertyTreeState local_border_box =
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index 0c27a04..0d32bc8 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h" #include "third_party/blink/renderer/core/html/html_iframe_element.h" +#include "third_party/blink/renderer/core/layout/layout_image.h" #include "third_party/blink/renderer/core/layout/layout_tree_as_text.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h" #include "third_party/blink/renderer/core/paint/object_paint_properties.h" @@ -5499,4 +5500,70 @@ EXPECT_EQ(1u, NumFragments(fixed_child)); } +TEST_P(PaintPropertyTreeBuilderTest, ImageWithInvertFilter) { + SetBodyInnerHTML(R"HTML( + <img id='img' src='x'> + )HTML"); + ToLayoutImage(GetLayoutObjectByElementId("img")) + ->UpdateShouldInvertColor(true); + GetDocument().View()->UpdateAllLifecyclePhases(); + const auto* filters = PaintPropertiesForElement("img")->Filter(); + ASSERT_NE(nullptr, filters); + CompositorFilterOperations filters_expect; + filters_expect.AppendInvertFilter(1.0f); + EXPECT_EQ(filters_expect, filters->Filter()); +} + +TEST_P(PaintPropertyTreeBuilderTest, ImageWithInvertFilterUpdated) { + SetBodyInnerHTML(R"HTML( + <img id='img' src='x'> + )HTML"); + + ToLayoutImage(GetLayoutObjectByElementId("img")) + ->UpdateShouldInvertColor(true); + GetDocument().View()->UpdateAllLifecyclePhases(); + const auto* filters = PaintPropertiesForElement("img")->Filter(); + ASSERT_NE(nullptr, filters); + CompositorFilterOperations filters_expect; + filters_expect.AppendInvertFilter(1.0f); + EXPECT_EQ(filters_expect, filters->Filter()); + ToLayoutImage(GetLayoutObjectByElementId("img")) + ->UpdateShouldInvertColor(false); + GetDocument().View()->UpdateAllLifecyclePhases(); + EXPECT_EQ(nullptr, PaintPropertiesForElement("img")); +} + +TEST_P(PaintPropertyTreeBuilderTest, LayeredImageWithInvertFilter) { + SetBodyInnerHTML(R"HTML( + <img id='img' style='position: relative;' src='x'> + )HTML"); + ToLayoutImage(GetLayoutObjectByElementId("img")) + ->UpdateShouldInvertColor(true); + GetDocument().View()->UpdateAllLifecyclePhases(); + const auto* filters = PaintPropertiesForElement("img")->Filter(); + ASSERT_NE(nullptr, filters); + CompositorFilterOperations filters_expect; + filters_expect.AppendInvertFilter(1.0f); + EXPECT_EQ(filters_expect, filters->Filter()); +} + +TEST_P(PaintPropertyTreeBuilderTest, LayeredImageWithInvertFilterUpdated) { + SetBodyInnerHTML(R"HTML( + <img id='img' style='position: relative;' src='x'> + )HTML"); + + ToLayoutImage(GetLayoutObjectByElementId("img")) + ->UpdateShouldInvertColor(true); + GetDocument().View()->UpdateAllLifecyclePhases(); + const auto* filters = PaintPropertiesForElement("img")->Filter(); + ASSERT_NE(nullptr, filters); + CompositorFilterOperations filters_expect; + filters_expect.AppendInvertFilter(1.0f); + EXPECT_EQ(filters_expect, filters->Filter()); + ToLayoutImage(GetLayoutObjectByElementId("img")) + ->UpdateShouldInvertColor(false); + GetDocument().View()->UpdateAllLifecyclePhases(); + EXPECT_EQ(nullptr, PaintPropertiesForElement("img")); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/replaced_painter.cc b/third_party/blink/renderer/core/paint/replaced_painter.cc index df2d892..0d50e827 100644 --- a/third_party/blink/renderer/core/paint/replaced_painter.cc +++ b/third_party/blink/renderer/core/paint/replaced_painter.cc
@@ -86,40 +86,56 @@ base::Optional<RoundedInnerRectClipper> clipper; base::Optional<ScopedPaintChunkProperties> chunk_properties; bool completely_clipped_out = false; - if (layout_replaced_.Style()->HasBorderRadius()) { - if (border_rect.IsEmpty()) { - completely_clipped_out = true; - } else if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { - if (!layout_replaced_.IsSVGRoot()) { + + if (layout_replaced_.Style()->HasBorderRadius() && border_rect.IsEmpty()) + completely_clipped_out = true; + + if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { + if (!layout_replaced_.IsSVGRoot()) { + if (layout_replaced_.Style()->HasBorderRadius()) { if (const auto* fragment = paint_info.FragmentToPaint(layout_replaced_)) { - const auto* properties = fragment->PaintProperties(); - DCHECK(properties && properties->InnerBorderRadiusClip()); + const auto* paint_properties = fragment->PaintProperties(); + DCHECK(paint_properties && + paint_properties->InnerBorderRadiusClip()); chunk_properties.emplace( local_paint_info.context.GetPaintController(), - properties->InnerBorderRadiusClip(), layout_replaced_, + paint_properties->InnerBorderRadiusClip(), layout_replaced_, + DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase)); + } + } else if (!layout_replaced_.HasLayer() || + !layout_replaced_.Layer()->IsSelfPaintingLayer()) { + // The only use case of this is to apply color-inversion filter for + // images violating feature policy optimized image policies. + if (layout_replaced_.FirstFragment().HasLocalBorderBoxProperties()) { + chunk_properties.emplace( + local_paint_info.context.GetPaintController(), + layout_replaced_.FirstFragment().LocalBorderBoxProperties(), + layout_replaced_, DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase)); } } - } else if (ShouldApplyViewportClip(layout_replaced_)) { - // Push a clip if we have a border radius, since we want to round the - // foreground content that gets painted. - FloatRoundedRect rounded_inner_rect = - layout_replaced_.Style()->GetRoundedInnerBorderFor( - border_rect, - LayoutRectOutsets(-(layout_replaced_.PaddingTop() + - layout_replaced_.BorderTop()), - -(layout_replaced_.PaddingRight() + - layout_replaced_.BorderRight()), - -(layout_replaced_.PaddingBottom() + - layout_replaced_.BorderBottom()), - -(layout_replaced_.PaddingLeft() + - layout_replaced_.BorderLeft())), - true, true); - - clipper.emplace(layout_replaced_, local_paint_info, border_rect, - rounded_inner_rect, kApplyToDisplayList); } + } else if (!completely_clipped_out && + layout_replaced_.Style()->HasBorderRadius() && + ShouldApplyViewportClip(layout_replaced_)) { + // Push a clip if we have a border radius, since we want to round the + // foreground content that gets painted. + FloatRoundedRect rounded_inner_rect = + layout_replaced_.Style()->GetRoundedInnerBorderFor( + border_rect, + LayoutRectOutsets(-(layout_replaced_.PaddingTop() + + layout_replaced_.BorderTop()), + -(layout_replaced_.PaddingRight() + + layout_replaced_.BorderRight()), + -(layout_replaced_.PaddingBottom() + + layout_replaced_.BorderBottom()), + -(layout_replaced_.PaddingLeft() + + layout_replaced_.BorderLeft())), + true, true); + + clipper.emplace(layout_replaced_, local_paint_info, border_rect, + rounded_inner_rect, kApplyToDisplayList); } if (!completely_clipped_out) {
diff --git a/third_party/blink/renderer/core/script/layered_api.cc b/third_party/blink/renderer/core/script/layered_api.cc index b6796248..55b3c54 100644 --- a/third_party/blink/renderer/core/script/layered_api.cc +++ b/third_party/blink/renderer/core/script/layered_api.cc
@@ -58,7 +58,7 @@ } // namespace // https://github.com/drufball/layered-apis/blob/master/spec.md#user-content-layered-api-fetching-url -KURL ResolveFetchingURL(const KURL& url) { +KURL ResolveFetchingURL(const KURL& url, const KURL& base_url) { // <spec step="1">If url's scheme is not "std", return url.</spec> if (!url.ProtocolIs(kStdScheme)) return url; @@ -96,8 +96,9 @@ if (fallback.IsNull()) return NullURL(); - // <spec step="7">Return the result of parsing fallback.</spec> - return KURL(NullURL(), fallback); + // <spec step="7">Return the result of parsing fallback with the base URL + // baseURLForFallback.</spec> + return KURL(base_url, fallback); } KURL GetInternalURL(const KURL& url) {
diff --git a/third_party/blink/renderer/core/script/layered_api.h b/third_party/blink/renderer/core/script/layered_api.h index f9d3599..87f8e59 100644 --- a/third_party/blink/renderer/core/script/layered_api.h +++ b/third_party/blink/renderer/core/script/layered_api.h
@@ -21,7 +21,7 @@ // href="https://github.com/drufball/layered-apis/blob/master/spec.md#user-content-layered-api-fetching-url"> // This operation maps URLs of the form std:x|y to either std:x or y // URLs.</spec> -CORE_EXPORT KURL ResolveFetchingURL(const KURL&); +CORE_EXPORT KURL ResolveFetchingURL(const KURL&, const KURL& base_url); // Returns std-internal://x/index.js if the URL is Layered API, or null URL // otherwise (not specced).
diff --git a/third_party/blink/renderer/core/script/layered_api_test.cc b/third_party/blink/renderer/core/script/layered_api_test.cc index 0f056fc..ae78031 100644 --- a/third_party/blink/renderer/core/script/layered_api_test.cc +++ b/third_party/blink/renderer/core/script/layered_api_test.cc
@@ -13,18 +13,33 @@ namespace { TEST(LayeredAPITest, ResolveFetchingURL) { - EXPECT_EQ(ResolveFetchingURL(KURL("https://example.com/")), + KURL base_url("https://example.com/base/path/"); + + EXPECT_EQ(ResolveFetchingURL(KURL("https://example.com/"), base_url), KURL("https://example.com/")); - EXPECT_EQ(ResolveFetchingURL(KURL("std:blank")), KURL("std:blank")); - EXPECT_EQ(ResolveFetchingURL(KURL("std:blank|https://fallback.example.com/")), + + EXPECT_EQ(ResolveFetchingURL(KURL("std:blank"), base_url), KURL("std:blank")); + EXPECT_EQ(ResolveFetchingURL(KURL("std:blank|https://fallback.example.com/"), + base_url), KURL("std:blank")); - EXPECT_EQ(ResolveFetchingURL(KURL("std:blank|https://:invalid-url")), - KURL("std:blank")); - EXPECT_EQ(ResolveFetchingURL(KURL("std:none")), NullURL()); - EXPECT_EQ(ResolveFetchingURL(KURL("std:none|https://fallback.example.com/")), + EXPECT_EQ( + ResolveFetchingURL(KURL("std:blank|https://:invalid-url"), base_url), + KURL("std:blank")); + + EXPECT_EQ(ResolveFetchingURL(KURL("std:none"), base_url), NullURL()); + EXPECT_EQ(ResolveFetchingURL(KURL("std:none|https://fallback.example.com/"), + base_url), KURL("https://fallback.example.com/")); EXPECT_FALSE( - ResolveFetchingURL(KURL("std:none|https://:invalid-url")).IsValid()); + ResolveFetchingURL(KURL("std:none|https://:invalid-url"), base_url) + .IsValid()); + + EXPECT_EQ(ResolveFetchingURL(KURL("std:none|fallback.js"), base_url), + KURL("https://example.com/base/path/fallback.js")); + EXPECT_EQ(ResolveFetchingURL(KURL("std:none|./fallback.js"), base_url), + KURL("https://example.com/base/path/fallback.js")); + EXPECT_EQ(ResolveFetchingURL(KURL("std:none|/fallback.js"), base_url), + KURL("https://example.com/fallback.js")); } TEST(LayeredAPITest, GetInternalURL) {
diff --git a/third_party/blink/renderer/core/script/modulator.cc b/third_party/blink/renderer/core/script/modulator.cc index c958aee..ab4eca3 100644 --- a/third_party/blink/renderer/core/script/modulator.cc +++ b/third_party/blink/renderer/core/script/modulator.cc
@@ -92,9 +92,9 @@ // href="https://github.com/drufball/layered-apis/blob/master/spec.md#resolve-a-module-specifier" // step="1">Let parsed be the result of applying the URL parser to // specifier. If parsed is not failure, then return the layered API fetching - // URL for parsed.</spec> + // URL given parsed and script's base URL.</spec> if (RuntimeEnabledFeatures::LayeredAPIEnabled()) - return blink::layered_api::ResolveFetchingURL(url); + return blink::layered_api::ResolveFetchingURL(url, base_url); return url; }
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc index 93a01339..0793bc4 100644 --- a/third_party/blink/renderer/core/script/modulator_impl_base.cc +++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -67,7 +67,8 @@ // of this algorithm specified custom perform the fetch steps, pass those // along as well.</spec> - tree_linker_registry_->Fetch(url, options, this, client); + tree_linker_registry_->Fetch(url, GetExecutionContext()->BaseURL(), options, + this, client); // <spec label="fetch-a-module-script-tree" step="3">When the internal module // script graph fetching procedure asynchronously completes with result,
diff --git a/third_party/blink/renderer/core/script/script_loader.h b/third_party/blink/renderer/core/script/script_loader.h index 3493263b..de6e46e 100644 --- a/third_party/blink/renderer/core/script/script_loader.h +++ b/third_party/blink/renderer/core/script/script_loader.h
@@ -138,6 +138,10 @@ bool is_evaluated, bool created_during_document_write); + void SetAsyncExecTypeForTesting(ScriptRunner::AsyncExecutionType type) { + async_exec_type_ = type; + } + private: bool IgnoresLoadRequest() const; bool IsScriptForEventSupported() const;
diff --git a/third_party/blink/renderer/core/script/script_runner.cc b/third_party/blink/renderer/core/script/script_runner.cc index 0709b30..8073a0c8 100644 --- a/third_party/blink/renderer/core/script/script_runner.cc +++ b/third_party/blink/renderer/core/script/script_runner.cc
@@ -269,7 +269,9 @@ DCHECK(!is_suspended_); DCHECK(script_loader); - // Currently, we support streaming only for async scripts. + // Currently, we stream only async scripts in this function. + // Note: HTMLParserScriptRunner kicks streaming for deferred or blocking + // scripts. DCHECK(pending_async_scripts_.find(script_loader) != pending_async_scripts_.end() || std::find(async_scripts_to_execute_soon_.begin(),
diff --git a/third_party/blink/renderer/core/script/script_runner_test.cc b/third_party/blink/renderer/core/script/script_runner_test.cc index eb79383a..bbc2e6e 100644 --- a/third_party/blink/renderer/core/script/script_runner_test.cc +++ b/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -37,17 +37,39 @@ MOCK_CONST_METHOD0(UrlForTracing, KURL()); MOCK_METHOD0(RemoveFromMemoryCache, void()); - MOCK_CONST_METHOD0(IsCurrentlyStreaming, bool()); - // The currently released googletest cannot mock methods with C++ move-only - // types like std::unique_ptr. This has been promised to be fixed in a - // future release of googletest, but for now we use the recommended - // workaround of 'bumping' the method-to-be-mocked to another method. + enum class State { + kStreamingNotReady, + kReadyToBeStreamed, + kStreaming, + kStreamingFinished, + }; + + bool IsCurrentlyStreaming() const override { + return state_ == State::kStreaming; + } + + void PrepareForStreaming() { + DCHECK_EQ(state_, State::kStreamingNotReady); + state_ = State::kReadyToBeStreamed; + } + bool StartStreamingIfPossible(ScriptStreamer::Type type, base::OnceClosure closure) override { - return DoStartStreamingIfPossible(type, &closure); + if (state_ != State::kReadyToBeStreamed) + return false; + + state_ = State::kStreaming; + streaming_finished_callback_ = std::move(closure); + return true; } - MOCK_METHOD2(DoStartStreamingIfPossible, - bool(ScriptStreamer::Type, base::OnceClosure*)); + + void SimulateStreamingEnd() { + DCHECK_EQ(state_, State::kStreaming); + state_ = State::kStreamingFinished; + std::move(streaming_finished_callback_).Run(); + } + + State state() const { return state_; } protected: MOCK_METHOD0(DisposeInternal, void()); @@ -55,67 +77,50 @@ private: MockPendingScript() : PendingScript(nullptr, TextPosition()) {} + + State state_ = State::kStreamingNotReady; + base::OnceClosure streaming_finished_callback_; }; class MockScriptLoader final : public ScriptLoader { public: - static MockScriptLoader* Create() { - return (new MockScriptLoader())->SetupForNonStreaming(); + static MockScriptLoader* CreateInOrder() { + auto* loader = new MockScriptLoader(); + loader->SetAsyncExecTypeForTesting(ScriptRunner::kInOrder); + return loader; } + static MockScriptLoader* CreateAsync() { + auto* loader = new MockScriptLoader(); + loader->SetAsyncExecTypeForTesting(ScriptRunner::kAsync); + loader->mock_pending_script_if_script_is_async_ = + MockPendingScript::Create(); + return loader; + } + ~MockScriptLoader() override {} MOCK_METHOD0(Execute, void()); MOCK_CONST_METHOD0(IsReady, bool()); - MOCK_METHOD0(GetPendingScriptIfScriptIsAsync, PendingScript*()); - - // Set up the mock for streaming. The closure passed in will receive the - // 'finish streaming' callback, so that the test case can control when - // the mock streaming has mock finished. - MockScriptLoader* SetupForStreaming(base::OnceClosure& finished_callback); - MockScriptLoader* SetupForNonStreaming(); void Trace(blink::Visitor*) override; + PendingScript* GetPendingScriptIfScriptIsAsync() override { + return mock_pending_script_if_script_is_async_.Get(); + } + MockPendingScript* GetMockPendingScript() { + return mock_pending_script_if_script_is_async_.Get(); + } + private: explicit MockScriptLoader() : ScriptLoader(MockScriptElementBase::Create(), false, false, false) {} - Member<MockPendingScript> mock_pending_script_; + + Member<MockPendingScript> mock_pending_script_if_script_is_async_; }; void MockScriptLoader::Trace(blink::Visitor* visitor) { ScriptLoader::Trace(visitor); - visitor->Trace(mock_pending_script_); -} - -MockScriptLoader* MockScriptLoader::SetupForStreaming( - base::OnceClosure& finished_callback) { - mock_pending_script_ = MockPendingScript::Create(); - SetupForNonStreaming(); - - // Mock the streaming functions and save the 'streaming done' callback - // into the callback done variable. This way, we can control when - // streamig is done. - EXPECT_CALL(*mock_pending_script_, DoStartStreamingIfPossible(_, _)) - .WillOnce(Return(false)) - .WillOnce( - Invoke([&finished_callback](ScriptStreamer::Type, - base::OnceClosure* callback) -> bool { - finished_callback = std::move(*callback); - return true; - })) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pending_script_, IsCurrentlyStreaming()) - .WillRepeatedly( - Invoke([&finished_callback] { return !!finished_callback; })); - return this; -} - -MockScriptLoader* MockScriptLoader::SetupForNonStreaming() { - EXPECT_CALL(*this, GetPendingScriptIfScriptIsAsync()) - .WillRepeatedly(Invoke([this]() -> PendingScript* { - return this->mock_pending_script_.Get(); - })); - return this; + visitor->Trace(mock_pending_script_if_script_is_async_); } class ScriptRunnerTest : public testing::Test { @@ -144,7 +149,8 @@ }; TEST_F(ScriptRunnerTest, QueueSingleScript_Async) { - MockScriptLoader* script_loader = MockScriptLoader::Create(); + auto* script_loader = MockScriptLoader::CreateAsync(); + script_runner_->QueueScriptForExecution(script_loader, ScriptRunner::kAsync); script_runner_->NotifyScriptReady(script_loader, ScriptRunner::kAsync); @@ -153,7 +159,7 @@ } TEST_F(ScriptRunnerTest, QueueSingleScript_InOrder) { - MockScriptLoader* script_loader = MockScriptLoader::Create(); + auto* script_loader = MockScriptLoader::CreateInOrder(); script_runner_->QueueScriptForExecution(script_loader, ScriptRunner::kInOrder); @@ -166,9 +172,9 @@ } TEST_F(ScriptRunnerTest, QueueMultipleScripts_InOrder) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); - MockScriptLoader* script_loader3 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateInOrder(); + auto* script_loader2 = MockScriptLoader::CreateInOrder(); + auto* script_loader3 = MockScriptLoader::CreateInOrder(); HeapVector<Member<MockScriptLoader>> script_loaders; script_loaders.push_back(script_loader1); @@ -206,11 +212,11 @@ } TEST_F(ScriptRunnerTest, QueueMixedScripts) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); - MockScriptLoader* script_loader3 = MockScriptLoader::Create(); - MockScriptLoader* script_loader4 = MockScriptLoader::Create(); - MockScriptLoader* script_loader5 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateInOrder(); + auto* script_loader2 = MockScriptLoader::CreateInOrder(); + auto* script_loader3 = MockScriptLoader::CreateInOrder(); + auto* script_loader4 = MockScriptLoader::CreateAsync(); + auto* script_loader5 = MockScriptLoader::CreateAsync(); script_runner_->QueueScriptForExecution(script_loader1, ScriptRunner::kInOrder); @@ -258,16 +264,16 @@ } TEST_F(ScriptRunnerTest, QueueReentrantScript_Async) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); - MockScriptLoader* script_loader3 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateAsync(); + auto* script_loader2 = MockScriptLoader::CreateAsync(); + auto* script_loader3 = MockScriptLoader::CreateAsync(); script_runner_->QueueScriptForExecution(script_loader1, ScriptRunner::kAsync); script_runner_->QueueScriptForExecution(script_loader2, ScriptRunner::kAsync); script_runner_->QueueScriptForExecution(script_loader3, ScriptRunner::kAsync); script_runner_->NotifyScriptReady(script_loader1, ScriptRunner::kAsync); - MockScriptLoader* script_loader = script_loader2; + auto* script_loader = script_loader2; EXPECT_CALL(*script_loader1, Execute()) .WillOnce(Invoke([script_loader, this] { order_.push_back(1); @@ -298,9 +304,9 @@ } TEST_F(ScriptRunnerTest, QueueReentrantScript_InOrder) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); - MockScriptLoader* script_loader3 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateInOrder(); + auto* script_loader2 = MockScriptLoader::CreateInOrder(); + auto* script_loader3 = MockScriptLoader::CreateInOrder(); EXPECT_CALL(*script_loader1, IsReady()).WillRepeatedly(Return(true)); EXPECT_CALL(*script_loader2, IsReady()).WillRepeatedly(Return(true)); @@ -352,7 +358,7 @@ script_loaders[i] = nullptr; for (int i = 0; i < 20; i++) { - script_loaders[i] = MockScriptLoader::Create(); + script_loaders[i] = MockScriptLoader::CreateAsync(); EXPECT_CALL(*script_loaders[i], IsReady()).WillRepeatedly(Return(true)); script_runner_->QueueScriptForExecution(script_loaders[i], @@ -386,9 +392,9 @@ } TEST_F(ScriptRunnerTest, ResumeAndSuspend_InOrder) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); - MockScriptLoader* script_loader3 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateInOrder(); + auto* script_loader2 = MockScriptLoader::CreateInOrder(); + auto* script_loader3 = MockScriptLoader::CreateInOrder(); script_runner_->QueueScriptForExecution(script_loader1, ScriptRunner::kInOrder); @@ -431,9 +437,9 @@ } TEST_F(ScriptRunnerTest, ResumeAndSuspend_Async) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); - MockScriptLoader* script_loader3 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateAsync(); + auto* script_loader2 = MockScriptLoader::CreateAsync(); + auto* script_loader3 = MockScriptLoader::CreateAsync(); script_runner_->QueueScriptForExecution(script_loader1, ScriptRunner::kAsync); script_runner_->QueueScriptForExecution(script_loader2, ScriptRunner::kAsync); @@ -463,8 +469,8 @@ } TEST_F(ScriptRunnerTest, LateNotifications) { - MockScriptLoader* script_loader1 = MockScriptLoader::Create(); - MockScriptLoader* script_loader2 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateInOrder(); + auto* script_loader2 = MockScriptLoader::CreateInOrder(); EXPECT_CALL(*script_loader1, IsReady()).WillRepeatedly(Return(true)); EXPECT_CALL(*script_loader2, IsReady()).WillRepeatedly(Return(true)); @@ -493,8 +499,8 @@ } TEST_F(ScriptRunnerTest, TasksWithDeadScriptRunner) { - Persistent<MockScriptLoader> script_loader1 = MockScriptLoader::Create(); - Persistent<MockScriptLoader> script_loader2 = MockScriptLoader::Create(); + Persistent<MockScriptLoader> script_loader1 = MockScriptLoader::CreateAsync(); + Persistent<MockScriptLoader> script_loader2 = MockScriptLoader::CreateAsync(); EXPECT_CALL(*script_loader1, IsReady()).WillRepeatedly(Return(true)); EXPECT_CALL(*script_loader2, IsReady()).WillRepeatedly(Return(true)); @@ -518,33 +524,36 @@ } TEST_F(ScriptRunnerTest, TryStreamWhenEnqueingScript) { - Persistent<MockScriptLoader> script_loader1 = MockScriptLoader::Create(); + auto* script_loader1 = MockScriptLoader::CreateAsync(); EXPECT_CALL(*script_loader1, IsReady()).WillRepeatedly(Return(true)); script_runner_->QueueScriptForExecution(script_loader1, ScriptRunner::kAsync); } TEST_F(ScriptRunnerTest, DontExecuteWhileStreaming) { - base::OnceClosure callback; - Persistent<MockScriptLoader> script_loader1 = - MockScriptLoader::Create()->SetupForStreaming(callback); - EXPECT_CALL(*script_loader1, IsReady()).WillRepeatedly(Return(true)); + auto* script_loader = MockScriptLoader::CreateAsync(); + EXPECT_CALL(*script_loader, IsReady()).WillRepeatedly(Return(false)); - // Enqueue script & make it ready. - script_runner_->QueueScriptForExecution(script_loader1, ScriptRunner::kAsync); - script_runner_->NotifyScriptReady(script_loader1, ScriptRunner::kAsync); + // Enqueue script. + script_runner_->QueueScriptForExecution(script_loader, ScriptRunner::kAsync); - // We should have started streaming by now. - CHECK(callback); + // Simulate script load and mark the pending script as streaming ready. + EXPECT_CALL(*script_loader, IsReady()).WillRepeatedly(Return(true)); + script_loader->GetMockPendingScript()->PrepareForStreaming(); + script_runner_->NotifyScriptReady(script_loader, ScriptRunner::kAsync); + + // ScriptLoader should have started streaming by now. + EXPECT_EQ(script_loader->GetMockPendingScript()->state(), + MockPendingScript::State::kStreaming); // Note that there is no expectation for ScriptLoader::Execute() yet, // so the mock will fail if it's called anyway. platform_->RunUntilIdle(); // Finish streaming. - std::move(callback).Run(); + script_loader->GetMockPendingScript()->SimulateStreamingEnd(); // Now that streaming is finished, expect Execute() to be called. - EXPECT_CALL(*script_loader1, Execute()).Times(1); + EXPECT_CALL(*script_loader, Execute()).Times(1); platform_->RunUntilIdle(); }
diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn index 92bf988e..efc23715 100644 --- a/third_party/blink/renderer/devtools/BUILD.gn +++ b/third_party/blink/renderer/devtools/BUILD.gn
@@ -703,6 +703,7 @@ "front_end/terminal/xterm.js/build/xterm.js", "front_end/test_runner/module.json", "front_end/test_runner/TestRunner.js", + "front_end/text_editor/autocompleteTooltip.css", "front_end/text_editor/cmdevtools.css", "front_end/text_editor/CodeMirrorTextEditor.js", "front_end/text_editor/CodeMirrorUtils.js",
diff --git a/third_party/blink/renderer/devtools/front_end/Tests.js b/third_party/blink/renderer/devtools/front_end/Tests.js index add96169..d853042 100644 --- a/third_party/blink/renderer/devtools/front_end/Tests.js +++ b/third_party/blink/renderer/devtools/front_end/Tests.js
@@ -1110,13 +1110,31 @@ this.releaseControl(); }; + TestSuite.prototype.testDisposeEmptyBrowserContext = async function(url) { + this.takeControl(); + const targetAgent = SDK.targetManager.mainTarget().targetAgent(); + const {browserContextId} = await targetAgent.invoke_createBrowserContext(); + const response1 = await targetAgent.invoke_getBrowserContexts(); + this.assertEquals(response1.browserContextIds.length, 1); + await targetAgent.invoke_disposeBrowserContext({browserContextId}); + const response2 = await targetAgent.invoke_getBrowserContexts(); + this.assertEquals(response2.browserContextIds.length, 0); + this.releaseControl(); + }; + TestSuite.prototype.testCreateBrowserContext = async function(url) { this.takeControl(); const browserContextIds = []; + const targetAgent = SDK.targetManager.mainTarget().targetAgent(); const target1 = await createIsolatedTarget(url); const target2 = await createIsolatedTarget(url); + const response = await targetAgent.invoke_getBrowserContexts(); + this.assertEquals(response.browserContextIds.length, 2); + this.assertTrue(response.browserContextIds.includes(browserContextIds[0])); + this.assertTrue(response.browserContextIds.includes(browserContextIds[1])); + await evalCode(target1, 'localStorage.setItem("page1", "page1")'); await evalCode(target2, 'localStorage.setItem("page2", "page2")'); @@ -1125,13 +1143,12 @@ this.assertEquals(await evalCode(target2, 'localStorage.getItem("page1")'), null); this.assertEquals(await evalCode(target2, 'localStorage.getItem("page2")'), 'page2'); - this.assertEquals(await disposeBrowserContext(browserContextIds[0]), false); - this.assertEquals(await disposeBrowserContext(browserContextIds[1]), false); - - await closeTarget(target1); - await closeTarget(target2); - this.assertEquals(await disposeBrowserContext(browserContextIds[0]), true); - this.assertEquals(await disposeBrowserContext(browserContextIds[1]), true); + const removedTargets = []; + SDK.targetManager.observeTargets({targetAdded: () => {}, targetRemoved: target => removedTargets.push(target)}); + await Promise.all([disposeBrowserContext(browserContextIds[0]), disposeBrowserContext(browserContextIds[1])]); + this.assertEquals(removedTargets.length, 2); + this.assertEquals(removedTargets.indexOf(target1) !== -1, true); + this.assertEquals(removedTargets.indexOf(target2) !== -1, true); this.releaseControl(); @@ -1140,7 +1157,6 @@ * @return {!Promise<!SDK.Target>} */ async function createIsolatedTarget(url) { - const targetAgent = SDK.targetManager.mainTarget().targetAgent(); const {browserContextId} = await targetAgent.invoke_createBrowserContext(); browserContextIds.push(browserContextId); @@ -1154,15 +1170,9 @@ return target; } - async function closeTarget(target) { - const targetAgent = SDK.targetManager.mainTarget().targetAgent(); - await targetAgent.invoke_closeTarget({targetId: target.id()}); - } - async function disposeBrowserContext(browserContextId) { const targetAgent = SDK.targetManager.mainTarget().targetAgent(); - const {success} = await targetAgent.invoke_disposeBrowserContext({browserContextId}); - return success; + await targetAgent.invoke_disposeBrowserContext({browserContextId}); } async function evalCode(target, code) {
diff --git a/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js b/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js index 5c01d53..e5cb9bd 100644 --- a/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js +++ b/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js
@@ -24,6 +24,17 @@ } /** + * @param {!Workspace.UISourceCode} uiSourceCode + * @param {boolean=} omitFocus + */ + selectUISourceCode(uiSourceCode, omitFocus) { + const treeElement = this._treeElements.get(uiSourceCode); + if (!treeElement) + return; + treeElement.select(omitFocus); + } + + /** * @return {?Workspace.UISourceCode} */ selectedUISourceCode() {
diff --git a/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js b/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js index 1d97d1a..d9bf5cd 100644 --- a/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js +++ b/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js
@@ -319,4 +319,24 @@ Addition: 'addition', Equal: 'equal', Spacer: 'spacer' -}; \ No newline at end of file +}; + +/** + * @implements {Common.Revealer} + */ +Changes.ChangesView.DiffUILocationRevealer = class { + /** + * @override + * @param {!Object} diffUILocation + * @param {boolean=} omitFocus + * @return {!Promise} + */ + async reveal(diffUILocation, omitFocus) { + if (!(diffUILocation instanceof WorkspaceDiff.DiffUILocation)) + throw new Error('Internal error: not a diff ui location'); + /** @type {!Changes.ChangesView} */ + const changesView = self.runtime.sharedInstance(Changes.ChangesView); + await UI.viewManager.showView('changes.changes'); + changesView._changesSidebar.selectUISourceCode(diffUILocation.uiSourceCode, omitFocus); + } +};
diff --git a/third_party/blink/renderer/devtools/front_end/changes/module.json b/third_party/blink/renderer/devtools/front_end/changes/module.json index a1d831a..1875abc 100644 --- a/third_party/blink/renderer/devtools/front_end/changes/module.json +++ b/third_party/blink/renderer/devtools/front_end/changes/module.json
@@ -7,6 +7,14 @@ "title": "Changes", "persistence": "closeable", "className": "Changes.ChangesView" + }, + { + "type": "@Common.Revealer", + "contextTypes": [ + "WorkspaceDiff.DiffUILocation" + ], + "destination": "Changes drawer", + "className": "Changes.ChangesView.DiffUILocationRevealer" } ], "dependencies": [
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js index 509c25e..41902804 100644 --- a/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js +++ b/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
@@ -1,9 +1,7 @@ // 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. -/** - * @unrestricted - */ + Console.ConsolePrompt = class extends UI.Widget { constructor() { super(); @@ -11,6 +9,7 @@ this._history = new Console.ConsoleHistoryManager(); this._initialText = ''; + /** @type {?UI.TextEditor} */ this._editor = null; this._isBelowPromptEnabled = Runtime.experiments.isEnabled('consoleBelowPrompt'); this._eagerPreviewElement = createElementWithClass('div', 'console-eager-preview'); @@ -25,6 +24,8 @@ this._eagerPreviewElement.classList.toggle('hidden', !this._eagerEvalSetting.get()); this.element.tabIndex = 0; + /** @type {?Promise} */ + this._previewRequestForTest = null; self.runtime.extension(UI.TextEditorFactory).instance().then(gotFactory.bind(this)); @@ -39,6 +40,7 @@ this._editor.configureAutocomplete({ substituteRangeCallback: this._substituteRange.bind(this), suggestionsCallback: this._wordsWithQuery.bind(this), + tooltipCallback: (lineNumber, columnNumber) => this._tooltipCallback(lineNumber, columnNumber) }); this._editor.widget().element.addEventListener('keydown', this._editorKeyDown.bind(this), true); this._editor.widget().show(this.element); @@ -371,6 +373,35 @@ .then(words => words.concat(historyWords)); } + /** + * @param {number} lineNumber + * @param {number} columnNumber + * @return {!Promise<?Element>} + */ + async _tooltipCallback(lineNumber, columnNumber) { + const before = this._editor.text(new TextUtils.TextRange(0, 0, lineNumber, columnNumber)); + const result = await ObjectUI.javaScriptAutocomplete.argumentsHint(before); + if (!result) + return null; + const argumentsElement = createElement('span'); + for (let i = 0; i < result.args.length; i++) { + if (i === result.argumentIndex || (i < result.argumentIndex && result.args[i].startsWith('...'))) { + const boldElement = createElement('b'); + boldElement.textContent = result.args[i]; + argumentsElement.appendChild(boldElement); + } else { + argumentsElement.createTextChild(result.args[i]); + } + if (i < result.args.length - 1) + argumentsElement.createTextChild(', '); + } + const tooltip = createElementWithClass('span', 'source-code'); + tooltip.createTextChild('\u0192('); + tooltip.appendChild(argumentsElement); + tooltip.createTextChild(')'); + return tooltip; + } + _editorSetForTest() { } };
diff --git a/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js b/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js index 6890f50..95fe35d42 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js +++ b/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js
@@ -239,6 +239,23 @@ return /** @type {!Promise<?{baseExpression: string, possibleSideEffects:boolean}>} */ ( this._runTask('findLastExpression', {content})); } + + /** + * @param {string} content + * @return {!Promise<?{baseExpression: string, possibleSideEffects:boolean, argumentIndex: number}>} + */ + findLastFunctionCall(content) { + return /** @type {!Promise<?{baseExpression: string, possibleSideEffects:boolean, argumentIndex: number}>} */ ( + this._runTask('findLastFunctionCall', {content})); + } + + /** + * @param {string} content + * @return {!Promise<!Array<string>>} + */ + argumentsList(content) { + return /** @type {!Promise<!Array<string>>} */ (this._runTask('argumentsList', {content})); + } }; Formatter.FormatterWorkerPool.MaxWorkers = 2;
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js index 791c5a81..d0d00c6 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js
@@ -87,6 +87,12 @@ case 'findLastExpression': postMessage(FormatterWorker.findLastExpression(params.content)); break; + case 'findLastFunctionCall': + postMessage(FormatterWorker.findLastFunctionCall(params.content)); + break; + case 'argumentsList': + postMessage(FormatterWorker.argumentsList(params.content)); + break; default: console.error('Unsupport method name: ' + method); } @@ -322,6 +328,95 @@ /** * @param {string} content + * @return {?{baseExpression: string, possibleSideEffects:boolean, argumentIndex: number}} + */ +FormatterWorker.findLastFunctionCall = function(content) { + if (content.length > 10000) + return null; + try { + const tokenizer = acorn.tokenizer(content, {ecmaVersion: 9}); + while (tokenizer.getToken().type !== acorn.tokTypes.eof) { + } + } catch (e) { + return null; + } + + const suffix = '000)'; + const base = FormatterWorker._lastCompleteExpression(content, suffix, new Set(['CallExpression', 'NewExpression'])); + if (!base) + return null; + const callee = base.baseNode['callee']; + const argumentIndex = base.baseNode['arguments'].length - 1; + const baseExpression = base.baseExpression.substring(callee.start, callee.end); + const possibleSideEffects = FormatterWorker._nodeHasPossibleSideEffects(callee); + return {baseExpression, possibleSideEffects, argumentIndex}; +}; + +/** + * @param {string} content + * @return {!Array<string>} + */ +FormatterWorker.argumentsList = function(content) { + if (content.length > 10000) + return []; + let parsed = null; + try { + // Try to parse as a function, anonymous function, or arrow function. + parsed = acorn.parse(`(${content})`, {ecmaVersion: 9}); + } catch (e) { + } + if (!parsed) { + try { + // Try to parse as a method. + parsed = acorn.parse(`({${content}})`, {ecmaVersion: 9}); + } catch (e) { + } + } + if (!parsed || !parsed.body || !parsed.body[0] || !parsed.body[0].expression) + return []; + const expression = parsed.body[0].expression; + let params = null; + switch (expression.type) { + case 'ClassExpression': + if (!expression.body.body) + break; + const constructor = expression.body.body.find(method => method.kind === 'constructor'); + if (constructor) + params = constructor.value.params; + break; + case 'ObjectExpression': + if (!expression.properties[0] || !expression.properties[0].value) + break; + params = expression.properties[0].value.params; + break; + case 'FunctionExpression': + case 'ArrowFunctionExpression': + params = expression.params; + break; + } + if (!params) + return []; + return params.map(paramName); + + function paramName(param) { + switch (param.type) { + case 'Identifier': + return param.name; + case 'AssignmentPattern': + return '?' + paramName(param.left); + case 'ObjectPattern': + return 'obj'; + case 'ArrayPattern': + return 'arr'; + case 'RestElement': + return '...' + paramName(param.argument); + } + return '?'; + } +}; + +/** + * @param {string} content * @return {?{baseExpression: string, possibleSideEffects:boolean}} */ FormatterWorker.findLastExpression = function(content) { @@ -335,8 +430,6 @@ return null; } - /** @type {!ESTree.Node} */ - let ast; const suffix = '.DEVTOOLS'; try { acorn.parse(content + suffix, {ecmaVersion: 9}); @@ -345,6 +438,23 @@ if (parseError.message.startsWith('Unexpected token') && parseError.pos === content.length) return null; } + const base = FormatterWorker._lastCompleteExpression(content, suffix, new Set(['MemberExpression', 'Identifier'])); + if (!base) + return null; + const {baseExpression, baseNode} = base; + const possibleSideEffects = FormatterWorker._nodeHasPossibleSideEffects(baseNode); + return {baseExpression, possibleSideEffects}; +}; + +/** + * @param {string} content + * @param {string} suffix + * @param {!Set<string>} types + * @return {?{baseNode: !ESTree.Node, baseExpression: string}} + */ +FormatterWorker._lastCompleteExpression = function(content, suffix, types) { + /** @type {!ESTree.Node} */ + let ast; let parsedContent = ''; for (let i = 0; i < content.length; i++) { try { @@ -357,7 +467,6 @@ } if (!ast) return null; - const types = new Set(['MemberExpression', 'Identifier']); let baseNode = null; const walker = new FormatterWorker.ESTreeWalker(node => { if (baseNode || node.end < ast.end) @@ -371,6 +480,14 @@ let baseExpression = parsedContent.substring(baseNode.start, parsedContent.length - suffix.length); if (baseExpression.startsWith('{')) baseExpression = `(${baseExpression})`; + return {baseNode, baseExpression}; +}; + +/** + * @param {!ESTree.Node} baseNode + * @return {boolean} + */ +FormatterWorker._nodeHasPossibleSideEffects = function(baseNode) { const sideEffectFreeTypes = new Set([ 'MemberExpression', 'Identifier', 'BinaryExpression', 'Literal', 'TemplateLiteral', 'TemplateElement', 'ObjectExpression', 'ArrayExpression', 'Property', 'ThisExpression' @@ -383,7 +500,7 @@ return FormatterWorker.ESTreeWalker.SkipSubtree; }); sideEffectwalker.walk(/** @type {!ESTree.Node} */ (baseNode)); - return {baseExpression, possibleSideEffects}; + return possibleSideEffects; }; /**
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js index 57d4010..4811440 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -159,7 +159,7 @@ } _createSearchPrompt() { - const text = this._searchHint.contentElement.createChild('div', 'search-button'); + const text = this._searchHint.contentElement.createChild('div', 'search-suggestion'); text.createChild('span').textContent = ls`Search headers and response bodies for `; const filterString = text.createChild('strong'); const button = UI.createTextButton('Find All', () => this._openSearchView()); @@ -1486,6 +1486,7 @@ * @param {!SDK.NetworkRequest} request */ selectRequest(request) { + this.setTextFilterValue(''); const node = this._reveal(request); if (node) node.select();
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js b/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js index de931827..8320051 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js
@@ -59,16 +59,18 @@ if (progress.isCanceled()) return null; const locations = []; + if (stringMatchesQuery(request.url())) + locations.push(Network.UIRequestLocation.urlMatch(request)); for (const header of request.requestHeaders()) { if (headerMatchesQuery(header)) - locations.push(new Network.UIRequestLocation(request, header, null, null)); + locations.push(Network.UIRequestLocation.requestHeaderMatch(request, header)); } for (const header of request.responseHeaders) { if (headerMatchesQuery(header)) - locations.push(new Network.UIRequestLocation(request, null, header, null)); + locations.push(Network.UIRequestLocation.responseHeaderMatch(request, header)); } for (const match of bodyMatches) - locations.push(new Network.UIRequestLocation(request, null, null, match)); + locations.push(Network.UIRequestLocation.bodyMatch(request, match)); progress.worked(); return new Network.NetworkSearchResult(request, locations); @@ -77,7 +79,14 @@ * @return {boolean} */ function headerMatchesQuery(header) { - const string = `${header.name}: ${header.value}`; + return stringMatchesQuery(`${header.name}: ${header.value}`); + } + + /** + * @param {string} string + * @return {boolean} + */ + function stringMatchesQuery(string) { const flags = searchConfig.ignoreCase() ? 'i' : ''; const regExps = searchConfig.queries().map(query => new RegExp(query, flags)); let pos = 0; @@ -104,12 +113,45 @@ * @param {?SDK.NetworkRequest.NameValue} requestHeader * @param {?SDK.NetworkRequest.NameValue} responseHeader * @param {?Common.ContentProvider.SearchMatch} searchMatch + * @param {boolean} urlMatch */ - constructor(request, requestHeader, responseHeader, searchMatch) { + constructor(request, requestHeader, responseHeader, searchMatch, urlMatch) { this.request = request; this.requestHeader = requestHeader; this.responseHeader = responseHeader; this.searchMatch = searchMatch; + this.isUrlMatch = urlMatch; + } + + /** + * @param {!SDK.NetworkRequest} request + * @param {?SDK.NetworkRequest.NameValue} header + */ + static requestHeaderMatch(request, header) { + return new Network.UIRequestLocation(request, header, null, null, false); + } + + /** + * @param {!SDK.NetworkRequest} request + * @param {?SDK.NetworkRequest.NameValue} header + */ + static responseHeaderMatch(request, header) { + return new Network.UIRequestLocation(request, null, header, null, false); + } + + /** + * @param {!SDK.NetworkRequest} request + * @param {?Common.ContentProvider.SearchMatch} searchMatch + */ + static bodyMatch(request, searchMatch) { + return new Network.UIRequestLocation(request, null, null, searchMatch, false); + } + + /** + * @param {!SDK.NetworkRequest} request + */ + static urlMatch(request) { + return new Network.UIRequestLocation(request, null, null, null, true); } }; @@ -160,6 +202,8 @@ */ matchLineContent(index) { const location = this._locations[index]; + if (location.isUrlMatch) + return this._request.url(); const header = location.requestHeader || location.responseHeader; if (header) return header.value; @@ -182,6 +226,8 @@ */ matchLabel(index) { const location = this._locations[index]; + if (location.isUrlMatch) + return Common.UIString('URL'); const header = location.requestHeader || location.responseHeader; if (header) return `${header.name}:`;
diff --git a/third_party/blink/renderer/devtools/front_end/network/networkPanel.css b/third_party/blink/renderer/devtools/front_end/network/networkPanel.css index ba6505e..1791144d 100644 --- a/third_party/blink/renderer/devtools/front_end/network/networkPanel.css +++ b/third_party/blink/renderer/devtools/front_end/network/networkPanel.css
@@ -137,6 +137,12 @@ margin: 0 4px; } +.open-search-view .search-suggestion { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + .network-tabbed-pane { background-color: var(--toolbar-bg-color); }
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js b/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js index 037dc20..6b8dfd9 100644 --- a/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js +++ b/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
@@ -33,6 +33,43 @@ } /** + * @param {string} fullText + * @return {!Promise<?{args: !Array<string>, argumentIndex: number}>} + */ + async argumentsHint(fullText) { + const functionCall = await Formatter.formatterWorkerPool().findLastFunctionCall(fullText); + if (!functionCall) + return null; + const executionContext = UI.context.flavor(SDK.ExecutionContext); + if (!executionContext) + return null; + const result = await executionContext.evaluate( + { + expression: functionCall.baseExpression, + objectGroup: 'argumentsHint', + includeCommandLineAPI: true, + silent: true, + returnByValue: false, + generatePreview: false, + throwOnSideEffect: functionCall.possibleSideEffects, + timeout: functionCall.possibleSideEffects ? 500 : undefined + }, + /* userGesture */ false, /* awaitPromise */ false); + if (!result || result.exceptionDetails || !result.object || result.object.type !== 'function') + return null; + executionContext.runtimeModel.releaseObjectGroup('argumentsHint'); + + const description = result.object.description; + if (description.endsWith('{ [native code] }')) + return null; // TODO(einbinder) support native function argument hints + const args = await Formatter.formatterWorkerPool().argumentsList(description); + + if (!args.length) + return null; + return {args, argumentIndex: functionCall.argumentIndex}; + } + + /** * @param {string} text * @param {string} query * @return {!Promise<!UI.SuggestBox.Suggestions>}
diff --git a/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js b/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js index 47286e8e..4ce4277 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js +++ b/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js
@@ -14,7 +14,7 @@ /** @type {!Array<!Sources.GutterDiffPlugin.GutterDecoration>} */ this._decorations = []; - this._textEditor.installGutter(SourceFrame.SourceCodeDiff.DiffGutterType, true); + this._textEditor.installGutter(Sources.GutterDiffPlugin.DiffGutterType, true); this._workspaceDiff = WorkspaceDiff.workspaceDiff(); this._workspaceDiff.subscribeToDiffChange(this._uiSourceCode, this._update, this); this._update(); @@ -97,6 +97,35 @@ /** * @override + * @param {!UI.ContextMenu} contextMenu + * @param {number} lineNumber + * @return {!Promise} + */ + async populateLineGutterContextMenu(contextMenu, lineNumber) { + Sources.GutterDiffPlugin._appendRevealDiffContextMenu(contextMenu, this._uiSourceCode); + } + + /** + * @override + * @param {!UI.ContextMenu} contextMenu + * @param {number} lineNumber + * @param {number} columnNumber + * @return {!Promise} + */ + async populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) { + Sources.GutterDiffPlugin._appendRevealDiffContextMenu(contextMenu, this._uiSourceCode); + } + + static _appendRevealDiffContextMenu(contextMenu, uiSourceCode) { + if (!WorkspaceDiff.workspaceDiff().isUISourceCodeModified(uiSourceCode)) + return; + contextMenu.revealSection().appendItem(ls`Local Modifications...`, () => { + Common.Revealer.reveal(new WorkspaceDiff.DiffUILocation(uiSourceCode)); + }); + } + + /** + * @override */ dispose() { for (const decoration of this._decorations) @@ -140,7 +169,7 @@ return; const element = createElementWithClass('div', 'diff-marker'); element.textContent = '\u00A0'; - this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.SourceCodeDiff.DiffGutterType, element); + this._textEditor.setGutterDecoration(location.lineNumber, Sources.GutterDiffPlugin.DiffGutterType, element); this._textEditor.toggleLineClass(location.lineNumber, this._className, true); } @@ -148,10 +177,30 @@ const location = this._position.resolve(); if (!location) return; - this._textEditor.setGutterDecoration(location.lineNumber, SourceFrame.SourceCodeDiff.DiffGutterType, null); + this._textEditor.setGutterDecoration(location.lineNumber, Sources.GutterDiffPlugin.DiffGutterType, null); this._textEditor.toggleLineClass(location.lineNumber, this._className, false); } }; /** @type {string} */ -SourceFrame.SourceCodeDiff.DiffGutterType = 'CodeMirror-gutter-diff'; +Sources.GutterDiffPlugin.DiffGutterType = 'CodeMirror-gutter-diff'; + +/** + * @implements {UI.ContextMenu.Provider} + * @unrestricted + */ +Sources.GutterDiffPlugin.ContextMenuProvider = class { + /** + * @override + * @param {!Event} event + * @param {!UI.ContextMenu} contextMenu + * @param {!Object} target + */ + appendApplicableItems(event, contextMenu, target) { + let uiSourceCode = /** @type {!Workspace.UISourceCode} */ (target); + const binding = Persistence.persistence.binding(uiSourceCode); + if (binding) + uiSourceCode = binding.network; + Sources.GutterDiffPlugin._appendRevealDiffContextMenu(contextMenu, uiSourceCode); + } +};
diff --git a/third_party/blink/renderer/devtools/front_end/sources/module.json b/third_party/blink/renderer/devtools/front_end/sources/module.json index bbb61d2..2097f804d 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/module.json +++ b/third_party/blink/renderer/devtools/front_end/sources/module.json
@@ -212,6 +212,13 @@ "className": "Sources.WatchExpressionsSidebarPane" }, { + "type": "@UI.ContextMenu.Provider", + "contextTypes": [ + "Workspace.UISourceCode" + ], + "className": "Sources.GutterDiffPlugin.ContextMenuProvider" + }, + { "type": "action", "actionId": "debugger.evaluate-selection", "className": "Sources.SourcesPanel.DebuggingActionDelegate",
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js b/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js index 93d4e26..7a210d9 100644 --- a/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js +++ b/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
@@ -22,7 +22,10 @@ this._changes = this._changes.bind(this); this._blur = this._blur.bind(this); this._beforeChange = this._beforeChange.bind(this); - this._mouseDown = this.clearAutocomplete.bind(this); + this._mouseDown = () => { + this.clearAutocomplete(); + this._tooltipGlassPane.hide(); + }; this._codeMirror.on('changes', this._changes); this._lastHintText = ''; /** @type {?UI.SuggestBox} */ @@ -30,6 +33,14 @@ /** @type {?string} */ this._currentSuggestion = null; this._hintElement = createElementWithClass('span', 'auto-complete-text'); + + this._tooltipGlassPane = new UI.GlassPane(); + this._tooltipGlassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent); + this._tooltipGlassPane.setOutsideClickCallback(this._tooltipGlassPane.hide.bind(this._tooltipGlassPane)); + this._tooltipElement = createElementWithClass('div', 'autocomplete-tooltip'); + const shadowRoot = + UI.createShadowRootWithCoreStyles(this._tooltipGlassPane.contentElement, 'text_editor/autocompleteTooltip.css'); + shadowRoot.appendChild(this._tooltipElement); } _initializeIfNeeded() { @@ -220,14 +231,14 @@ autocomplete(force) { this._initializeIfNeeded(); if (this._codeMirror.somethingSelected()) { - this.clearAutocomplete(); + this._hideSuggestBox(); return; } const cursor = this._codeMirror.getCursor('head'); const substituteRange = this._substituteRange(cursor.line, cursor.ch); if (!substituteRange || !this._validateSelectionsContexts(substituteRange)) { - this.clearAutocomplete(); + this._hideSuggestBox(); return; } @@ -246,7 +257,7 @@ function wordsAcquired(wordsWithQuery) { if (!wordsWithQuery.length || (wordsWithQuery.length === 1 && query === wordsWithQuery[0].text) || (!this._suggestBox && hadSuggestBox)) { - this.clearAutocomplete(); + this._hideSuggestBox(); this._onSuggestionsShownForTest([]); return; } @@ -259,6 +270,8 @@ queryRange.startColumn !== oldQueryRange.startColumn) this._updateAnchorBox(); this._suggestBox.updateSuggestions(this._anchorBox, wordsWithQuery, true, !this._isCursorAtEndOfLine(), query); + if (this._suggestBox.visible) + this._tooltipGlassPane.hide(); this._onSuggestionsShownForTest(wordsWithQuery); } } @@ -311,6 +324,11 @@ } clearAutocomplete() { + this._tooltipGlassPane.hide(); + this._hideSuggestBox(); + } + + _hideSuggestBox() { if (!this._suggestBox) return; this._suggestBox.hide(); @@ -328,6 +346,10 @@ * @return {boolean} */ keyDown(event) { + if (this._tooltipGlassPane.isShowing() && event.keyCode === UI.KeyboardShortcut.Keys.Esc.code) { + this._tooltipGlassPane.hide(); + return true; + } if (!this._suggestBox) return false; switch (event.keyCode) { @@ -417,6 +439,7 @@ } _onScroll() { + this._tooltipGlassPane.hide(); if (!this._suggestBox) return; const cursor = this._codeMirror.getCursor(); @@ -431,7 +454,34 @@ } } + async _updateTooltip() { + const cursor = this._codeMirror.getCursor(); + const tooltip = this._config.tooltipCallback ? await this._config.tooltipCallback(cursor.line, cursor.ch) : null; + const newCursor = this._codeMirror.getCursor(); + + if (newCursor.line !== cursor.line && newCursor.ch !== cursor.ch) + return; + if (this._suggestBox && this._suggestBox.visible) + return; + + if (!tooltip) { + this._tooltipGlassPane.hide(); + return; + } + const metrics = this._textEditor.cursorPositionToCoordinates(cursor.line, cursor.ch); + if (!metrics) { + this._tooltipGlassPane.hide(); + return; + } + + this._tooltipGlassPane.setContentAnchorBox(new AnchorBox(metrics.x, metrics.y, 0, metrics.height)); + this._tooltipElement.removeChildren(); + this._tooltipElement.appendChild(tooltip); + this._tooltipGlassPane.show(/** @type {!Document} */ (this._textEditor.element.ownerDocument)); + } + _onCursorActivity() { + this._updateTooltip(); if (!this._suggestBox) return; const cursor = this._codeMirror.getCursor();
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/autocompleteTooltip.css b/third_party/blink/renderer/devtools/front_end/text_editor/autocompleteTooltip.css new file mode 100644 index 0000000..f125260 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/text_editor/autocompleteTooltip.css
@@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +.autocomplete-tooltip { + background-color: #FFFFFF; + pointer-events: none; + margin-left: -3px; + box-shadow: var(--drop-shadow); + overflow-x: hidden; + height: 20px; +} + +.autocomplete-tooltip > * { + padding: 0px 4px; + white-space: nowrap; + vertical-align: middle; + line-height: 20px; +} \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/module.json b/third_party/blink/renderer/devtools/front_end/text_editor/module.json index 429098b..e1a6b60 100644 --- a/third_party/blink/renderer/devtools/front_end/text_editor/module.json +++ b/third_party/blink/renderer/devtools/front_end/text_editor/module.json
@@ -26,6 +26,7 @@ "CodeMirrorTextEditor.js" ], "resources": [ + "autocompleteTooltip.css", "cmdevtools.css" ], "skip_compilation": [
diff --git a/third_party/blink/renderer/devtools/front_end/ui/Fragment.js b/third_party/blink/renderer/devtools/front_end/ui/Fragment.js index d30df1e..b7aabfb6 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/Fragment.js +++ b/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
@@ -9,9 +9,6 @@ constructor(element) { this._element = element; - /** @type {!Map<string, !Array<!UI.Fragment._State>>} */ - this._states = new Map(); - /** @type {!Map<string, !Element>} */ this._elementsById = new Map(); } @@ -32,45 +29,20 @@ } /** - * @param {string} name - * @param {boolean} toggled - */ - setState(name, toggled) { - const list = this._states.get(name); - if (list === undefined) { - console.error('Unknown state ' + name); - return; - } - for (const state of list) { - if (state.toggled === toggled) - continue; - state.toggled = toggled; - const value = state.attributeValue; - state.attributeValue = state.element.getAttribute(state.attributeName); - if (value === null) - state.element.removeAttribute(state.attributeName); - else - state.element.setAttribute(state.attributeName, value); - } - } - - /** * @param {!Array<string>} strings - * @param {...*} vararg + * @param {...*} values * @return {!UI.Fragment} */ - static build(strings, vararg) { - const values = Array.prototype.slice.call(arguments, 1); + static build(strings, ...values) { return UI.Fragment._render(UI.Fragment._template(strings), values); } /** * @param {!Array<string>} strings - * @param {...*} vararg + * @param {...*} values * @return {!UI.Fragment} */ - static cached(strings, vararg) { - const values = Array.prototype.slice.call(arguments, 1); + static cached(strings, ...values) { let template = UI.Fragment._templateCache.get(strings); if (!template) { template = UI.Fragment._template(strings); @@ -119,17 +91,7 @@ const attributesToRemove = []; for (let i = 0; i < node.attributes.length; i++) { - let name = node.attributes[i].name; - - if (name.startsWith('s-')) { - attributesToRemove.push(name); - name = name.substring(2); - const state = name.substring(0, name.indexOf('-')); - const attr = name.substring(state.length + 1); - nodesToMark.push(node); - binds.push({state: {name: state, attribute: attr, value: node.attributes[i].value}}); - continue; - } + const name = node.attributes[i].name; if (!UI.Fragment._attributeMarkerRegex.test(name) && !UI.Fragment._attributeMarkerRegex.test(node.attributes[i].value)) @@ -186,7 +148,6 @@ /** @type {!Element} */ (content.firstChild === content.lastChild ? content.firstChild : content); const result = new UI.Fragment(resultElement); - const idByElement = new Map(); const boundElements = []; for (let i = 0; i < template.binds.length; i++) { const className = UI.Fragment._class(i); @@ -200,7 +161,6 @@ const element = boundElements[bindIndex]; if ('elementId' in bind) { result._elementsById.set(/** @type {string} */ (bind.elementId), element); - idByElement.set(element, bind.elementId); } else if ('replaceNodeIndex' in bind) { const value = values[/** @type {number} */ (bind.replaceNodeIndex)]; let node = null; @@ -211,13 +171,7 @@ else node = createTextNode('' + value); - element.parentNode.insertBefore(node, element); - element.remove(); - } else if ('state' in bind) { - const list = result._states.get(bind.state.name) || []; - list.push( - {attributeName: bind.state.attribute, attributeValue: bind.state.value, element: element, toggled: false}); - result._states.set(bind.state.name, list); + element.parentNode.replaceChild(node, element); } else if ('attr' in bind) { if (bind.attr.names.length === 2 && bind.attr.values.length === 1 && typeof values[bind.attr.index] === 'function') { @@ -238,31 +192,9 @@ } } } else { - throw 'Unexpected bind'; + throw new Error('Unexpected bind'); } } - - // We do this after binds so that querySelector works. - const shadows = result._element.querySelectorAll('x-shadow'); - for (const shadow of shadows) { - if (!shadow.parentElement) - throw 'There must be a parent element here'; - const shadowRoot = UI.createShadowRootWithCoreStyles(shadow.parentElement); - if (shadow.parentElement.tagName === 'X-WIDGET') - shadow.parentElement._shadowRoot = shadowRoot; - const children = []; - while (shadow.lastChild) { - children.push(shadow.lastChild); - shadow.lastChild.remove(); - } - for (let i = children.length - 1; i >= 0; i--) - shadowRoot.appendChild(children[i]); - const id = idByElement.get(shadow); - if (id) - result._elementsById.set(id, /** @type {!Element} */ (/** @type {!Node} */ (shadowRoot))); - shadow.remove(); - } - return result; } }; @@ -277,24 +209,8 @@ /** * @typedef {!{ - * attributeName: string, - * attributeValue: string, - * element: !Element, - * toggled: boolean - * }} - */ -UI.Fragment._State; - -/** - * @typedef {!{ * elementId: (string|undefined), * - * state: (!{ - * name: string, - * attribute: string, - * value: string - * }|undefined), - * * attr: (!{ * index: number, * names: !Array<string>, @@ -315,3 +231,12 @@ UI.Fragment._class = index => 'template-class-' + index; UI.Fragment._templateCache = new Map(); + +/** + * @param {!Array<string>} strings + * @param {...*} vararg + * @return {!Element} + */ +UI.html = (strings, ...vararg) => { + return UI.Fragment.cached(strings, ...vararg).element(); +};
diff --git a/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js b/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js index 8bf364db..d8aeb04 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js +++ b/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
@@ -116,6 +116,7 @@ /** * @typedef {{ * substituteRangeCallback: ((function(number, number):?TextUtils.TextRange)|undefined), + * tooltipCallback: ((function(number, number):?Element)|undefined), * suggestionsCallback: ((function(!TextUtils.TextRange, !TextUtils.TextRange, boolean=):?Promise.<!UI.SuggestBox.Suggestions>)|undefined), * isWordChar: ((function(string):boolean)|undefined) * }}
diff --git a/third_party/blink/renderer/devtools/front_end/ui/XLink.js b/third_party/blink/renderer/devtools/front_end/ui/XLink.js index e7bdbbc..a29a72af 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/XLink.js +++ b/third_party/blink/renderer/devtools/front_end/ui/XLink.js
@@ -19,9 +19,9 @@ className = className || ''; // clang-format off // TODO(dgozman): migrate css from 'devtools-link' to 'x-link'. - return (UI.Fragment.cached` + return UI.html` <x-link href='${url}' class='${className} devtools-link' ${preventClick ? 'no-click' : ''} - >${linkText.trimMiddle(UI.MaxLengthForDisplayedURLs)}</x-link>`).element(); + >${linkText.trimMiddle(UI.MaxLengthForDisplayedURLs)}</x-link>`; // clang-format on }
diff --git a/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js b/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js index 98791f0c..4e05823 100644 --- a/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js +++ b/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js
@@ -60,6 +60,14 @@ /** * @param {!Workspace.UISourceCode} uiSourceCode + * @return {boolean} + */ + isUISourceCodeModified(uiSourceCode) { + return this._modifiedUISourceCodes.has(uiSourceCode) || this._loadingUISourceCodes.has(uiSourceCode); + } + + /** + * @param {!Workspace.UISourceCode} uiSourceCode * @return {!WorkspaceDiff.WorkspaceDiff.UISourceCodeDiff} */ _uiSourceCodeDiff(uiSourceCode) { @@ -303,4 +311,13 @@ return WorkspaceDiff.WorkspaceDiff._instance; }; +WorkspaceDiff.DiffUILocation = class { + /** + * @param {!Workspace.UISourceCode} uiSourceCode + */ + constructor(uiSourceCode) { + this.uiSourceCode = uiSourceCode; + } +}; + WorkspaceDiff.WorkspaceDiff.UpdateTimeout = 200; \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes index 196e0a51a..3f1964e 100644 --- a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes +++ b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes
@@ -1,2 +1,2 @@ -41de8b8314e09505c2d54694c45e76cbcaba3a7a55aa84bad7be64f79d29ce36 jsdoc_validator.jar -a85a8bc9d70c97eeb9a0c6bbc08687595664941cd54ab3a9dda2ea61691404c0 src +e9e1827178cd3cbef994fca9d1abdb91157ea3ee3f8c1484bfe6611b106df24d jsdoc_validator.jar +7dc86cebcd4d0e7251458410fdcfeea8c26ed2f00c0a06ee4484e4dd37f67e89 src
diff --git a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar index 994218ca..67671149 100644 --- a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar +++ b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar Binary files differ
diff --git a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/ContextTrackingValidationCheck.java b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/ContextTrackingValidationCheck.java index 0e42182c..49f01c3 100644 --- a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/ContextTrackingValidationCheck.java +++ b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/ContextTrackingValidationCheck.java
@@ -132,6 +132,9 @@ Node paramNode = parametersNode.getChildAtIndex(i); String paramText = state.getContext().getNodeText(paramNode); + // Handle rest parameters + if ("...".equals(paramText)) continue; + // Handle default parameters (ES6) String paramName = paramText.split("=")[0].trim(); parameterNames.add(paramName);
diff --git a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/tests/function.js b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/tests/function.js index 1343675..57f27604 100644 --- a/third_party/blink/renderer/devtools/scripts/jsdoc_validator/tests/function.js +++ b/third_party/blink/renderer/devtools/scripts/jsdoc_validator/tests/function.js
@@ -378,3 +378,9 @@ */ returnNumber: function() { } } + +/** + * @param {string} a + * @param {...number} abc + */ +function funcParamsOK3(a, ...abc) {}
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 0f62cf5..c145ca5 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -108,7 +108,7 @@ modification_count_(0), relation_cache_(new AXRelationCache(this)), notification_post_timer_( - document.GetTaskRunner(TaskType::kInternalAccessibility), + document.GetTaskRunner(TaskType::kInternalDefault), this, &AXObjectCacheImpl::NotificationPostTimerFired), accessibility_event_permission_(mojom::PermissionStatus::ASK),
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc index ca66a803..af62f2d 100644 --- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc
@@ -44,8 +44,8 @@ return image_layer_bridge_->GetImage(); } -void ImageBitmapRenderingContextBase::SetUV(const FloatPoint left_top, - const FloatPoint right_bottom) { +void ImageBitmapRenderingContextBase::SetUV(const FloatPoint& left_top, + const FloatPoint& right_bottom) { image_layer_bridge_->SetUV(left_top, right_bottom); }
diff --git a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h index 9935c55e..9e8a823 100644 --- a/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h +++ b/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h
@@ -34,7 +34,7 @@ bool isContextLost() const override { return false; } void SetImage(ImageBitmap*); scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final; - void SetUV(const FloatPoint left_top, const FloatPoint right_bottom); + void SetUV(const FloatPoint& left_top, const FloatPoint& right_bottom); bool IsComposited() const final { return true; } bool IsAccelerated() const final;
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc index f60a23a..bf2a00d 100644 --- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc +++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -38,8 +38,16 @@ #include "third_party/blink/renderer/modules/gamepad/gamepad_list.h" #include "third_party/blink/renderer/modules/vr/navigator_vr.h" +namespace blink { + namespace { +// A button press must have a value at least this large to qualify as a user +// activation. The selected value should be greater than 0.5 so that axes +// incorrectly mapped as triggers do not generate activations in the idle +// position. +const double kButtonActivationThreshold = 0.9; + void HasGamepadConnectionChanged(const String& old_id, const String& new_id, bool old_connected, @@ -55,9 +63,25 @@ *gamepad_lost = id_changed || (old_connected && !new_connected); } -} // namespace +bool HasUserActivation(GamepadList& gamepads) { + // A button press counts as a user activation if the button's value is greater + // than the activation threshold. A threshold is used so that analog buttons + // or triggers do not generate an activation from a light touch. + for (size_t pad_index = 0; pad_index < gamepads.length(); ++pad_index) { + Gamepad* pad = gamepads.item(pad_index); + if (pad) { + const GamepadButtonVector& buttons = pad->buttons(); + for (size_t i = 0; i < buttons.size(); ++i) { + double value = buttons.at(i)->value(); + if (value > kButtonActivationThreshold) + return true; + } + } + } + return false; +} -namespace blink { +} // namespace template <typename T> static void SampleGamepad(unsigned index, @@ -152,6 +176,7 @@ return *supplement; } +// static GamepadList* NavigatorGamepad::getGamepads(Navigator& navigator) { return NavigatorGamepad::From(navigator).Gamepads(); } @@ -167,6 +192,13 @@ } SampleAndCheckConnectedGamepads(); + + // Allow gamepad button presses to qualify as user activations. + if (RuntimeEnabledFeatures::UserActivationV2Enabled() && + GetPage()->IsPageVisible() && HasUserActivation(*gamepads_)) { + Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture); + } + return gamepads_.Get(); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc index cfeac8fc..c144dcf 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -49,6 +49,30 @@ Member<ScriptPromiseResolver> resolver_; }; +class SetParametersRequest : public RTCVoidRequestScriptPromiseResolverImpl { + public: + SetParametersRequest(ScriptPromiseResolver* resolver, RTCRtpSender* sender) + : RTCVoidRequestScriptPromiseResolverImpl(resolver), sender_(sender) {} + + void RequestSucceeded() override { + sender_->ClearLastReturnedParameters(); + RTCVoidRequestScriptPromiseResolverImpl::RequestSucceeded(); + } + + void RequestFailed(const webrtc::RTCError& error) override { + sender_->ClearLastReturnedParameters(); + RTCVoidRequestScriptPromiseResolverImpl::RequestFailed(error); + } + + void Trace(blink::Visitor* visitor) override { + visitor->Trace(sender_); + RTCVoidRequestScriptPromiseResolverImpl::Trace(visitor); + } + + private: + Member<RTCRtpSender> sender_; +}; + bool HasInvalidModification(const RTCRtpParameters& parameters, const RTCRtpParameters& new_parameters) { if (parameters.hasTransactionId() != new_parameters.hasTransactionId() || @@ -296,10 +320,10 @@ "getParameters() needs to be called before setParameters().")); return promise; } - // The specification mentions that some fields in the dictionnary should not + // The specification mentions that some fields in the dictionary should not // be modified. Some of those checks are done in the lower WebRTC layer, but // there is no perfect 1-1 mapping between the Javascript layer and native. - // So we save the last returned dictionnary and enforce the check at this + // So we save the last returned dictionary and enforce the check at this // level instead. if (HasInvalidModification(last_returned_parameters_.value(), parameters)) { resolver->Reject( @@ -321,12 +345,16 @@ degradation_preference = blink::WebRTCDegradationPreference::Balanced; } - auto* request = RTCVoidRequestScriptPromiseResolverImpl::Create(resolver); + auto* request = new SetParametersRequest(resolver, this); sender_->SetParameters(std::move(encodings), degradation_preference.value(), request); return promise; } +void RTCRtpSender::ClearLastReturnedParameters() { + last_returned_parameters_.reset(); +} + ScriptPromise RTCRtpSender::getStats(ScriptState* script_state) { ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise();
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h index 22f0b982..9f655eaf 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
@@ -45,6 +45,7 @@ // Sets the track. This must be called when the |WebRTCRtpSender| has its // track updated, and the |track| must match the |WebRTCRtpSender::Track|. void SetTrack(MediaStreamTrack*); + void ClearLastReturnedParameters(); MediaStreamVector streams() const; void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h b/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h index cb46d3d..eed62be 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h
@@ -12,7 +12,7 @@ class ScriptPromiseResolver; -class RTCVoidRequestScriptPromiseResolverImpl final : public RTCVoidRequest { +class RTCVoidRequestScriptPromiseResolverImpl : public RTCVoidRequest { public: static RTCVoidRequestScriptPromiseResolverImpl* Create( ScriptPromiseResolver*); @@ -24,7 +24,7 @@ void Trace(blink::Visitor*) override; - private: + protected: RTCVoidRequestScriptPromiseResolverImpl(ScriptPromiseResolver*); Member<ScriptPromiseResolver> resolver_;
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc index f04f1d7..6212d2c 100644 --- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc +++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -343,10 +343,12 @@ switch (state_) { case WebRemotePlaybackState::kConnecting: DispatchEvent(Event::Create(EventTypeNames::connecting)); - if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled() && - media_element_->IsHTMLVideoElement()) { - // TODO(xjz): Pass the remote device name. - ToHTMLVideoElement(media_element_)->MediaRemotingStarted(WebString()); + if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) { + if (media_element_->IsHTMLVideoElement()) { + // TODO(xjz): Pass the remote device name. + ToHTMLVideoElement(media_element_)->MediaRemotingStarted(WebString()); + } + media_element_->FlingingStarted(); } break; case WebRemotePlaybackState::kConnected: @@ -354,11 +356,14 @@ break; case WebRemotePlaybackState::kDisconnected: DispatchEvent(Event::Create(EventTypeNames::disconnect)); - if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled() && - media_element_->IsHTMLVideoElement()) { - ToHTMLVideoElement(media_element_) - ->MediaRemotingStopped( - WebLocalizedString::kMediaRemotingStopNoText); + if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) { + if (media_element_->IsHTMLVideoElement()) { + ToHTMLVideoElement(media_element_) + ->MediaRemotingStopped( + WebLocalizedString::kMediaRemotingStopNoText); + } + presentation_id_ = ""; + media_element_->FlingingStopped(); } break; }
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.cc b/third_party/blink/renderer/modules/websockets/dom_websocket.cc index 3f147cb..ff4dcf5 100644 --- a/third_party/blink/renderer/modules/websockets/dom_websocket.cc +++ b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -586,12 +586,10 @@ return state_; } -unsigned DOMWebSocket::bufferedAmount() const { - uint64_t sum = buffered_amount_after_close_ + buffered_amount_; - - if (sum > std::numeric_limits<unsigned>::max()) - return std::numeric_limits<unsigned>::max(); - return sum; +uint64_t DOMWebSocket::bufferedAmount() const { + // TODO(ricea): Check for overflow once machines with exabytes of RAM become + // commonplace. + return buffered_amount_after_close_ + buffered_amount_; } String DOMWebSocket::protocol() const {
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.h b/third_party/blink/renderer/modules/websockets/dom_websocket.h index 01e246e..8a29012 100644 --- a/third_party/blink/renderer/modules/websockets/dom_websocket.h +++ b/third_party/blink/renderer/modules/websockets/dom_websocket.h
@@ -103,7 +103,7 @@ const KURL& url() const; State readyState() const; - unsigned bufferedAmount() const; + uint64_t bufferedAmount() const; String protocol() const; String extensions() const;
diff --git a/third_party/blink/renderer/modules/websockets/websocket.idl b/third_party/blink/renderer/modules/websockets/websocket.idl index 8d23f66..d979eb17 100644 --- a/third_party/blink/renderer/modules/websockets/websocket.idl +++ b/third_party/blink/renderer/modules/websockets/websocket.idl
@@ -49,7 +49,7 @@ const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; - readonly attribute unsigned long bufferedAmount; + readonly attribute unsigned long long bufferedAmount; // networking attribute EventHandler onopen;
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc index 7071d13..6cd2d22 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc +++ b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
@@ -320,9 +320,9 @@ // execution context caused extreme input delay due to processing // multiple frames without yielding, see crbug.com/701444. Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask( - FROM_HERE, WTF::Bind(&XRFrameProvider::ProcessScheduledFrame, - WrapWeakPersistent(this), base::nullopt, - time_delta.InSecondsF())); + FROM_HERE, + WTF::Bind(&XRFrameProvider::ProcessScheduledFrame, + WrapWeakPersistent(this), nullptr, time_delta.InSecondsF())); } void XRFrameProvider::OnNonExclusiveVSync(double timestamp) { @@ -337,7 +337,7 @@ Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask( FROM_HERE, WTF::Bind(&XRFrameProvider::ProcessScheduledFrame, - WrapWeakPersistent(this), base::nullopt, timestamp)); + WrapWeakPersistent(this), nullptr, timestamp)); } void XRFrameProvider::OnNonExclusivePose(device::mojom::blink::VRPosePtr pose) { @@ -396,7 +396,7 @@ } void XRFrameProvider::ProcessScheduledFrame( - base::Optional<device::mojom::blink::VRMagicWindowFrameDataPtr> frame_data, + device::mojom::blink::VRMagicWindowFrameDataPtr frame_data, double timestamp) { DVLOG(2) << __FUNCTION__; @@ -441,7 +441,7 @@ if (frame_data) { // TODO(https://crbug.com/837883): only render background for // sessions that are using AR. - RenderBackgroundImage(frame_data.value(), session); + RenderBackgroundImage(frame_data, session); } if (frame_pose_ && frame_pose_->input_state.has_value()) { @@ -450,8 +450,7 @@ } if (frame_data) { - session->SetNonExclusiveProjectionMatrix( - frame_data.value()->projection_matrix); + session->SetNonExclusiveProjectionMatrix(frame_data->projection_matrix); } std::unique_ptr<TransformationMatrix> pose_matrix =
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_provider.h b/third_party/blink/renderer/modules/xr/xr_frame_provider.h index b1e1402..0109a2a3 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame_provider.h +++ b/third_party/blink/renderer/modules/xr/xr_frame_provider.h
@@ -62,8 +62,7 @@ device::mojom::blink::VRDisplayFrameTransportOptionsPtr); void OnPresentationProviderConnectionError(); void ProcessScheduledFrame( - base::Optional<device::mojom::blink::VRMagicWindowFrameDataPtr> - frame_data, + device::mojom::blink::VRMagicWindowFrameDataPtr frame_data, double timestamp); void RenderBackgroundImage(
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index f00fcccd..bf9ad5b 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1357,6 +1357,8 @@ "text/bidi_run_list.h", "text/bidi_text_run.cc", "text/bidi_text_run.h", + "text/capitalize.cc", + "text/capitalize.h", "text/character.cc", "text/character.h", "text/character_emoji.cc", @@ -1889,6 +1891,7 @@ "testing/tree_test_helpers.h", "text/bidi_resolver_test.cc", "text/bidi_test_harness.h", + "text/capitalize_test.cc", "text/character_test.cc", "text/date_time_format_test.cc", "text/hyphenation_test.cc",
diff --git a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc index 3f055bd4..6ae7b0b 100644 --- a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc +++ b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
@@ -152,6 +152,8 @@ return true; case mojom::FeaturePolicyFeature::kUnsizedMedia: case mojom::FeaturePolicyFeature::kVerticalScroll: + case mojom::FeaturePolicyFeature::kLegacyImageFormats: + case mojom::FeaturePolicyFeature::kImageCompression: return RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled(); default: return false;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc index 93cdc43..4dff05f 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -30,10 +30,12 @@ #include "base/location.h" #include "base/single_thread_task_runner.h" +#include "cc/layers/texture_layer.h" #include "components/viz/common/resources/transferable_resource.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_compositor_support.h" +#include "third_party/blink/public/platform/web_layer.h" #include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h" #include "third_party/blink/renderer/platform/graphics/canvas_metrics.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" @@ -98,7 +100,11 @@ Canvas2DLayerBridge::~Canvas2DLayerBridge() { BeginDestruction(); DCHECK(destruction_in_progress_); - layer_.reset(); + if (layer_) { + web_layer_ = nullptr; + layer_->ClearClient(); + layer_ = nullptr; + } } void Canvas2DLayerBridge::StartRecording() { @@ -298,13 +304,15 @@ } if (resource_provider_ && resource_provider_->IsAccelerated() && !layer_) { - layer_ = - Platform::Current()->CompositorSupport()->CreateExternalTextureLayer( - this); - layer_->SetOpaque(ColorParams().GetOpacityMode() == kOpaque); + layer_ = cc::TextureLayer::CreateForMailbox(this); + layer_->SetIsDrawable(true); + layer_->SetContentsOpaque(ColorParams().GetOpacityMode() == kOpaque); layer_->SetBlendBackgroundColor(ColorParams().GetOpacityMode() != kOpaque); - GraphicsLayer::RegisterContentsLayer(layer_->Layer()); layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality); + web_layer_ = + Platform::Current()->CompositorSupport()->CreateLayerFromCCLayer( + layer_.get()); + GraphicsLayer::RegisterContentsLayer(web_layer_.get()); } if (resource_provider_ && IsHibernating()) { @@ -396,12 +404,12 @@ ResetResourceProvider(); if (layer_ && acceleration_mode_ != kDisableAcceleration) { - GraphicsLayer::UnregisterContentsLayer(layer_->Layer()); + GraphicsLayer::UnregisterContentsLayer(web_layer_.get()); layer_->ClearTexture(); // Orphaning the layer is required to trigger the recration of a new layer // in the case where destruction is caused by a canvas resize. Test: // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html - layer_->Layer()->RemoveFromParent(); + layer_->RemoveFromParent(); } DCHECK(!bytes_allocated_); @@ -654,7 +662,7 @@ DCHECK(!destruction_in_progress_); // Trigger lazy layer creation GetOrCreateResourceProvider(kPreferAcceleration); - return layer_ ? layer_->Layer() : nullptr; + return web_layer_.get(); } void Canvas2DLayerBridge::DidDraw(const FloatRect& rect) { @@ -712,7 +720,7 @@ void Canvas2DLayerBridge::DoPaintInvalidation(const FloatRect& dirty_rect) { DCHECK(!destruction_in_progress_); if (layer_ && acceleration_mode_ != kDisableAcceleration) - layer_->Layer()->InvalidateRect(EnclosingIntRect(dirty_rect)); + layer_->SetNeedsDisplayRect(EnclosingIntRect(dirty_rect)); } scoped_refptr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot(
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h index 7be67ddd..6fd73e7 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -32,7 +32,7 @@ #include "base/memory/weak_ptr.h" #include "build/build_config.h" #include "cc/layers/texture_layer_client.h" -#include "third_party/blink/public/platform/web_external_texture_layer.h" +#include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/geometry/int_size.h" #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource_host.h" @@ -50,12 +50,17 @@ struct SkImageInfo; +namespace cc { +class TextureLayer; +} + namespace blink { class Canvas2DLayerBridgeTest; class CanvasResourceProvider; class SharedContextRateLimiter; class StaticBitmapImage; +class WebLayer; #if defined(OS_MACOSX) // Canvas hibernation is currently disabled on MacOS X due to a bug that causes @@ -181,7 +186,8 @@ std::unique_ptr<CanvasResourceProvider> resource_provider_; std::unique_ptr<PaintRecorder> recorder_; sk_sp<SkImage> hibernation_image_; - std::unique_ptr<WebExternalTextureLayer> layer_; + std::unique_ptr<WebLayer> web_layer_; // Wrapper for |layer_|. + scoped_refptr<cc::TextureLayer> layer_; std::unique_ptr<SharedContextRateLimiter> rate_limiter_; std::unique_ptr<Logger> logger_; int msaa_sample_count_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc index 9bcffdae..ce5db67 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -11,7 +11,6 @@ #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h" -#include "third_party/blink/renderer/platform/graphics/canvas_resource.h" #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -49,13 +48,11 @@ GLuint GetBackingTextureHandleForOverwrite() override { GrBackendTexture backend_texture = GetSkSurface()->getBackendTexture( SkSurface::kDiscardWrite_TextureHandleAccess); - if (!backend_texture.isValid()) { + if (!backend_texture.isValid()) return 0; - } GrGLTextureInfo info; - if (!backend_texture.getGLTextureInfo(&info)) { + if (!backend_texture.getGLTextureInfo(&info)) return 0; - } return info.fID; } @@ -115,7 +112,7 @@ ColorParams().GetSkSurfaceProps()); } - unsigned msaa_sample_count_; + const unsigned msaa_sample_count_; }; // CanvasResourceProviderTextureGpuMemoryBuffer @@ -141,7 +138,7 @@ ~CanvasResourceProviderTextureGpuMemoryBuffer() override = default; - protected: + private: scoped_refptr<CanvasResource> CreateResource() final { return CanvasResourceGpuMemoryBuffer::Create( Size(), ColorParams(), ContextProviderWrapper(), CreateWeakPtr(), @@ -179,6 +176,35 @@ return output_resource; } + + void RecycleResource(scoped_refptr<CanvasResource> resource) override { + DCHECK(resource->HasOneRef()); + if (resource_recycling_enabled_) + recycled_resources_.push_back(std::move(resource)); + } + + void SetResourceRecyclingEnabled(bool value) override { + resource_recycling_enabled_ = value; + if (!resource_recycling_enabled_) + ClearRecycledResources(); + } + + void ClearRecycledResources() { recycled_resources_.clear(); } + + scoped_refptr<CanvasResource> NewOrRecycledResource() { + if (recycled_resources_.size()) { + scoped_refptr<CanvasResource> resource = + std::move(recycled_resources_.back()); + recycled_resources_.pop_back(); + // Recycling implies releasing the old content + resource->WaitSyncTokenBeforeRelease(); + return resource; + } + return CreateResource(); + } + + WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_; + bool resource_recycling_enabled_ = true; }; // CanvasResourceProviderBitmap @@ -212,8 +238,6 @@ kPremul_SkAlphaType, ColorParams().GetSkColorSpaceForSkSurfaces()); return SkSurface::MakeRaster(info, ColorParams().GetSkSurfaceProps()); } - - sk_sp<SkSurface> surface_; }; // CanvasResourceProvider base class implementation @@ -374,9 +398,8 @@ } SkSurface* CanvasResourceProvider::GetSkSurface() const { - if (!surface_) { + if (!surface_) surface_ = CreateSkSurface(); - } return surface_.get(); } @@ -470,29 +493,9 @@ GetSkSurface()->flush(); } -void CanvasResourceProvider::RecycleResource( - scoped_refptr<CanvasResource> resource) { - DCHECK(resource->HasOneRef()); - if (resource_recycling_enabled_) - recycled_resources_.push_back(std::move(resource)); -} - -void CanvasResourceProvider::SetResourceRecyclingEnabled(bool value) { - resource_recycling_enabled_ = value; - if (!resource_recycling_enabled_) - ClearRecycledResources(); -} - -scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() { - if (recycled_resources_.size()) { - scoped_refptr<CanvasResource> resource = - std::move(recycled_resources_.back()); - recycled_resources_.pop_back(); - // Recycling implies releasing the old content - resource->WaitSyncTokenBeforeRelease(); - return resource; - } - return CreateResource(); +void CanvasResourceProvider::RecycleResource(scoped_refptr<CanvasResource>) { + // To be implemented in subclasses that use resource recycling. + NOTREACHED(); } bool CanvasResourceProvider::IsGpuContextLost() const { @@ -515,15 +518,10 @@ // if this wasn't required, but the canvas is currently filled with the magic // transparency color. Can we have another way to manage this? DCHECK(IsValid()); - if (color_params_.GetOpacityMode() == kOpaque) { + if (color_params_.GetOpacityMode() == kOpaque) Canvas()->clear(SK_ColorBLACK); - } else { + else Canvas()->clear(SK_ColorTRANSPARENT); - } -} - -void CanvasResourceProvider::ClearRecycledResources() { - recycled_resources_.clear(); } void CanvasResourceProvider::InvalidateSurface() {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h index 40165aa..c68faf8 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -12,6 +12,7 @@ #include "cc/raster/playback_image_provider.h" #include "third_party/blink/renderer/platform/geometry/int_size.h" #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h" +#include "third_party/blink/renderer/platform/graphics/canvas_resource.h" #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h" @@ -37,7 +38,6 @@ namespace blink { -class CanvasResource; class StaticBitmapImage; class WebGraphicsContext3DProviderWrapper; @@ -93,9 +93,10 @@ virtual bool IsValid() const = 0; virtual bool IsAccelerated() const = 0; uint32_t ContentUniqueID() const; - void ClearRecycledResources(); - void RecycleResource(scoped_refptr<CanvasResource>); - void SetResourceRecyclingEnabled(bool); + + virtual void RecycleResource(scoped_refptr<CanvasResource>); + virtual void SetResourceRecyclingEnabled(bool) {} + SkSurface* GetSkSurface() const; bool IsGpuContextLost() const; bool WritePixels(const SkImageInfo& orig_info, @@ -116,7 +117,6 @@ base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper() { return context_provider_wrapper_; } - scoped_refptr<CanvasResource> NewOrRecycledResource(); SkFilterQuality FilterQuality() const { return filter_quality_; } base::WeakPtr<CanvasResourceProvider> CreateWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); @@ -160,9 +160,7 @@ std::unique_ptr<cc::SkiaPaintCanvas> canvas_; mutable sk_sp<SkSurface> surface_; // mutable for lazy init std::unique_ptr<SkCanvas> xform_canvas_; - WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_; SkFilterQuality filter_quality_; - bool resource_recycling_enabled_ = true; const cc::PaintImage::Id snapshot_paint_image_id_; cc::PaintImage::ContentId snapshot_paint_image_content_id_ =
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 3a48462b..a6c07bb 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -53,6 +53,12 @@ } PaintArtifactCompositor::~PaintArtifactCompositor() { + // TODO(crbug.com/836897, crbug.com/836912): + // In BlinkGenPropertyTrees mode, some of the layers passed from Blink core + // have pre-filled element ID. Need to figure out what is the best place to + // setup them. + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) + return; for (auto child : root_layer_->children()) DCHECK(!child->element_id()); }
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 210d6c3..1c89c15 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -48,7 +48,7 @@ #include "gpu/config/gpu_feature_info.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_compositor_support.h" -#include "third_party/blink/public/platform/web_external_texture_layer.h" +#include "third_party/blink/public/platform/web_layer.h" #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" @@ -190,8 +190,12 @@ DrawingBuffer::~DrawingBuffer() { DCHECK(destruction_in_progress_); SwapPreviousFrameCallback(nullptr); - layer_.reset(); - context_provider_.reset(); + if (layer_) { + web_layer_ = nullptr; + layer_->ClearClient(); + layer_ = nullptr; + } + context_provider_ = nullptr; } bool DrawingBuffer::MarkContentsChanged() { @@ -865,11 +869,10 @@ WebLayer* DrawingBuffer::PlatformLayer() { if (!layer_) { - layer_ = - Platform::Current()->CompositorSupport()->CreateExternalTextureLayer( - this); + layer_ = cc::TextureLayer::CreateForMailbox(this); - layer_->SetOpaque(!want_alpha_channel_); + layer_->SetIsDrawable(true); + layer_->SetContentsOpaque(!want_alpha_channel_); layer_->SetBlendBackgroundColor(want_alpha_channel_); // If premultiplied_alpha_false_texture_ exists, then premultiplied_alpha_ // has already been handled via CopySubTextureCHROMIUM -- the alpha channel @@ -884,10 +887,14 @@ layer_->SetPremultipliedAlpha(premultiplied_alpha_ || premultiplied_alpha_false_texture_); layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality); - GraphicsLayer::RegisterContentsLayer(layer_->Layer()); + + web_layer_ = + Platform::Current()->CompositorSupport()->CreateLayerFromCCLayer( + layer_.get()); + GraphicsLayer::RegisterContentsLayer(web_layer_.get()); } - return layer_->Layer(); + return web_layer_.get(); } void DrawingBuffer::ClearPlatformLayer() { @@ -932,7 +939,7 @@ fbo_ = 0; if (layer_) - GraphicsLayer::UnregisterContentsLayer(layer_->Layer()); + GraphicsLayer::UnregisterContentsLayer(web_layer_.get()); client_ = nullptr; }
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h index 3242b99e..73d6c04 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -64,7 +64,6 @@ class CanvasColorParams; class Extensions3DUtil; class StaticBitmapImage; -class WebExternalTextureLayer; class WebGraphicsContext3DProvider; class WebGraphicsContext3DProviderWrapper; class WebLayer; @@ -563,7 +562,8 @@ bool is_hidden_ = false; SkFilterQuality filter_quality_ = kLow_SkFilterQuality; - std::unique_ptr<WebExternalTextureLayer> layer_; + scoped_refptr<cc::TextureLayer> layer_; + std::unique_ptr<WebLayer> web_layer_; // Wrapper for |layer_|. // Mailboxes that were released by the compositor can be used again by this // DrawingBuffer.
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc index ff9dd43c..1eb9dd0 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h" +#include "cc/layers/texture_layer.h" #include "cc/resources/cross_thread_shared_bitmap.h" #include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/common/resources/bitmap_allocation.h" @@ -11,25 +12,28 @@ #include "gpu/command_buffer/client/gles2_interface.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_compositor_support.h" -#include "third_party/blink/public/platform/web_external_texture_layer.h" #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" +#include "third_party/blink/public/platform/web_layer.h" #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/color_behavior.h" #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" +#include "ui/gfx/geometry/size.h" namespace blink { ImageLayerBridge::ImageLayerBridge(OpacityMode opacity_mode) : opacity_mode_(opacity_mode) { - layer_ = Platform::Current()->CompositorSupport()->CreateExternalTextureLayer( - this); - GraphicsLayer::RegisterContentsLayer(layer_->Layer()); + layer_ = cc::TextureLayer::CreateForMailbox(this); + layer_->SetIsDrawable(true); layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality); if (opacity_mode_ == kOpaque) { - layer_->SetOpaque(true); + layer_->SetContentsOpaque(true); layer_->SetBlendBackgroundColor(false); } + web_layer_ = Platform::Current()->CompositorSupport()->CreateLayerFromCCLayer( + layer_.get()); + GraphicsLayer::RegisterContentsLayer(web_layer_.get()); } ImageLayerBridge::~ImageLayerBridge() { @@ -44,7 +48,7 @@ image_ = std::move(image); if (image_) { if (opacity_mode_ == kNonOpaque) { - layer_->SetOpaque(image_->CurrentFrameKnownToBeOpaque()); + layer_->SetContentsOpaque(image_->CurrentFrameKnownToBeOpaque()); layer_->SetBlendBackgroundColor(!image_->CurrentFrameKnownToBeOpaque()); } } @@ -61,20 +65,20 @@ has_presented_since_last_set_image_ = false; } -void ImageLayerBridge::SetUV(const FloatPoint left_top, - const FloatPoint right_bottom) { +void ImageLayerBridge::SetUV(const FloatPoint& left_top, + const FloatPoint& right_bottom) { if (disposed_) return; - layer_->SetUV(WebFloatPoint(left_top.X(), left_top.Y()), - WebFloatPoint(right_bottom.X(), right_bottom.Y())); + layer_->SetUV(left_top, right_bottom); } void ImageLayerBridge::Dispose() { if (layer_) { - GraphicsLayer::UnregisterContentsLayer(layer_->Layer()); + GraphicsLayer::UnregisterContentsLayer(web_layer_.get()); layer_->ClearTexture(); - layer_.reset(); + web_layer_ = nullptr; + layer_ = nullptr; } image_ = nullptr; disposed_ = true; @@ -216,7 +220,7 @@ } WebLayer* ImageLayerBridge::PlatformLayer() const { - return layer_->Layer(); + return web_layer_.get(); } ImageLayerBridge::RegisteredBitmap::RegisteredBitmap() = default;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h index b58dbb53..5b39341 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h +++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
@@ -14,16 +14,18 @@ #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "ui/gfx/geometry/size.h" namespace cc { class CrossThreadSharedBitmap; +class TextureLayer; +} + +namespace gfx { +class Size; } namespace blink { - class WebLayer; -class WebExternalTextureLayer; class PLATFORM_EXPORT ImageLayerBridge : public GarbageCollectedFinalized<ImageLayerBridge>, @@ -51,7 +53,7 @@ void SetFilterQuality(SkFilterQuality filter_quality) { filter_quality_ = filter_quality; } - void SetUV(const FloatPoint left_top, const FloatPoint right_bottom); + void SetUV(const FloatPoint& left_top, const FloatPoint& right_bottom); bool IsAccelerated() { return image_->IsTextureBacked(); } @@ -85,7 +87,8 @@ bool lost_resource); scoped_refptr<StaticBitmapImage> image_; - std::unique_ptr<WebExternalTextureLayer> layer_; + scoped_refptr<cc::TextureLayer> layer_; + std::unique_ptr<WebLayer> web_layer_; // Wrapper for |layer_|. SkFilterQuality filter_quality_ = kLow_SkFilterQuality; // SharedMemory bitmaps that can be recycled.
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h index 9a40207..1b71d1d 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -226,6 +226,7 @@ SetContentsTo(layer, prevent_contents_opaque_changes); } bool HasContentsLayer() const { return contents_layer_; } + WebLayer* ContentsLayer() const { return contents_layer_; } // For hosting this GraphicsLayer in a native layer hierarchy. WebLayer* PlatformLayer() const; @@ -277,9 +278,6 @@ PaintController& GetPaintController() const; - // Exposed for tests. - WebLayer* ContentsLayer() const { return contents_layer_; } - void SetElementId(const CompositorElementId&); CompositorElementId GetElementId() const;
diff --git a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc index b1c83dd..e7fe70e 100644 --- a/third_party/blink/renderer/platform/graphics/image_frame_generator.cc +++ b/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
@@ -151,6 +151,9 @@ TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", static_cast<int>(index)); + // Lock the mutex, so only one thread can use the decoder at once. + MutexLocker lock(decode_mutex_); + // This implementation does not support arbitrary scaling so check the // requested size. SkISize scaled_size = SkISize::Make(info.width(), info.height()); @@ -226,13 +229,14 @@ const SkISize& scaled_size, SkBitmap::Allocator& allocator, ImageDecoder::AlphaOption alpha_option) { +#if DCHECK_IS_ON() + DCHECK(decode_mutex_.Locked()); +#endif + TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index", static_cast<int>(index)); ImageDecoder* decoder = nullptr; - - // Lock the mutex, so only one thread can use the decoder at once. - MutexLocker lock(decode_mutex_); const bool resume_decoding = ImageDecodingStore::Instance().LockDecoder( this, scaled_size, alpha_option, &decoder); DCHECK(!resume_decoding || decoder);
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/third_party/blink/renderer/platform/graphics/paint/display_item.cc index 9d7fb821..e154076 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item.cc +++ b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -125,6 +125,7 @@ DEBUG_STRING_CASE(ForeignLayerPlugin); DEBUG_STRING_CASE(ForeignLayerVideo); DEBUG_STRING_CASE(ForeignLayerWrapper); + DEBUG_STRING_CASE(ForeignLayerContentsWrapper); DEFAULT_CASE; } }
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h index 80ecd92..96e856e 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item.h +++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -120,7 +120,8 @@ kForeignLayerPlugin, kForeignLayerVideo, kForeignLayerWrapper, - kForeignLayerLast = kForeignLayerWrapper, + kForeignLayerContentsWrapper, + kForeignLayerLast = kForeignLayerContentsWrapper, kClipFirst, kClipBoxPaintPhaseFirst = kClipFirst,
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn index 4614d56..a7fea929 100644 --- a/third_party/blink/renderer/platform/heap/BUILD.gn +++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -51,6 +51,8 @@ "heap_linked_stack.h", "heap_page.cc", "heap_page.h", + "heap_stats_collector.cc", + "heap_stats_collector.h", "heap_terminated_array.h", "heap_terminated_array_builder.h", "heap_traits.h", @@ -111,6 +113,7 @@ "address_cache_test.cc", "blink_gc_memory_dump_provider_test.cc", "heap_compact_test.cc", + "heap_stats_collector_test.cc", "heap_test.cc", "heap_test_utilities.cc", "heap_test_utilities.h",
diff --git a/third_party/blink/renderer/platform/heap/blink_gc.h b/third_party/blink/renderer/platform/heap/blink_gc.h index 65d62de2..1c2f5a50d 100644 --- a/third_party/blink/renderer/platform/heap/blink_gc.h +++ b/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -97,14 +97,15 @@ }; enum GCReason { - kIdleGC, - kPreciseGC, - kConservativeGC, - kForcedGC, - kMemoryPressureGC, - kPageNavigationGC, - kThreadTerminationGC, - kLastGCReason = kThreadTerminationGC, + kIdleGC = 0, + kPreciseGC = 1, + kConservativeGC = 2, + kForcedGC = 3, + kMemoryPressureGC = 4, + kPageNavigationGC = 5, + kThreadTerminationGC = 6, + kTesting = 7, + kLastGCReason = kTesting, }; enum ArenaIndices {
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc index 77c074f..c752d60 100644 --- a/third_party/blink/renderer/platform/heap/heap.cc +++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -40,6 +40,7 @@ #include "third_party/blink/renderer/platform/heap/address_cache.h" #include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h" #include "third_party/blink/renderer/platform/heap/heap_compact.h" +#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" #include "third_party/blink/renderer/platform/heap/marking_visitor.h" #include "third_party/blink/renderer/platform/heap/page_memory.h" #include "third_party/blink/renderer/platform/heap/page_pool.h" @@ -128,6 +129,7 @@ ThreadHeap::ThreadHeap(ThreadState* thread_state) : thread_state_(thread_state), + heap_stats_collector_(std::make_unique<ThreadHeapStatsCollector>()), region_tree_(std::make_unique<RegionTree>()), address_cache_(std::make_unique<AddressCache>()), free_page_pool_(std::make_unique<PagePool>()),
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h index bb25750b..282f2936 100644 --- a/third_party/blink/renderer/platform/heap/heap.h +++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -56,6 +56,7 @@ } // namespace incremental_marking_test class AddressCache; +class ThreadHeapStatsCollector; class PagePool; class RegionTree; @@ -463,6 +464,10 @@ enum SnapshotType { kHeapSnapshot, kFreelistSnapshot }; void TakeSnapshot(SnapshotType); + ThreadHeapStatsCollector* stats_collector() const { + return heap_stats_collector_.get(); + } + #if defined(ADDRESS_SANITIZER) void PoisonEagerArena(); void PoisonAllHeaps(); @@ -496,6 +501,7 @@ ThreadState* thread_state_; ThreadHeapStats stats_; + std::unique_ptr<ThreadHeapStatsCollector> heap_stats_collector_; std::unique_ptr<RegionTree> region_tree_; std::unique_ptr<AddressCache> address_cache_; std::unique_ptr<PagePool> free_page_pool_;
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc index 181745da..1e2fdab 100644 --- a/third_party/blink/renderer/platform/heap/heap_page.cc +++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -36,6 +36,7 @@ #include "third_party/blink/renderer/platform/heap/address_cache.h" #include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h" #include "third_party/blink/renderer/platform/heap/heap_compact.h" +#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" #include "third_party/blink/renderer/platform/heap/marking_verifier.h" #include "third_party/blink/renderer/platform/heap/page_memory.h" #include "third_party/blink/renderer/platform/heap/page_pool.h" @@ -265,16 +266,16 @@ if (GetThreadState()->SweepForbidden()) return nullptr; - TRACE_EVENT0("blink_gc", "BaseArena::lazySweepPages"); - ThreadState::SweepForbiddenScope sweep_forbidden(GetThreadState()); - ScriptForbiddenScope script_forbidden; - - double start_time = WTF::CurrentTimeTicksInMilliseconds(); - Address result = LazySweepPages(allocation_size, gc_info_index); - GetThreadState()->AccumulateSweepingTime( - WTF::CurrentTimeTicksInMilliseconds() - start_time); + Address result = nullptr; + { + ThreadHeapStatsCollector::Scope stats_scope( + GetThreadState()->Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kLazySweepOnAllocation); + ThreadState::SweepForbiddenScope sweep_forbidden(GetThreadState()); + ScriptForbiddenScope script_forbidden; + result = LazySweepPages(allocation_size, gc_info_index); + } ThreadHeap::ReportMemoryUsageForTracing(); - return result; }
diff --git a/third_party/blink/renderer/platform/heap/heap_page.h b/third_party/blink/renderer/platform/heap/heap_page.h index 89943847..39b379c3 100644 --- a/third_party/blink/renderer/platform/heap/heap_page.h +++ b/third_party/blink/renderer/platform/heap/heap_page.h
@@ -954,11 +954,9 @@ #if defined(OS_WIN) static const uintptr_t random2 = ~(RotateLeft16(reinterpret_cast<uintptr_t>(::ReadFile))); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) static const uintptr_t random2 = ~(RotateLeft16(reinterpret_cast<uintptr_t>(::read))); -#else -#error OS not supported #endif #if defined(ARCH_CPU_64_BITS)
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc new file mode 100644 index 0000000..78b62431 --- /dev/null +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
@@ -0,0 +1,105 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" + +#include "base/logging.h" +#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +#include "third_party/blink/renderer/platform/wtf/time.h" + +namespace blink { + +ThreadHeapStatsCollector::Scope::Scope(ThreadHeapStatsCollector* tracer, + ThreadHeapStatsCollector::Scope::Id id) + : tracer_(tracer), + start_time_(WTF::CurrentTimeTicksInMilliseconds()), + id_(id) { + TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("blink_gc"), + ThreadHeapStatsCollector::Scope::ToString(id_)); +} + +ThreadHeapStatsCollector::Scope::~Scope() { + TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("blink_gc"), + ThreadHeapStatsCollector::Scope::ToString(id_)); + tracer_->IncreaseScopeTime( + id_, WTF::CurrentTimeTicksInMilliseconds() - start_time_); +} + +const char* ThreadHeapStatsCollector::Scope::ToString( + ThreadHeapStatsCollector::Scope::Id id) { + switch (id) { + case Scope::kCompleteSweep: + return "BlinkGC.CompleteSweep"; + case Scope::kEagerSweep: + return "BlinkGC.EagerSweep"; + case Scope::kIncrementalMarkingStartMarking: + return "BlinkGC.IncrementalMarkingStartMarking"; + case Scope::kIncrementalMarkingStep: + return "BlinkGC.IncrementalMarkingStep"; + case Scope::kIncrementalMarkingFinalize: + return "BlinkGC.IncrementalMarkingFinalize"; + case Scope::kIncrementalMarkingFinalizeMarking: + return "BlinkGC.IncrementalMarkingFinalizeMarking"; + case Scope::kLazySweepInIdle: + return "BlinkGC.LazySweepInIdle"; + case Scope::kLazySweepOnAllocation: + return "BlinkGC.LazySweepOnAllocation"; + case Scope::kFullGCMarking: + return "BlinkGC.FullGCMarking"; + case Scope::kNumIds: + break; + } + CHECK(false); + return nullptr; +} + +void ThreadHeapStatsCollector::IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::Id id, + double time) { + DCHECK(is_started_); + current_.scope_data[id] += time; +} + +void ThreadHeapStatsCollector::IncreaseMarkedObjectSize(size_t size) { + DCHECK(is_started_); + current_.marked_object_size += size; +} + +void ThreadHeapStatsCollector::Start(BlinkGC::GCReason reason) { + DCHECK(!is_started_); + is_started_ = true; + current_.reason = reason; +} + +void ThreadHeapStatsCollector::Stop() { + is_started_ = false; + previous_ = std::move(current_); + current_.reset(); +} + +void ThreadHeapStatsCollector::Event::reset() { + marked_object_size = 0; + memset(scope_data, 0, sizeof(scope_data)); + reason = BlinkGC::kTesting; +} + +double ThreadHeapStatsCollector::Event::marking_time_in_ms() const { + return scope_data[Scope::kIncrementalMarkingStartMarking] + + scope_data[Scope::kIncrementalMarkingStep] + + scope_data[Scope::kIncrementalMarkingFinalizeMarking] + + scope_data[Scope::kFullGCMarking]; +} + +double ThreadHeapStatsCollector::Event::marking_time_per_byte_in_s() const { + return marked_object_size ? marking_time_in_ms() / 1000 / marked_object_size + : 0.0; +} + +double ThreadHeapStatsCollector::Event::sweeping_time_in_ms() const { + return scope_data[Scope::kCompleteSweep] + scope_data[Scope::kEagerSweep] + + scope_data[Scope::kLazySweepInIdle] + + scope_data[Scope::kLazySweepOnAllocation]; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/third_party/blink/renderer/platform/heap/heap_stats_collector.h new file mode 100644 index 0000000..ef5776a --- /dev/null +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -0,0 +1,85 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_STATS_COLLECTOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_STATS_COLLECTOR_H_ + +#include <stddef.h> + +#include "third_party/blink/renderer/platform/heap/blink_gc.h" +#include "third_party/blink/renderer/platform/platform_export.h" + +namespace blink { + +// Manages counters and statistics across garbage collection cycles. +// +// Usage: +// ThreadHeapStatsCollector stats_collector; +// stats_collector.Start(<BlinkGC::GCReason>); +// // Use tracer. +// // Current event is available using stats_collector.current(). +// stats_collector.Stop(); +// // Previous event is available using stats_collector.previous(). +class PLATFORM_EXPORT ThreadHeapStatsCollector { + public: + // Trace a particular scope. Will emit a trace event and record the time in + // the corresponding ThreadHeapStatsCollector. + class PLATFORM_EXPORT Scope { + public: + // These ids will form human readable names when used in Scopes. + enum Id { + kCompleteSweep, + kEagerSweep, + kIncrementalMarkingStartMarking, + kIncrementalMarkingStep, + kIncrementalMarkingFinalize, + kIncrementalMarkingFinalizeMarking, + kLazySweepInIdle, + kLazySweepOnAllocation, + kFullGCMarking, + kNumIds, + }; + + static const char* ToString(Id); + + Scope(ThreadHeapStatsCollector*, Id); + ~Scope(); + + private: + ThreadHeapStatsCollector* const tracer_; + const double start_time_; + const Id id_; + }; + + struct PLATFORM_EXPORT Event { + void reset(); + + double marking_time_in_ms() const; + double marking_time_per_byte_in_s() const; + double sweeping_time_in_ms() const; + + size_t marked_object_size = 0; + double scope_data[Scope::kNumIds] = {0}; + BlinkGC::GCReason reason; + }; + + void Start(BlinkGC::GCReason); + void Stop(); + + void IncreaseScopeTime(Scope::Id, double); + void IncreaseMarkedObjectSize(size_t); + + bool is_started() const { return is_started_; } + const Event& current() const { return current_; } + const Event& previous() const { return previous_; } + + private: + Event current_; + Event previous_; + bool is_started_ = false; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_STATS_COLLECTOR_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc b/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc new file mode 100644 index 0000000..9db1958 --- /dev/null +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
@@ -0,0 +1,141 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +// ============================================================================= +// ThreadHeapStatsCollector. =================================================== +// ============================================================================= + +TEST(ThreadHeapStatsCollectorTest, InitialEmpty) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + for (int i = 0; i < ThreadHeapStatsCollector::Scope::Id::kNumIds; i++) { + EXPECT_DOUBLE_EQ(0.0, stats_collector.current().scope_data[i]); + } + stats_collector.Stop(); +} + +TEST(ThreadHeapStatsCollectorTest, IncreaseScopeTime) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep, 1.0); + EXPECT_DOUBLE_EQ( + 1.0, stats_collector.current().scope_data + [ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep]); +} + +TEST(ThreadHeapStatsCollectorTest, StopMovesCurrentToPrevious) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep, 1.0); + stats_collector.Stop(); + EXPECT_DOUBLE_EQ( + 1.0, stats_collector.previous().scope_data + [ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep]); +} + +TEST(ThreadHeapStatsCollectorTest, StopResetsCurrent) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep, 1.0); + stats_collector.Stop(); + EXPECT_DOUBLE_EQ( + 0.0, stats_collector.current().scope_data + [ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep]); +} + +TEST(ThreadHeapStatsCollectorTest, StartStop) { + ThreadHeapStatsCollector stats_collector; + EXPECT_FALSE(stats_collector.is_started()); + stats_collector.Start(BlinkGC::kTesting); + EXPECT_TRUE(stats_collector.is_started()); + stats_collector.Stop(); + EXPECT_FALSE(stats_collector.is_started()); +} + +// ============================================================================= +// ThreadHeapStatsCollector::Scope. ============================================ +// ============================================================================= + +TEST(ThreadHeapStatsCollectorTest, ScopeToString) { + EXPECT_STREQ( + "BlinkGC.IncrementalMarkingStartMarking", + ThreadHeapStatsCollector::Scope::ToString( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStartMarking)); +} + +// ============================================================================= +// ThreadHeapStatsCollector::Event. ============================================ +// ============================================================================= + +TEST(ThreadHeapStatsCollectorTest, EventMarkedObjectSize) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseMarkedObjectSize(1024); + stats_collector.Stop(); + EXPECT_EQ(1024u, stats_collector.previous().marked_object_size); +} + +TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeInMsFromIncrementalGC) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStartMarking, 7.0); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep, 2.0); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingFinalizeMarking, 1.0); + // Ignore the full finalization. + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kIncrementalMarkingFinalize, 3.0); + stats_collector.Stop(); + EXPECT_DOUBLE_EQ(10.0, stats_collector.previous().marking_time_in_ms()); +} + +TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeInMsFromFullGC) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kFullGCMarking, 11.0); + stats_collector.Stop(); + EXPECT_DOUBLE_EQ(11.0, stats_collector.previous().marking_time_in_ms()); +} + +TEST(ThreadHeapStatsCollectorTest, EventMarkingTimePerByteInS) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseMarkedObjectSize(1000); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kFullGCMarking, 1000.0); + stats_collector.Stop(); + EXPECT_DOUBLE_EQ(.001, + stats_collector.previous().marking_time_per_byte_in_s()); +} + +TEST(ThreadHeapStatsCollectorTest, SweepingTimeInMs) { + ThreadHeapStatsCollector stats_collector; + stats_collector.Start(BlinkGC::kTesting); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kLazySweepInIdle, 1.0); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kLazySweepInIdle, 2.0); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kLazySweepInIdle, 3.0); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kLazySweepOnAllocation, 4.0); + stats_collector.IncreaseScopeTime( + ThreadHeapStatsCollector::Scope::kCompleteSweep, 5.0); + stats_collector.Stop(); + EXPECT_DOUBLE_EQ(15.0, stats_collector.previous().sweeping_time_in_ms()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc index bc33272d..9d108d9 100644 --- a/third_party/blink/renderer/platform/heap/heap_test.cc +++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -42,6 +42,7 @@ #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap_linked_stack.h" +#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" #include "third_party/blink/renderer/platform/heap/heap_terminated_array_builder.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/marking_visitor.h" @@ -365,6 +366,7 @@ : TestGCCollectGarbageScope(state), atomic_pause_scope_(ThreadState::Current()), persistent_lock_(ProcessHeap::CrossThreadPersistentMutex()) { + ThreadState::Current()->Heap().stats_collector()->Start(BlinkGC::kTesting); ThreadState::Current()->MarkPhasePrologue(state, BlinkGC::kAtomicMarking, BlinkGC::kPreciseGC); }
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc index 31d89242..8a2cf71 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.cc +++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -49,6 +49,7 @@ #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap_buildflags.h" #include "third_party/blink/renderer/platform/heap/heap_compact.h" +#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" #include "third_party/blink/renderer/platform/heap/marking_visitor.h" #include "third_party/blink/renderer/platform/heap/page_pool.h" #include "third_party/blink/renderer/platform/heap/safe_point.h" @@ -106,6 +107,8 @@ return "PageNavigationGC"; case BlinkGC::kThreadTerminationGC: return "ThreadTerminationGC"; + case BlinkGC::kTesting: + return "TestingGC"; } return "<Unknown>"; } @@ -155,7 +158,6 @@ no_allocation_count_(0), gc_forbidden_count_(0), mixins_being_constructed_count_(0), - accumulated_sweeping_time_(0), object_resurrection_forbidden_(false), in_atomic_pause_(false), gc_mixin_marker_(nullptr), @@ -655,20 +657,22 @@ RUNTIME_CALL_TIMER_SCOPE_IF_ISOLATE_EXISTS( GetIsolate(), RuntimeCallStats::CounterId::kPerformIdleLazySweep); - TRACE_EVENT1("blink_gc,devtools.timeline", - "ThreadState::performIdleLazySweep", "idleDeltaInSeconds", - deadline_seconds - CurrentTimeTicksInSeconds()); - - AtomicPauseScope atomic_pause_scope(this); - SweepForbiddenScope scope(this); - - double start_time = WTF::CurrentTimeTicksInMilliseconds(); - bool sweep_completed = Heap().AdvanceLazySweep(deadline_seconds); - // We couldn't finish the sweeping within the deadline. - // We request another idle task for the remaining sweeping. - if (!sweep_completed) - ScheduleIdleLazySweep(); - AccumulateSweepingTime(WTF::CurrentTimeTicksInMilliseconds() - start_time); + bool sweep_completed = false; + { + AtomicPauseScope atomic_pause_scope(this); + SweepForbiddenScope scope(this); + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kLazySweepInIdle); + TRACE_EVENT1("blink_gc,devtools.timeline", + "ThreadState::performIdleLazySweep", "idleDeltaInSeconds", + deadline_seconds - CurrentTimeTicksInSeconds()); + sweep_completed = Heap().AdvanceLazySweep(deadline_seconds); + // We couldn't finish the sweeping within the deadline. + // We request another idle task for the remaining sweeping. + if (!sweep_completed) + ScheduleIdleLazySweep(); + } if (sweep_completed) PostSweep(); @@ -882,6 +886,7 @@ gc_state_ = kNoGCScheduled; SetGCPhase(GCPhase::kSweeping); SetGCPhase(GCPhase::kNone); + Heap().stats_collector()->Stop(); return; } @@ -894,8 +899,6 @@ // a dead object gets resurrected. InvokePreFinalizers(); - accumulated_sweeping_time_ = 0; - EagerSweep(); // Any sweep compaction must happen after pre-finalizers and eager @@ -925,12 +928,10 @@ // by lazy sweeping. Keep those in a designated heap and sweep it // eagerly. DCHECK(IsSweepingInProgress()); - SweepForbiddenScope scope(this); - - double start_time = WTF::CurrentTimeTicksInMilliseconds(); + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), ThreadHeapStatsCollector::Scope::kEagerSweep); Heap().Arena(BlinkGC::kEagerSweepArenaIndex)->CompleteSweep(); - AccumulateSweepingTime(WTF::CurrentTimeTicksInMilliseconds() - start_time); } void ThreadState::CompleteSweep() { @@ -945,24 +946,15 @@ if (SweepForbidden()) return; - AtomicPauseScope atomic_pause_scope(this); - SweepForbiddenScope scope(this); - - TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep"); - double start_time = WTF::CurrentTimeTicksInMilliseconds(); - - Heap().CompleteSweep(); - - double time_for_complete_sweep = - WTF::CurrentTimeTicksInMilliseconds() - start_time; - AccumulateSweepingTime(time_for_complete_sweep); - - if (IsMainThread()) { - DEFINE_STATIC_LOCAL(CustomCountHistogram, complete_sweep_histogram, - ("BlinkGC.CompleteSweep", 1, 10 * 1000, 50)); - complete_sweep_histogram.Count(time_for_complete_sweep); + { + AtomicPauseScope atomic_pause_scope(this); + SweepForbiddenScope scope(this); + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kCompleteSweep); + TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep"); + Heap().CompleteSweep(); } - PostSweep(); } @@ -975,6 +967,31 @@ thread_state_->RemoveObserver(this); } +namespace { + +void UpdateHistograms(const ThreadHeapStatsCollector::Event& event) { + DEFINE_THREAD_SAFE_STATIC_LOCAL( + EnumerationHistogram, gc_reason_histogram, + ("BlinkGC.GCReason", BlinkGC::kLastGCReason + 1)); + gc_reason_histogram.Count(event.reason); + + // TODO(mlippautz): Update name of this histogram. + DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, marking_time_histogram, + ("BlinkGC.CollectGarbage", 0, 10 * 1000, 50)); + marking_time_histogram.Count(event.marking_time_in_ms()); + + DEFINE_STATIC_LOCAL(CustomCountHistogram, complete_sweep_histogram, + ("BlinkGC.CompleteSweep", 1, 10 * 1000, 50)); + complete_sweep_histogram.Count( + event.scope_data[ThreadHeapStatsCollector::Scope::kCompleteSweep]); + + DEFINE_STATIC_LOCAL(CustomCountHistogram, time_for_sweep_histogram, + ("BlinkGC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); + time_for_sweep_histogram.Count(event.sweeping_time_in_ms()); +} + +} // namespace + void ThreadState::PostSweep() { DCHECK(CheckThread()); ThreadHeap::ReportMemoryUsageForTracing(); @@ -1007,10 +1024,6 @@ DEFINE_STATIC_LOCAL(CustomCountHistogram, collection_rate_histogram, ("BlinkGC.CollectionRate", 1, 100, 20)); collection_rate_histogram.Count(static_cast<int>(100 * collection_rate)); - DEFINE_STATIC_LOCAL( - CustomCountHistogram, time_for_sweep_histogram, - ("BlinkGC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); - time_for_sweep_histogram.Count(accumulated_sweeping_time_); #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \ case BlinkGC::k##GCReason: { \ @@ -1040,6 +1053,10 @@ for (auto* const observer : observers_) observer->OnCompleteSweepDone(); + + Heap().stats_collector()->Stop(); + if (IsMainThread()) + UpdateHistograms(Heap().stats_collector()->previous()); } void ThreadState::SafePoint(BlinkGC::StackState stack_state) { @@ -1274,16 +1291,27 @@ VLOG(2) << "[state:" << this << "] " << "IncrementalMarking: Start"; CompleteSweep(); - AtomicPauseScope atomic_pause_scope(this); - MarkPhasePrologue(BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kIncrementalMarking, BlinkGC::kIdleGC); - MarkPhaseVisitRoots(); - EnableIncrementalMarkingBarrier(); - ScheduleIncrementalMarkingStep(); - DCHECK(IsMarkingInProgress()); + // TODO(mlippautz): Replace this with a proper reason once incremental marking + // is actually scheduled in production. + Heap().stats_collector()->Start(BlinkGC::kTesting); + { + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStartMarking); + AtomicPauseScope atomic_pause_scope(this); + MarkPhasePrologue(BlinkGC::kNoHeapPointersOnStack, + BlinkGC::kIncrementalMarking, BlinkGC::kTesting); + MarkPhaseVisitRoots(); + EnableIncrementalMarkingBarrier(); + ScheduleIncrementalMarkingStep(); + DCHECK(IsMarkingInProgress()); + } } void ThreadState::IncrementalMarkingStep() { + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kIncrementalMarkingStep); VLOG(2) << "[state:" << this << "] " << "IncrementalMarking: Step"; AtomicPauseScope atomic_pause_scope(this); @@ -1298,20 +1326,30 @@ } void ThreadState::IncrementalMarkingFinalize() { - VLOG(2) << "[state:" << this << "] " - << "IncrementalMarking: Finalize"; - SetGCState(kNoGCScheduled); - DisableIncrementalMarkingBarrier(); - AtomicPauseScope atomic_pause_scope(this); - DCHECK(IsMarkingInProgress()); - MarkPhaseVisitRoots(); - bool complete = - MarkPhaseAdvanceMarking(std::numeric_limits<double>::infinity()); - CHECK(complete); - MarkPhaseEpilogue(current_gc_data_.marking_type); - PreSweep(current_gc_data_.marking_type, BlinkGC::kLazySweeping); - DCHECK(IsSweepingInProgress()); - DCHECK_EQ(GcState(), kNoGCScheduled); + { + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kIncrementalMarkingFinalize); + VLOG(2) << "[state:" << this << "] " + << "IncrementalMarking: Finalize"; + SetGCState(kNoGCScheduled); + DisableIncrementalMarkingBarrier(); + AtomicPauseScope atomic_pause_scope(this); + DCHECK(IsMarkingInProgress()); + { + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kIncrementalMarkingFinalizeMarking); + MarkPhaseVisitRoots(); + bool complete = + MarkPhaseAdvanceMarking(std::numeric_limits<double>::infinity()); + CHECK(complete); + MarkPhaseEpilogue(current_gc_data_.marking_type); + } + PreSweep(current_gc_data_.marking_type, BlinkGC::kLazySweeping); + DCHECK(IsSweepingInProgress()); + DCHECK_EQ(GcState(), kNoGCScheduled); + } } void ThreadState::CollectGarbage(BlinkGC::StackState stack_state, @@ -1327,7 +1365,6 @@ double start_total_collect_garbage_time = WTF::CurrentTimeTicksInMilliseconds(); - RUNTIME_CALL_TIMER_SCOPE_IF_ISOLATE_EXISTS( GetIsolate(), RuntimeCallStats::CounterId::kCollectGarbage); @@ -1341,8 +1378,8 @@ } // We don't want floating garbage for the specific garbage collection types - // mentioned below. In this case we will follow up with a regular full garbage - // collection. + // mentioned below. In this case we will follow up with a regular full + // garbage collection. const bool should_do_full_gc = !was_incremental_marking || reason == BlinkGC::kForcedGC || reason == BlinkGC::kMemoryPressureGC || @@ -1350,8 +1387,12 @@ if (should_do_full_gc) { CompleteSweep(); SetGCState(kNoGCScheduled); + Heap().stats_collector()->Start(reason); AtomicPauseScope atomic_pause_scope(this); { + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), + ThreadHeapStatsCollector::Scope::kFullGCMarking); TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", "lazySweeping", sweeping_type == BlinkGC::kLazySweeping, "gcReason", GcReasonString(reason)); @@ -1498,9 +1539,6 @@ if (invalidate_dead_objects_in_wrappers_marking_deque_) invalidate_dead_objects_in_wrappers_marking_deque_(isolate_); - DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, marking_time_histogram, - ("BlinkGC.CollectGarbage", 0, 10 * 1000, 50)); - marking_time_histogram.Count(current_gc_data_.marking_time_in_milliseconds); DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, total_object_space_histogram, ("BlinkGC.TotalObjectSpace", 0, 4 * 1024 * 1024, 50)); @@ -1511,10 +1549,6 @@ ("BlinkGC.TotalAllocatedSpace", 0, 4 * 1024 * 1024, 50)); total_allocated_space_histogram.Count(ProcessHeap::TotalAllocatedSpace() / 1024); - DEFINE_THREAD_SAFE_STATIC_LOCAL( - EnumerationHistogram, gc_reason_histogram, - ("BlinkGC.GCReason", BlinkGC::kLastGCReason + 1)); - gc_reason_histogram.Count(current_gc_data_.reason); } void ThreadState::VerifyMarking(BlinkGC::MarkingType marking_type) {
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h index 4f0d530..281b001 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.h +++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -530,10 +530,6 @@ } } - void AccumulateSweepingTime(double time) { - accumulated_sweeping_time_ += time; - } - void FreePersistentNode(PersistentRegion*, PersistentNode*); using PersistentClearCallback = void (*)(void*); @@ -700,7 +696,6 @@ size_t no_allocation_count_; size_t gc_forbidden_count_; size_t mixins_being_constructed_count_; - double accumulated_sweeping_time_; bool object_resurrection_forbidden_; bool in_atomic_pause_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index e99d3d0..f1af7dd6 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -616,6 +616,9 @@ status: "experimental", }, { + name: "IntersectionObserverV2", + }, + { name: "JSImageDecode", status: "stable", },
diff --git a/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc index afb593c2..7ffb883b 100644 --- a/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc
@@ -71,7 +71,6 @@ case TaskType::kInternalUserInteraction: case TaskType::kInternalInspector: case TaskType::kInternalAnimation: - case TaskType::kInternalAccessibility: // UnthrottledTaskRunner is generally discouraged in future. // TODO(nhiroki): Identify which tasks can be throttled / suspendable and // move them into other task runners. See also comments in
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index daea9dfbf..d5643a1 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -286,7 +286,6 @@ case TaskType::kIdleTask: case TaskType::kInternalDefault: case TaskType::kMiscPlatformAPI: - case TaskType::kInternalAccessibility: // TODO(altimin): Move appropriate tasks to throttleable task queue. return TaskRunnerImpl::Create(DeferrableTaskQueue(), type); // PostedMessage can be used for navigation, so we shouldn't defer it
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index 52c2acf..2d70578 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -180,8 +180,6 @@ return "InternalInspector"; case TaskType::kInternalAnimation: return "InternalAnimation"; - case TaskType::kInternalAccessibility: - return "InternalAccessibility"; case TaskType::kCount: return "Count"; }
diff --git a/third_party/blink/renderer/platform/scroll/scrollable_area.cc b/third_party/blink/renderer/platform/scroll/scrollable_area.cc index 7234c646..b7141c8 100644 --- a/third_party/blink/renderer/platform/scroll/scrollable_area.cc +++ b/third_party/blink/renderer/platform/scroll/scrollable_area.cc
@@ -158,6 +158,9 @@ ScrollResult ScrollableArea::UserScroll(ScrollGranularity granularity, const ScrollOffset& delta) { + TRACE_EVENT2("input", "ScrollableArea::UserScroll", "x", delta.Width(), "y", + delta.Height()); + float step_x = ScrollStep(granularity, kHorizontalScrollbar); float step_y = ScrollStep(granularity, kVerticalScrollbar);
diff --git a/third_party/blink/renderer/platform/testing/paint_test_configurations.h b/third_party/blink/renderer/platform/testing/paint_test_configurations.h index c59088f..d434d1a2 100644 --- a/third_party/blink/renderer/platform/testing/paint_test_configurations.h +++ b/third_party/blink/renderer/platform/testing/paint_test_configurations.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_PAINT_TEST_CONFIGURATIONS_H_ #include <gtest/gtest.h> +#include "third_party/blink/public/web/web_heap.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" namespace blink { @@ -33,6 +34,10 @@ ScopedSlimmingPaintV2ForTest(GetParam() & kSlimmingPaintV2), ScopedPaintUnderInvalidationCheckingForTest( GetParam() & kUnderInvalidationChecking) {} + ~PaintTestConfigurations() { + // Must destruct all objects before toggling back feature flags. + WebHeap::CollectAllGarbageForTesting(); + } }; static constexpr unsigned kAllSlimmingPaintTestConfigurations[] = {
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/third_party/blink/renderer/platform/testing/testing_platform_support.cc index dce88ae7..63622fa1 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support.cc +++ b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -103,10 +103,6 @@ cc::ContentLayerClient*) { return nullptr; } -std::unique_ptr<WebExternalTextureLayer> -TestingCompositorSupport::CreateExternalTextureLayer(cc::TextureLayerClient*) { - return nullptr; -} std::unique_ptr<WebImageLayer> TestingCompositorSupport::CreateImageLayer() { return nullptr;
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.h b/third_party/blink/renderer/platform/testing/testing_platform_support.h index 1866a96a..fae881d 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support.h +++ b/third_party/blink/renderer/platform/testing/testing_platform_support.h
@@ -58,8 +58,6 @@ std::unique_ptr<WebLayer> CreateLayerFromCCLayer(cc::Layer*) override; std::unique_ptr<WebContentLayer> CreateContentLayer( cc::ContentLayerClient*) override; - std::unique_ptr<WebExternalTextureLayer> CreateExternalTextureLayer( - cc::TextureLayerClient*) override; std::unique_ptr<WebImageLayer> CreateImageLayer() override; std::unique_ptr<WebScrollbarLayer> CreateScrollbarLayer( std::unique_ptr<WebScrollbar>,
diff --git a/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc b/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc index 6ad79fe..4dbe3b2 100644 --- a/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc +++ b/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc
@@ -60,7 +60,7 @@ // TODO(ccameron): This likely causes surface invariant violations. layer_tree_host_->SetViewportSizeAndScale( gfx_size, layer_tree_host_->device_scale_factor(), - layer_tree_host_->local_surface_id()); + layer_tree_host_->local_surface_id_from_parent()); } void WebLayerTreeViewImplForTesting::SetRootLayer(const blink::WebLayer& root) {
diff --git a/third_party/blink/renderer/platform/text/capitalize.cc b/third_party/blink/renderer/platform/text/capitalize.cc new file mode 100644 index 0000000..858ef83 --- /dev/null +++ b/third_party/blink/renderer/platform/text/capitalize.cc
@@ -0,0 +1,60 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/text/capitalize.h" + +#include "third_party/blink/renderer/platform/text/text_break_iterator.h" +#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h" +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +String Capitalize(const String& string, UChar previous_character) { + if (string.IsNull()) + return string; + + unsigned length = string.length(); + const StringImpl& input = *string.Impl(); + + CHECK_LT(length, std::numeric_limits<unsigned>::max()); + StringBuffer<UChar> string_with_previous(length + 1); + string_with_previous[0] = previous_character == kNoBreakSpaceCharacter + ? kSpaceCharacter + : previous_character; + for (unsigned i = 1; i < length + 1; i++) { + // Replace   with a real space since ICU no longer treats   as a + // word separator. + if (input[i - 1] == kNoBreakSpaceCharacter) + string_with_previous[i] = kSpaceCharacter; + else + string_with_previous[i] = input[i - 1]; + } + + TextBreakIterator* boundary = + WordBreakIterator(string_with_previous.Characters(), length + 1); + if (!boundary) + return string; + + StringBuilder result; + result.ReserveCapacity(length); + + int32_t end_of_word; + int32_t start_of_word = boundary->first(); + for (end_of_word = boundary->next(); end_of_word != kTextBreakDone; + start_of_word = end_of_word, end_of_word = boundary->next()) { + if (start_of_word) { // Ignore first char of previous string + result.Append( + input[start_of_word - 1] == kNoBreakSpaceCharacter + ? kNoBreakSpaceCharacter + : WTF::Unicode::ToTitleCase(string_with_previous[start_of_word])); + } + for (int i = start_of_word + 1; i < end_of_word; i++) + result.Append(input[i - 1]); + } + + return result.ToString(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/text/capitalize.h b/third_party/blink/renderer/platform/text/capitalize.h new file mode 100644 index 0000000..0490579b --- /dev/null +++ b/third_party/blink/renderer/platform/text/capitalize.h
@@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_CAPITALIZE_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_CAPITALIZE_H_ + +#include <unicode/utypes.h> +#include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/forward.h" + +namespace blink { + +// Capitalize (titlecase) each word of a string. +// https://drafts.csswg.org/css-text-3/#valdef-text-transform-capitalize +PLATFORM_EXPORT String Capitalize(const String&, + UChar previous_character = ' '); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_CAPITALIZE_H_
diff --git a/third_party/blink/renderer/platform/text/capitalize_test.cc b/third_party/blink/renderer/platform/text/capitalize_test.cc new file mode 100644 index 0000000..ffa15f97 --- /dev/null +++ b/third_party/blink/renderer/platform/text/capitalize_test.cc
@@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/text/capitalize.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/text/character.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +struct CapitalizeTestData { + String input; + String expected; + UChar previous_character = kSpaceCharacter; +}; + +class CapitalizeTest : public testing::Test, + public testing::WithParamInterface<CapitalizeTestData> { +}; + +INSTANTIATE_TEST_CASE_P(CapitalizeTest, + CapitalizeTest, + testing::Values(CapitalizeTestData{String(), String()}, + CapitalizeTestData{"", ""}, + CapitalizeTestData{"hello, world", + "Hello, World"})); + +TEST_P(CapitalizeTest, Data) { + const auto& data = GetParam(); + EXPECT_EQ(data.expected, Capitalize(data.input, data.previous_character)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/text/text_run_test.cc b/third_party/blink/renderer/platform/text/text_run_test.cc index 4dd4b1e0..4ec66b1 100644 --- a/third_party/blink/renderer/platform/text/text_run_test.cc +++ b/third_party/blink/renderer/platform/text/text_run_test.cc
@@ -8,29 +8,23 @@ namespace blink { -#if defined(THREAD_SANITIZER) -#define MAYBE_IndexOfSubRun DISABLED_IndexOfSubRun // https://crbug.com/830648 -#else -#define MAYBE_IndexOfSubRun IndexOfSubRun -#endif - -TEST(TextRunTest, MAYBE_IndexOfSubRun) { - TextRun run(String("1234567890")); +TEST(TextRunTest, IndexOfSubRun) { + TextRun run("1234567890"); EXPECT_EQ(0u, run.IndexOfSubRun(run.SubRun(0, 4))); EXPECT_EQ(4u, run.IndexOfSubRun(run.SubRun(4, 4))); EXPECT_EQ(6u, run.IndexOfSubRun(run.SubRun(6, 4))); const unsigned kNotSubRun = std::numeric_limits<unsigned>::max(); EXPECT_EQ(kNotSubRun, run.IndexOfSubRun(run.SubRun(7, 4))); - EXPECT_EQ(kNotSubRun, run.IndexOfSubRun(TextRun(String("1")))); - EXPECT_EQ(kNotSubRun, run.IndexOfSubRun(TextRun(String(u"1")))); + EXPECT_EQ(kNotSubRun, run.IndexOfSubRun(TextRun("1"))); + EXPECT_EQ(kNotSubRun, run.IndexOfSubRun(TextRun(u"1"))); - TextRun run16(String(u"1234567890")); + TextRun run16(u"1234567890"); EXPECT_EQ(0u, run16.IndexOfSubRun(run16.SubRun(0, 4))); EXPECT_EQ(4u, run16.IndexOfSubRun(run16.SubRun(4, 4))); EXPECT_EQ(6u, run16.IndexOfSubRun(run16.SubRun(6, 4))); EXPECT_EQ(kNotSubRun, run16.IndexOfSubRun(run16.SubRun(7, 4))); - EXPECT_EQ(kNotSubRun, run16.IndexOfSubRun(TextRun(String("1")))); - EXPECT_EQ(kNotSubRun, run16.IndexOfSubRun(TextRun(String(u"1")))); + EXPECT_EQ(kNotSubRun, run16.IndexOfSubRun(TextRun("1"))); + EXPECT_EQ(kNotSubRun, run16.IndexOfSubRun(TextRun(u"1"))); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/web_thread.cc b/third_party/blink/renderer/platform/web_thread.cc index 15d7408..5d100e6 100644 --- a/third_party/blink/renderer/platform/web_thread.cc +++ b/third_party/blink/renderer/platform/web_thread.cc
@@ -10,7 +10,7 @@ #if defined(OS_WIN) #include <windows.h> -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <unistd.h> #endif @@ -36,7 +36,7 @@ #if defined(OS_WIN) static_assert(sizeof(blink::PlatformThreadId) >= sizeof(DWORD), "size of platform thread id is too small"); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) static_assert(sizeof(blink::PlatformThreadId) >= sizeof(pid_t), "size of platform thread id is too small"); #else
diff --git a/third_party/blink/renderer/platform/wtf/byte_order.h b/third_party/blink/renderer/platform/wtf/byte_order.h index 94b64640..c6cb57e8 100644 --- a/third_party/blink/renderer/platform/wtf/byte_order.h +++ b/third_party/blink/renderer/platform/wtf/byte_order.h
@@ -33,7 +33,7 @@ #include "build/build_config.h" -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) #include <arpa/inet.h> #endif
diff --git a/third_party/blink/renderer/platform/wtf/threading_primitives.h b/third_party/blink/renderer/platform/wtf/threading_primitives.h index 7777fe9..12c24ab 100644 --- a/third_party/blink/renderer/platform/wtf/threading_primitives.h +++ b/third_party/blink/renderer/platform/wtf/threading_primitives.h
@@ -41,15 +41,19 @@ #if defined(OS_WIN) #include <windows.h> -#endif - -#if defined(OS_POSIX) +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) #include <pthread.h> #endif namespace WTF { -#if defined(OS_POSIX) +#if defined(OS_WIN) +struct PlatformMutex { + CRITICAL_SECTION internal_mutex_; + size_t recursion_count_; +}; +typedef CONDITION_VARIABLE PlatformCondition; +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) struct PlatformMutex { pthread_mutex_t internal_mutex_; #if DCHECK_IS_ON() @@ -57,15 +61,6 @@ #endif }; typedef pthread_cond_t PlatformCondition; -#elif defined(OS_WIN) -struct PlatformMutex { - CRITICAL_SECTION internal_mutex_; - size_t recursion_count_; -}; -typedef CONDITION_VARIABLE PlatformCondition; -#else -typedef void* PlatformMutex; -typedef void* PlatformCondition; #endif class WTF_EXPORT MutexBase {
diff --git a/third_party/blink/renderer/platform/wtf/threading_pthreads.cc b/third_party/blink/renderer/platform/wtf/threading_pthreads.cc index 57e06ed..cf4f983 100644 --- a/third_party/blink/renderer/platform/wtf/threading_pthreads.cc +++ b/third_party/blink/renderer/platform/wtf/threading_pthreads.cc
@@ -32,7 +32,7 @@ #include "build/build_config.h" -#if defined(OS_POSIX) +#if defined(OS_POSIX) || defined(OS_FUCHSIA) #include <errno.h> #include <limits.h> @@ -270,4 +270,4 @@ } // namespace WTF -#endif // defined(OS_POSIX) +#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
diff --git a/third_party/blink/tools/blinkpy/common/base85.py b/third_party/blink/tools/blinkpy/common/base85.py new file mode 100644 index 0000000..7d57140 --- /dev/null +++ b/third_party/blink/tools/blinkpy/common/base85.py
@@ -0,0 +1,43 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +_BASE85_CHARACTERS = ('0123456789' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '!#$%&()*+-;<=>?@^_`{|}~') + +# pylint: disable=invalid-name +_char_to_value = {} + + +def decode_base85(encoded_str): + """Decodes a base85 string. + + The input string length must be a multiple of 5, and the resultant + binary length is always a multiple of 4. + """ + if len(encoded_str) % 5 != 0: + raise ValueError('Input string length is not a multiple of 5; ' + + str(len(encoded_str))) + if not _char_to_value: + for i, ch in enumerate(_BASE85_CHARACTERS): + _char_to_value[ch] = i + + result = '' + i = 0 + while i < len(encoded_str): + acc = 0 + for _ in range(5): + ch = encoded_str[i] + if ch not in _char_to_value: + raise ValueError('Invalid base85 character; "{}"'.format(ch)) + new_acc = acc * 85 + _char_to_value[ch] + assert new_acc >= acc + acc = new_acc + i += 1 + for _ in range(4): + result += chr(acc >> 24) + acc = (acc & 0x00ffffff) << 8 + assert acc >= 0 + return result
diff --git a/third_party/blink/tools/blinkpy/common/base85_unittest.py b/third_party/blink/tools/blinkpy/common/base85_unittest.py new file mode 100644 index 0000000..165c8cb --- /dev/null +++ b/third_party/blink/tools/blinkpy/common/base85_unittest.py
@@ -0,0 +1,28 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import unittest + +from blinkpy.common.base85 import decode_base85 + + +class TestBase85(unittest.TestCase): + + def test_decode(self): + self.assertEqual(decode_base85('cmV?d00001'), 'x\x01\x03\x00\x00\x00\x00\x01') + + def test_decode_invalid_input(self): + self.assertRaises(ValueError, decode_base85, '1') + self.assertRaises(ValueError, decode_base85, '123456') + self.assertRaises(ValueError, decode_base85, ' 2345') + self.assertRaises(ValueError, decode_base85, '1234/') + + def test_decode_corners(self): + self.assertEqual(decode_base85(''), '') + self.assertEqual(decode_base85('00000'), '\x00\x00\x00\x00') + self.assertEqual(decode_base85('|NsC0'), '\xFF\xFF\xFF\xFF') + + # acc will be larger than 0xFFFFFFFF. Such input is invalid. + self.assertRaises(ValueError, decode_base85, '|NsC1') + self.assertRaises(ValueError, decode_base85, '~~~~~')
diff --git a/third_party/blink/tools/blinkpy/common/pretty_diff.py b/third_party/blink/tools/blinkpy/common/pretty_diff.py new file mode 100644 index 0000000..6c706746 --- /dev/null +++ b/third_party/blink/tools/blinkpy/common/pretty_diff.py
@@ -0,0 +1,492 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Prettifies 'git diff' output. + +prettify_diff() takes a diff string, and returns an HTML string decorating the +diff. + +This code doesn't support other diff commands such as "diff" and "svn diff". +""" + + +import base64 +import cgi +import difflib +import mimetypes +import re +import zlib + +from blinkpy.common.base85 import decode_base85 + + +# The style below is meant to be similar to PolyGerrit. +_LEADING_HTML = """<!DOCTYPE html> +<meta charset="UTF-8"> +<style> +body { + background: white; + font-family: "Roboto Mono", Menlo, "Lucida Console", Monaco, monospace; +} +table { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin-top: 1em; +} +td { white-space: pre-wrap; font-size: 14px; } +.fileheader { position: sticky; top: 0px; } +.fileheader div { + background: #eee; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + box-sizing: border-box; + line-height: 2.25em; + padding: 0.2em 1rem 0.2em 1rem; +} +.rename { color: #999999; display: block; } +.fileinfo { background: #fafafa; color: #3a66d9; } +.filehooter div { border-top: 1px solid #ddd; } +.hunkheader { background: rgb(255, 247, 212); color: #757575; } +.lineno { + background: #fafafa; + box-sizing: border-box; + color: #666; + padding: 0 0.5em; + text-align: right; + vertical-align: top; + width: 94px; +} +.emptylineno { box-sizing: border-box; width: 94px; } +.code { border-left: 1px solid #ddd; word-break: break-all; } +.del { background: #ffeeee; } +.del.strong { background: #ffcaca; } +.add { background: #eeffee; } +.add.strong { background: #caffca; } +.binary { padding: 8px; border-left: 1px solid #ddd; } +pre { white-space: pre-wrap; font-size: 14px; } +</style> +<body> +""" + + +def prettify_diff(diff_str): + diff_lines = diff_str.split('\n') + # List of DiffFile instances + diff_files = [] + + diff_file, diff_lines = DiffFile.parse(diff_lines) + while diff_file: + diff_files.append(diff_file) + diff_file, diff_lines = DiffFile.parse(diff_lines) + + result_html = _LEADING_HTML + for diff_file in diff_files: + result_html += diff_file.prettify() + + # If diff_lines still has unconsumed lines, this code has a bug or the input + # diff is broken. We show the raw diff in such case. + if diff_lines: + result_html += '<pre>' + for line in diff_lines: + result_html += cgi.escape(line) + '\n' + result_html += '</pre>' + + return result_html + '</body>\n' + + +class DiffFile(object): + """Represents diff for a single file. + + An instance of this class contains one of the following: + - Text hunks + - Two binary hunks + - Meta information + """ + LINK_BASE_URL = 'https://chromium.googlesource.com/chromium/src/+/master/' + + def __init__(self, old_name, new_name, hunks=None, binaries=None, info=None): + assert old_name or new_name + assert bool(hunks) + bool(binaries) + bool(info) == 1 + self._old_name = old_name + self._new_name = new_name + self._hunks = hunks + self._binaries = binaries + self._info = info + + def prettify(self): + status = 'M' + pretty_name = self._linkify(self._new_name) + additional_info = '' + if self._old_name == '': + status = 'A' + pretty_name = cgi.escape(self._new_name) + elif self._new_name == '': + status = 'D' + pretty_name = self._linkify(self._old_name) + elif self._old_name != self._new_name: + status = 'R' + pretty_name = cgi.escape(self._new_name) + additional_info = ('\n<span class=rename>Renamed from {}</span>' + .format(self._linkify(self._old_name))) + + result_html = ('\n<table>\n<tr><td colspan=3 class=fileheader><div>' + + status + ' ' + pretty_name + additional_info + '</div>') + + if self._hunks: + for hunk in self._hunks: + result_html += hunk.prettify() + elif self._info: + result_html += '<tr><td colspan=3 class=fileinfo>{}</tr>'.format( + cgi.escape('\n'.join(self._info))) + else: + old_binary, new_binary = self._binaries # pylint: disable=unpacking-non-sequence + if self._old_name and old_binary: + result_html += old_binary.prettify(self._mime_from_name(self._old_name), 'del') + if self._new_name and new_binary: + result_html += new_binary.prettify(self._mime_from_name(self._new_name), 'add') + return result_html + '<tr><td colspan=3 class=filehooter><div></div></table>\n' + + def _linkify(self, name): + return '<a href="{url}" target="_new">{anchor}</a>'.format( + url=DiffFile.LINK_BASE_URL + cgi.escape(name), anchor=cgi.escape(name)) + + def _mime_from_name(self, name): + mime_type, _ = mimetypes.guess_type(name) + return mime_type if mime_type else 'application/octet-stream' + + @staticmethod + def parse(lines): + """Parses diff lines, and creates a DiffFile instance. + + Finds a file diff header, creates a single DiffFile instance, and + returns a tuple of the DiffFile instance and unconsumed lines. If a file + diff isn't found, (None, lines) is returned. + """ + diff_command_re = r'diff (?:-[^ ]+ )*a/([^ ]+) b/([^ ]+)' + old_name = None + new_name = None + info_lines = None + found_diff_command_line = False + for i, line in enumerate(lines): + if not found_diff_command_line: + match = re.match(diff_command_re, line) + if not match: + continue + old_name = match.group(1) + new_name = match.group(2) + info_lines = [] + found_diff_command_line = True + continue + + match = re.match(r'(GIT binary patch|--- ([^ ]+).*)', line) + if match: + if match.group(0) == 'GIT binary patch': + return DiffFile._parse_binaries(lines[i + 1:], old_name, new_name) + return DiffFile._parse_text_hunks(lines[i:], old_name, new_name) + + index_match = re.match(r'^index ([0-9a-f]+)\.\.([0-9a-f]+).*', line) + if index_match: + # Adjusts old_name and new_name for file addition/removal. + old_name, new_name = DiffFile._adjust_names(index_match, old_name, new_name) + continue + + diff_match = re.match(diff_command_re, line) + if diff_match: + # There are no hunks. Renaming without any modification, + # or adding/removing an empty file. + return (DiffFile(old_name, new_name, info=info_lines), lines[i:]) + + # File mode, rename summary, etc. + info_lines.append(line) + + if found_diff_command_line and info_lines: + return (DiffFile(old_name, new_name, info=info_lines), []) + return (None, lines) + + @staticmethod + def _parse_binaries(lines, old_name, new_name): + new_binary, remaining_lines = BinaryHunk.parse(lines) + old_binary, remaining_lines = BinaryHunk.parse(remaining_lines) + return (DiffFile(old_name, new_name, binaries=(old_binary, new_binary)), + remaining_lines) + + @staticmethod + def _parse_text_hunks(lines, old_name, new_name): + line = lines[0] + if len(lines) < 2: + raise ValueError('"+++ " line is missing after "{}"'.format(line)) + next_line = lines[1] + if not next_line.startswith('+++ '): + raise ValueError('"+++ " line is missing after "{}"'.format(line)) + hunks, remaining_lines = DiffHunk.parse(lines[2:]) + return (DiffFile(old_name, new_name, hunks=hunks), remaining_lines) + + @staticmethod + def _adjust_names(match, old_name, new_name): + old_index = match.group(1) + new_index = match.group(2) + if old_index and re.match(r'^0+$', old_index): + old_name = '' + if new_index and re.match(r'^0+$', new_index): + new_name = '' + return (old_name, new_name) + + +class DiffHunk(object): + """Represents a single text hunk, starting with '@@ -d,d +d,d @@'. + + This class also has code to detect character-level diff. + """ + + def __init__(self, old_start, new_start, context, lines): + self._old_start = old_start + self._new_start = new_start + self._context = '' + if context: + self._context = context + if self._context.startswith(' '): + self._context = self._context[1:] + self._lines = lines + # _annotations is a list of None or a list of tuples. + # A tuple consists of start index and end index, and it represents a + # modified part of a line, which should be highlighted in the pretty + # diff. + self._annotations = [None for _ in self._lines] + for deleted_index, inserted_index in self._find_operations(self._lines): + DiffHunk._annotate_character_diff(self._lines, deleted_index, + inserted_index, self._annotations) + + @staticmethod + def _find_operations(lines): + """Finds 'operations' in the hunk. + + A hunk contains one or more operations, and an operation is one of the + followings: + - Replace operation: '-' lines, followed by '+' lines + - Delete operation: '-' lines, not followed by '+' lines + - Insertion operation: '+' lines + """ + # List of tuples which consist of (list of '-' line index, list of '+' line index) + operations = [] + inserted_index = [] + deleted_index = [] + for i, line in enumerate(lines): + if line[0] == ' ': + if deleted_index or inserted_index: + operations.append((deleted_index, inserted_index)) + deleted_index = [] + inserted_index = [] + elif line[0] == '-': + if inserted_index: + operations.append((deleted_index, inserted_index)) + deleted_index = [] + inserted_index = [] + deleted_index.append(i) + else: + assert line[0] == '+' + inserted_index.append(i) + if deleted_index or inserted_index: + operations.append((deleted_index, inserted_index)) + return operations + + @staticmethod + def _annotate_character_diff(lines, deleted_index, inserted_index, annotations): + assert len(lines) == len(annotations) + if not deleted_index: + for i in inserted_index: + annotations[i] = [(0, len(lines[i]) - 1)] + return + + if not inserted_index: + for i in deleted_index: + annotations[i] = [(0, len(lines[i]) - 1)] + return + + deleted_str = ''.join([lines[i][1:] for i in deleted_index]) + inserted_str = ''.join([lines[i][1:] for i in inserted_index]) + matcher = difflib.SequenceMatcher(None, deleted_str, inserted_str) + for tag, d_start, d_end, i_start, i_end in matcher.get_opcodes(): + if tag == 'delete': + DiffHunk._annotate(lines, deleted_index[0], + d_start, d_end, annotations) + elif tag == 'insert': + DiffHunk._annotate(lines, inserted_index[0], + i_start, i_end, annotations) + elif tag == 'replace': + DiffHunk._annotate(lines, deleted_index[0], + d_start, d_end, annotations) + DiffHunk._annotate(lines, inserted_index[0], + i_start, i_end, annotations) + + @staticmethod + def _annotate(lines, index, start, end, annotations): + assert index < len(lines) + line_len = len(lines[index]) - 1 + if line_len == 0 and start == 0: + annotations[index] = [(0, 0)] + DiffHunk._annotate(lines, index + 1, start, end, annotations) + return + if start >= line_len: + DiffHunk._annotate(lines, index + 1, start - line_len, + end - line_len, annotations) + return + if not annotations[index]: + annotations[index] = [] + annotations[index].append((start, min(line_len, end))) + if end > line_len: + DiffHunk._annotate(lines, index + 1, 0, end - line_len, annotations) + + def prettify_code(self, index, klass): + line = self._lines[index][1:] + annotation = self._annotations[index] + if not annotation: + return '<td class="code {klass}">{code}'.format( + klass=klass, code=cgi.escape(line)) + + start, end = annotation[0] + if start == 0 and end == len(line): + return '<td class="code {klass} strong">{code}'.format( + klass=klass, code=cgi.escape(line)) + + i = 0 + result_html = '<td class="code {}">'.format(klass) + for start, end in annotation: + result_html += cgi.escape(line[i:start]) + result_html += '<span class="{} strong">'.format(klass) + result_html += cgi.escape(line[start:end]) + result_html += '</span>' + i = end + return result_html + cgi.escape(line[i:]) + + def prettify(self): + result_html = ('<tr><td class=hunkheader>@@<td class=hunkheader>@@' + '<td class=hunkheader>{}</tr>\n').format(self._context) + old_lineno = self._old_start + new_lineno = self._new_start + for i, line in enumerate(self._lines): + if line[0] == ' ': + result_html += ('<tr><td class=lineno>{old_lineno}<td ' + 'class=lineno>{new_lineno}<td class=code>{code}' + '</tr>\n').format(old_lineno=old_lineno, + new_lineno=new_lineno, + code=cgi.escape(line[1:])) + old_lineno += 1 + new_lineno += 1 + elif line[0] == '-': + result_html += '<tr><td class=lineno>{lineno}<td class=emptylineno>{code}</tr>\n'.format( + lineno=old_lineno, code=self.prettify_code(i, 'del')) + old_lineno += 1 + else: + assert line[0] == '+' + result_html += '<tr><td class=emptylineno><td class=lineno>{lineno}{code}</tr>\n'.format( + lineno=new_lineno, code=self.prettify_code(i, 'add')) + new_lineno += 1 + return result_html + + @staticmethod + def parse(lines): + """Parses diff lines, and creates a sequence of DiffHunk instances. + + Finds a hunk header, creates a sequence of DiffHunk instances, and + returns a tuple of the DiffHunk list and unconsumed lines. If a hunk + header isn't found, ValueError is raised. + """ + old_start = None + new_start = None + context = None + hunk_lines = None + hunks = [] + hunk_header_re = r'^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@(.*)?' + found_hunk_header = False + for i, line in enumerate(lines): + if not found_hunk_header: + match = re.match(hunk_header_re, line) + if match: + found_hunk_header = True + old_start = int(match.group(1)) + new_start = int(match.group(2)) + context = match.group(3) + hunk_lines = [] + continue + if line.startswith((' ', '-', '+')): + hunk_lines.append(line) + continue + hunks.append(DiffHunk(old_start, new_start, context, hunk_lines)) + match = re.match(hunk_header_re, line) + if not match: + return (hunks, lines[i:]) + old_start = int(match.group(1)) + new_start = int(match.group(2)) + context = match.group(3) + hunk_lines = [] + if found_hunk_header: + hunks.append(DiffHunk(old_start, new_start, context, hunk_lines)) + else: + raise ValueError('Found no hunks') + return (hunks, []) + + +class BinaryHunk(object): + """Represents a binary hunk. + + A binary diff for a single file contains two binary hunks. An + instance of this class represents a single binary hunk. + """ + + def __init__(self, bin_type, size, bin_data): + assert bin_type in ('literal', 'delta') + self._type = bin_type + self._size = size + self._compressed_data = bin_data + + def prettify(self, mime_type, klass): + result_html = ('<tr><td class=emptylineno><td class=emptylineno>' + '<td class="{klass} strong binary">Binary {type}; {size}' + ' Bytes<br>\n').format(klass=klass, type=self._type, + size=self._size) + if self._type == 'delta': + # Because we can assume the input diff is always produced by git, we + # can obtain the original blob, apply the delta, and render both of + # the original blob and the patched blob. However, we're not sure + # how much it is worth to do. + # + # For 'delta' format, see patch_delta() in patch-delta.c. + # https://github.com/git/git/blob/master/patch-delta.c + return result_html + 'We don\'t support rendering a delta binary hunk.' + if mime_type.startswith('image/'): + return result_html + '<img src="data:{type};base64,{data}">'.format( + type=mime_type, data=base64.b64encode(zlib.decompress(self._compressed_data))) + return result_html + 'We don\'t support rendering {} binary.'.format(mime_type) + + @staticmethod + def parse(lines): + """Creates a BinaryHunk instance starting with lines[0]. + + Returns a tuple of the BinaryHunk instance and unconsumed lines. + """ + match = re.match(r'(literal|delta) (\d+)', lines[0]) + if not match: + raise ValueError('No "literal <size>" or "delta <size>".') + bin_type = match.group(1) + size = int(match.group(2)) + bin_data = '' + + lines = lines[1:] + for i, line in enumerate(lines): + if len(line) == 0: + return (BinaryHunk(bin_type, size, bin_data), lines[i + 1:]) + line_length_letter = line[0] + # Map a letter to a number. + # A-Z -> 1-26 + # a-z -> 27-52 + line_length = 1 + ord(line_length_letter) - ord('A') + if line_length_letter >= 'a': + line_length = 27 + ord(line_length_letter) - ord('a') + if line_length * 5 > (len(line) - 1) * 4: + raise ValueError('Base85 length mismatch: length by the first ' + 'letter:{}, actual:{}, line:"{}"'.format( + line_length * 5, (len(line) - 1) * 4, line)) + bin_data += decode_base85(line[1:])[0:line_length] + raise ValueError('No blank line terminating a binary hunk.')
diff --git a/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py b/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py new file mode 100644 index 0000000..3aae9fd --- /dev/null +++ b/third_party/blink/tools/blinkpy/common/pretty_diff_unittest.py
@@ -0,0 +1,194 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import re +import unittest + +from blinkpy.common.pretty_diff import BinaryHunk, DiffFile, DiffHunk + + +# This test contains tests for protected methods. +# pylint: disable=protected-access + +class TestFileDiff(unittest.TestCase): + + def _assert_file_status(self, diff, status): + html = diff.prettify() + match = re.search(r'\b([A-Z]) ', html) + self.assertTrue(match and match.group(1) == status) + + def test_empty_input(self): + lines = [] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNone(diff) + self.assertEquals(remaining_lines, []) + + def test_100percent_similarity(self): + # crrev.com/c576df77d72abe47154ff2489bb035aa20892f7f + lines = ['diff --git a/platform/modules/offscreencanvas/OWNERS b/platform/modules/frame_sinks/OWNERS', + 'similarity index 100%', + 'rename from platform/modules/offscreencanvas/OWNERS', + 'rename to platform/modules/frame_sinks/OWNERS', + 'diff --git a/platform/modules/frame_sinks/embedded_frame_sink.mojom ' + + 'b/platform/modules/frame_sinks/embedded_frame_sink.mojom'] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines[0], lines[4]) + + def test_emptify_text(self): + lines = ['diff --git a/third_party/blink/text-to-zero.txt b/third_party/blink/text-to-zero.txt', + 'index 2262de0..e69de29 100644', + '--- a/third_party/blink/text-to-zero.txt', + '+++ b/third_party/blink/text-to-zero.txt', + '@@ -1 +0,0 @@', + '-hoge'] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'M') + + def test_remove_text(self): + lines = ['diff --git a/text-to-be-removed.txt b/text-to-be-removed.txt', + 'deleted file mode 100644', + 'index 2262de0..0000000', + '--- a/text-to-be-removed.txt', + '+++ /dev/null', + '@@ -1 +0,0 @@', + '-hoge'] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'D') + + def test_remove_zero_byte_text(self): + lines = ['diff --git a/text-zero.txt b/text-zero.txt', + 'deleted file mode 100644', + 'index e69de29..0000000'] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'D') + + def test_add_empty_text(self): + lines = ['diff --git a/text-zero.txt b/text-zero.txt', + 'new file mode 100644', + 'index 0000000..e69de29'] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'A') + + def test_emptify_binary(self): + lines = ['diff --git a/binary-to-zero.png b/binary-to-zero.png', + 'index 9b56f1c6942441578b0585d8b9688fdfcb2aa3fd..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644', + 'GIT binary patch', + 'literal 0', + 'HcmV?d00001', + '', + 'literal 6', + 'NcmZSh&&2%iKL7{~0|Ed5', + ''] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'M') + + def test_remove_binary(self): + lines = ['diff --git a/binary-to-be-removed.png b/binary-to-be-removed.png', + 'deleted file mode 100644', + 'index 9b56f1c6942441578b0585d8b9688fdfcb2aa3fd..0000000000000000000000000000000000000000', + 'GIT binary patch', + 'literal 0', + 'HcmV?d00001', + '', + 'literal 6', + 'NcmZSh&&2%iKL7{~0|Ed5', + ''] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'D') + + def test_add_binary(self): + lines = ['diff --git a/binary-to-zero.png b/binary-to-zero.png', + 'new file mode 100644', + 'index 0000000000000000000000000000000000000000..9b56f1c6942441578b0585d8b9688fdfcb2aa3fd', + 'GIT binary patch', + 'literal 6', + 'NcmZSh&&2%iKL7{~0|Ed5', + '', + 'literal 0', + 'HcmV?d00001', + ''] + diff, remaining_lines = DiffFile.parse(lines) + self.assertIsNotNone(diff) + self.assertEquals(remaining_lines, []) + self._assert_file_status(diff, 'A') + + +class TestDiffHunk(unittest.TestCase): + + def test_find_operations(self): + self.assertEquals(DiffHunk._find_operations([]), []) + self.assertEquals(DiffHunk._find_operations([' ']), []) + + self.assertEquals(DiffHunk._find_operations(['-']), [([0], [])]) + self.assertEquals(DiffHunk._find_operations(['-', '-']), [([0, 1], [])]) + self.assertEquals(DiffHunk._find_operations([' ', '-', '-']), + [([1, 2], [])]) + self.assertEquals(DiffHunk._find_operations(['-', '-', ' ']), + [([0, 1], [])]) + + self.assertEquals(DiffHunk._find_operations(['+']), [([], [0])]) + self.assertEquals(DiffHunk._find_operations(['+', '+']), [([], [0, 1])]) + self.assertEquals(DiffHunk._find_operations([' ', '+', '+']), + [([], [1, 2])]) + self.assertEquals(DiffHunk._find_operations(['+', '+', ' ']), + [([], [0, 1])]) + + self.assertEquals(DiffHunk._find_operations(['-', '+']), [([0], [1])]) + self.assertEquals(DiffHunk._find_operations(['-', '-', '+', '+']), + [([0, 1], [2, 3])]) + self.assertEquals(DiffHunk._find_operations([' ', '-', '-', '+']), + [([1, 2], [3])]) + self.assertEquals(DiffHunk._find_operations(['-', '-', '+', '+', ' ']), + [([0, 1], [2, 3])]) + self.assertEquals(DiffHunk._find_operations(['-', '-', '+', '+', '-']), + [([0, 1], [2, 3]), ([4], [])]) + self.assertEquals(DiffHunk._find_operations(['-', '+', '-', '+']), + [([0], [1]), ([2], [3])]) + + def _annotate(self, lines, index, start, end): + annotations = [None for _ in lines] + DiffHunk._annotate(lines, index, start, end, annotations) + return annotations + + def test_annotate(self): + self.assertEquals(self._annotate(['-abcdef'], 0, 2, 4), + [[(2, 4)]]) + self.assertEquals(self._annotate(['-abcdef', '-ghi'], 0, 2, 6), + [[(2, 6)], None]) + self.assertEquals(self._annotate(['-abcdef', '-ghi'], 0, 2, 7), + [[(2, 6)], [(0, 1)]]) + self.assertEquals(self._annotate(['-abcdef', '-ghi', '-jkl'], 0, 2, 11), + [[(2, 6)], [(0, 3)], [(0, 2)]]) + self.assertEquals(self._annotate(['+', '+abc', ' de'], 0, 0, 2), + [[(0, 0)], [(0, 2)], None]) + + +class TestBinaryHunk(unittest.TestCase): + + def test_literal_image(self): + lines = ['literal 6', 'NcmZSh&&2%iKL7{~0|Ed5', '', 'literal 0...'] + binary, remaining_lines = BinaryHunk.parse(lines) + self.assertIsNotNone(binary) + self.assertEquals(remaining_lines[0], lines[3]) + self.assertTrue('data:image/png;base64,' in binary.prettify('image/png', 'add')) + + def test_literal_non_image(self): + lines = ['literal 6', 'NcmZSh&&2%iKL7{~0|Ed5', ''] + binary, remaining_lines = BinaryHunk.parse(lines) + self.assertIsNotNone(binary) + self.assertEquals(remaining_lines, []) + self.assertTrue('<img ' not in binary.prettify('application/octet-stream', 'del'))
diff --git a/third_party/blink/tools/blinkpy/common/prettypatch.py b/third_party/blink/tools/blinkpy/common/prettypatch.py deleted file mode 100644 index 1c61077..0000000 --- a/third_party/blink/tools/blinkpy/common/prettypatch.py +++ /dev/null
@@ -1,65 +0,0 @@ -# Copyright (c) 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import os -import tempfile - - -class PrettyPatch(object): - - def __init__(self, executive): - self._executive = executive - - def pretty_diff_file(self, diff): - # Diffs can contain multiple text files of different encodings - # so we always deal with them as byte arrays, not unicode strings. - assert isinstance(diff, str) - pretty_diff = self.pretty_diff(diff) - diff_file = tempfile.NamedTemporaryFile(suffix='.html') - diff_file.write(pretty_diff) - diff_file.flush() - return diff_file - - def pretty_diff(self, diff): - # prettify.rb will hang forever if given no input. - # Avoid the hang by returning an empty string. - if not diff: - return '' - - pretty_patch_path = os.path.join(os.path.dirname(__file__), '..', '..', - 'blinkruby') - prettify_path = os.path.join(pretty_patch_path, 'prettify.rb') - args = [ - 'ruby', - '-I', - pretty_patch_path, - prettify_path, - ] - # PrettyPatch does not modify the encoding of the diff output - # so we can't expect it to be utf-8. - return self._executive.run_command(args, input=diff, decode_output=False)
diff --git a/third_party/blink/tools/blinkpy/tool/commands/pretty_diff.py b/third_party/blink/tools/blinkpy/tool/commands/pretty_diff.py index 5236aa03..54c22121 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/pretty_diff.py +++ b/third_party/blink/tools/blinkpy/tool/commands/pretty_diff.py
@@ -29,9 +29,10 @@ import logging import optparse import sys +import tempfile import urllib -from blinkpy.common.prettypatch import PrettyPatch +from blinkpy.common.pretty_diff import prettify_diff from blinkpy.common.system.executive import ScriptError from blinkpy.tool.commands.command import Command @@ -66,9 +67,8 @@ if not self._tool.user.can_open_url(): return None try: - pretty_patch = PrettyPatch(self._tool.executive) patch = self._diff(options) - pretty_diff_file = pretty_patch.pretty_diff_file(patch) + pretty_diff_file = PrettyDiff._pretty_diff_file(patch) self._open_pretty_diff(pretty_diff_file.name) # We return the pretty_diff_file here because we need to keep the # file alive until the user has had a chance to confirm the diff. @@ -85,6 +85,16 @@ return self._tool.git().create_patch(options.git_commit, changed_files=changed_files) + @staticmethod + def _pretty_diff_file(diff): + # Diffs can contain multiple text files of different encodings + # so we always deal with them as byte arrays, not unicode strings. + assert isinstance(diff, str) + diff_file = tempfile.NamedTemporaryFile(suffix='.html') + diff_file.write(prettify_diff(diff)) + diff_file.flush() + return diff_file + def _open_pretty_diff(self, file_path): url = 'file://%s' % urllib.quote(file_path) self._tool.user.open_url(url)
diff --git a/third_party/blink/tools/blinkruby/PrettyPatch.rb b/third_party/blink/tools/blinkruby/PrettyPatch.rb deleted file mode 100644 index 3345cbf..0000000 --- a/third_party/blink/tools/blinkruby/PrettyPatch.rb +++ /dev/null
@@ -1,980 +0,0 @@ -require 'cgi' -require 'diff' -require 'open3' -require 'open-uri' -require 'pp' -require 'set' -require 'tempfile' - -module PrettyPatch - -public - - GIT_PATH = "git" - - def self.prettify(string) - $last_prettify_file_count = -1 - $last_prettify_part_count = { "remove" => 0, "add" => 0, "shared" => 0, "binary" => 0, "extract-error" => 0 } - string = normalize_line_ending(string) - str = "#{HEADER}<body>\n" - - # Just look at the first line to see if it is an SVN revision number as added - # by blink_tool.py for git checkouts. - $svn_revision = 0 - string.each_line do |line| - match = /^Subversion\ Revision: (\d*)$/.match(line) - unless match.nil? - str << "<span class='revision'>#{match[1]}</span>\n" - $svn_revision = match[1].to_i; - end - break - end - - fileDiffs = FileDiff.parse(string) - - $last_prettify_file_count = fileDiffs.length - str << fileDiffs.collect{ |diff| diff.to_html }.join - str << "</body></html>" - end - - def self.filename_from_diff_header(line) - DIFF_HEADER_FORMATS.each do |format| - match = format.match(line) - return match[1] unless match.nil? - end - nil - end - - def self.diff_header?(line) - RELAXED_DIFF_HEADER_FORMATS.any? { |format| line =~ format } - end - -private - DIFF_HEADER_FORMATS = [ - /^Index: (.*)\r?$/, - /^diff --git "?a\/.+"? "?b\/(.+)"?\r?$/, - /^\+\+\+ ([^\t]+)(\t.*)?\r?$/ - ] - - RELAXED_DIFF_HEADER_FORMATS = [ - /^Index:/, - /^diff/ - ] - - BINARY_FILE_MARKER_FORMAT = /^Cannot display: file marked as a binary type.$/ - - IMAGE_FILE_MARKER_FORMAT = /^svn:mime-type = image\/png$/ - - GIT_INDEX_MARKER_FORMAT = /^index ([0-9a-f]{40})\.\.([0-9a-f]{40})/ - - GIT_BINARY_FILE_MARKER_FORMAT = /^GIT binary patch$/ - - GIT_BINARY_PATCH_FORMAT = /^(literal|delta) \d+$/ - - GIT_LITERAL_FORMAT = /^literal \d+$/ - - GIT_DELTA_FORMAT = /^delta \d+$/ - - START_OF_BINARY_DATA_FORMAT = /^[0-9a-zA-Z\+\/=]{20,}/ # Assume 20 chars without a space is base64 binary data. - - START_OF_SECTION_FORMAT = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@\s*(.*)/ - - START_OF_EXTENT_STRING = "%c" % 0 - END_OF_EXTENT_STRING = "%c" % 1 - - # We won't search for intra-line diffs in lines longer than this length, to avoid hangs. See <http://webkit.org/b/56109>. - MAXIMUM_INTRALINE_DIFF_LINE_LENGTH = 10000 - - SMALLEST_EQUAL_OPERATION = 3 - - OPENSOURCE_URL = "https://chromium.googlesource.com/chromium/src/+/master/" - - IMAGE_CHECKSUM_ERROR = "INVALID: Image lacks a checksum. This will fail with a MISSING error in run_web_tests.py. Always generate new png files using run_web_tests.py." - - def self.normalize_line_ending(s) - if RUBY_VERSION >= "1.9" - # Transliteration table from http://stackoverflow.com/a/6609998 - transliteration_table = { '\xc2\x82' => ',', # High code comma - '\xc2\x84' => ',,', # High code double comma - '\xc2\x85' => '...', # Tripple dot - '\xc2\x88' => '^', # High carat - '\xc2\x91' => '\x27', # Forward single quote - '\xc2\x92' => '\x27', # Reverse single quote - '\xc2\x93' => '\x22', # Forward double quote - '\xc2\x94' => '\x22', # Reverse double quote - '\xc2\x95' => ' ', - '\xc2\x96' => '-', # High hyphen - '\xc2\x97' => '--', # Double hyphen - '\xc2\x99' => ' ', - '\xc2\xa0' => ' ', - '\xc2\xa6' => '|', # Split vertical bar - '\xc2\xab' => '<<', # Double less than - '\xc2\xbb' => '>>', # Double greater than - '\xc2\xbc' => '1/4', # one quarter - '\xc2\xbd' => '1/2', # one half - '\xc2\xbe' => '3/4', # three quarters - '\xca\xbf' => '\x27', # c-single quote - '\xcc\xa8' => '', # modifier - under curve - '\xcc\xb1' => '' # modifier - under line - } - encoded_string = s.force_encoding('UTF-8').encode('UTF-16', :invalid => :replace, :replace => '', :fallback => transliteration_table).encode('UTF-8') - encoded_string.gsub /\r\n?/, "\n" - else - s.gsub /\r\n?/, "\n" - end - end - - def self.linkifyFilename(filename) - "<a href='#{OPENSOURCE_URL}#{filename}'>#{filename}</a>" - end - - - HEADER =<<EOF -<html> -<head> -<style> -:link, :visited { - text-decoration: none; - border-bottom: 1px dotted; -} - -:link { - color: #039; -} - -.FileDiff { - background-color: #f8f8f8; - border: 1px solid #ddd; - font-family: monospace; - margin: 1em 0; - position: relative; -} - -h1 { - color: #333; - font-family: sans-serif; - font-size: 1em; - margin-left: 0.5em; - display: table-cell; - width: 100%; - padding: 0.5em; -} - -h1 :link, h1 :visited { - color: inherit; -} - -h1 :hover { - color: #555; - background-color: #eee; -} - -.DiffLinks { - float: right; -} - -.FileDiffLinkContainer { - opacity: 0; - display: table-cell; - padding-right: 0.5em; - white-space: nowrap; -} - -.DiffSection { - background-color: white; - border: solid #ddd; - border-width: 1px 0px; -} - -.ExpansionLine, .LineContainer { - white-space: nowrap; -} - -.sidebyside .DiffBlockPart.add:first-child { - float: right; -} - -.LineSide, -.sidebyside .DiffBlockPart.remove, -.sidebyside .DiffBlockPart.add { - display:inline-block; - width: 50%; - vertical-align: top; -} - -.sidebyside .resizeHandle { - width: 5px; - height: 100%; - cursor: move; - position: absolute; - top: 0; - left: 50%; -} - -.sidebyside .resizeHandle:hover { - background-color: grey; - opacity: 0.5; -} - -.sidebyside .DiffBlockPart.remove .to, -.sidebyside .DiffBlockPart.add .from { - display: none; -} - -.lineNumber, .expansionLineNumber { - border-bottom: 1px solid #998; - border-right: 1px solid #ddd; - color: #444; - display: inline-block; - padding: 1px 5px 0px 0px; - text-align: right; - vertical-align: bottom; - width: 3em; -} - -.lineNumber { - background-color: #eed; -} - -.expansionLineNumber { - background-color: #eee; -} - -.text { - padding-left: 5px; - white-space: pre-wrap; - word-wrap: break-word; -} - -.image { - border: 2px solid black; -} - -.context, .context .lineNumber { - color: #849; - background-color: #fef; -} - -.Line.add, .FileDiff .add { - background-color: #dfd; -} - -.Line.add ins { - background-color: #9e9; - text-decoration: none; -} - -.Line.remove, .FileDiff .remove { - background-color: #fdd; -} - -.Line.remove del { - background-color: #e99; - text-decoration: none; -} - -/* Support for inline comments */ - -.author { - font-style: italic; -} - -.comment { - position: relative; -} - -.comment textarea { - height: 6em; -} - -.overallComments textarea { - height: 2em; - max-width: 100%; - min-width: 200px; -} - -.comment textarea, .overallComments textarea { - display: block; - width: 100%; -} - -.overallComments .open { - -webkit-transition: height .2s; - height: 4em; -} - -#statusBubbleContainer.wrap { - display: block; -} - -#toolbar { - display: -webkit-flex; - display: -moz-flex; - padding: 3px; - left: 0; - right: 0; - border: 1px solid #ddd; - background-color: #eee; - font-family: sans-serif; - position: fixed; - bottom: 0; -} - -#toolbar .actions { - float: right; -} - -.winter { - position: fixed; - z-index: 5; - left: 0; - right: 0; - top: 0; - bottom: 0; - background-color: black; - opacity: 0.8; -} - -.inactive { - display: none; -} - -.lightbox { - position: fixed; - z-index: 6; - left: 10%; - right: 10%; - top: 10%; - bottom: 10%; - background: white; -} - -.lightbox iframe { - width: 100%; - height: 100%; -} - -.commentContext .lineNumber { - background-color: yellow; -} - -.selected .lineNumber { - background-color: #69F; - border-bottom-color: #69F; - border-right-color: #69F; -} - -.ExpandLinkContainer { - opacity: 0; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; -} - -.ExpandArea { - margin: 0; -} - -.ExpandText { - margin-left: 0.67em; -} - -.LinkContainer { - font-family: sans-serif; - font-size: small; - font-style: normal; - -webkit-transition: opacity 0.5s; -} - -.LinkContainer a { - border: 0; -} - -.LinkContainer label:after, -.LinkContainer a:after { - content: " | "; - color: black; -} - -.LinkContainer a:last-of-type:after { - content: ""; -} - -.LinkContainer label { - color: #039; -} - -.help { - color: gray; - font-style: italic; -} - -#message { - font-size: small; - font-family: sans-serif; -} - -.commentStatus { - font-style: italic; -} - -.comment, .previousComment, .frozenComment { - background-color: #ffd; -} - -.overallComments { - -webkit-flex: 1; - -moz-flex: 1; - margin-right: 3px; -} - -.previousComment, .frozenComment { - border: inset 1px; - padding: 5px; - white-space: pre-wrap; -} - -.comment button { - width: 6em; -} - -div:focus { - outline: 1px solid blue; - outline-offset: -1px; -} - -.statusBubble { - /* The width/height get set to the bubble contents via postMessage on browsers that support it. */ - width: 450px; - height: 20px; - margin: 2px 2px 0 0; - border: none; - vertical-align: middle; -} - -.revision { - display: none; -} - -.autosave-state { - position: absolute; - right: 0; - top: -1.3em; - padding: 0 3px; - outline: 1px solid #DDD; - color: #8FDF5F; - font-size: small; - background-color: #EEE; -} - -.autosave-state:empty { - outline: 0px; -} -.autosave-state.saving { - color: #E98080; -} - -.clear_float { - clear: both; -} -</style> -</head> -EOF - - def self.revisionOrDescription(string) - case string - when /\(revision \d+\)/ - /\(revision (\d+)\)/.match(string)[1] - when /\(.*\)/ - /\((.*)\)/.match(string)[1] - end - end - - def self.has_image_suffix(filename) - filename =~ /\.(png|jpg|gif)$/ - end - - class FileDiff - def initialize(lines) - @filename = PrettyPatch.filename_from_diff_header(lines[0].chomp) - startOfSections = 1 - for i in 0...lines.length - case lines[i] - when /^--- / - @from = PrettyPatch.revisionOrDescription(lines[i]) - when /^\+\+\+ / - @filename = PrettyPatch.filename_from_diff_header(lines[i].chomp) if @filename.nil? - @to = PrettyPatch.revisionOrDescription(lines[i]) - startOfSections = i + 1 - break - when BINARY_FILE_MARKER_FORMAT - @binary = true - if (IMAGE_FILE_MARKER_FORMAT.match(lines[i + 1]) or PrettyPatch.has_image_suffix(@filename)) then - @image = true - startOfSections = i + 2 - for x in startOfSections...lines.length - # Binary diffs often have property changes listed before the actual binary data. Skip them. - if START_OF_BINARY_DATA_FORMAT.match(lines[x]) then - startOfSections = x - break - end - end - end - break - when GIT_INDEX_MARKER_FORMAT - @git_indexes = [$1, $2] - when GIT_BINARY_FILE_MARKER_FORMAT - @binary = true - if (GIT_BINARY_PATCH_FORMAT.match(lines[i + 1]) and PrettyPatch.has_image_suffix(@filename)) then - @git_image = true - startOfSections = i + 1 - end - break - end - end - lines_with_contents = lines[startOfSections...lines.length] - @sections = DiffSection.parse(lines_with_contents) unless @binary - if @image and not lines_with_contents.empty? - @image_url = "data:image/png;base64," + lines_with_contents.join - @image_checksum = FileDiff.read_checksum_from_png(lines_with_contents.join.unpack("m").join) - elsif @git_image - begin - raise "index line is missing" unless @git_indexes - - chunks = nil - for i in 0...lines_with_contents.length - if lines_with_contents[i] =~ /^$/ - chunks = [lines_with_contents[i + 1 .. -1], lines_with_contents[0 .. i]] - break - end - end - - raise "no binary chunks" unless chunks - - from_filepath = FileDiff.extract_contents_of_from_revision(@filename, chunks[0], @git_indexes[0]) - to_filepath = FileDiff.extract_contents_of_to_revision(@filename, chunks[1], @git_indexes[1], from_filepath, @git_indexes[0]) - filepaths = from_filepath, to_filepath - - binary_contents = filepaths.collect { |filepath| File.exists?(filepath) ? File.read(filepath) : nil } - @image_urls = binary_contents.collect { |content| (content and not content.empty?) ? "data:image/png;base64," + [content].pack("m") : nil } - @image_checksums = binary_contents.collect { |content| FileDiff.read_checksum_from_png(content) } - rescue - $last_prettify_part_count["extract-error"] += 1 - @image_error = "Exception raised during decoding git binary patch:<pre>#{CGI.escapeHTML($!.to_s + "\n" + $!.backtrace.join("\n"))}</pre>" - ensure - File.unlink(from_filepath) if (from_filepath and File.exists?(from_filepath)) - File.unlink(to_filepath) if (to_filepath and File.exists?(to_filepath)) - end - end - nil - end - - def image_to_html - if not @image_url then - return "<span class='text'>Image file removed</span>" - end - - image_checksum = "" - if @image_checksum - image_checksum = @image_checksum - elsif @filename.include? "-expected.png" and @image_url - image_checksum = IMAGE_CHECKSUM_ERROR - end - - return "<p>" + image_checksum + "</p><img class='image' src='" + @image_url + "' />" - end - - def to_html - str = "<div class='FileDiff'>\n" - str += "<h1>#{PrettyPatch.linkifyFilename(@filename)}</h1>\n" - if @image then - str += self.image_to_html - elsif @git_image then - if @image_error - str += @image_error - else - for i in (0...2) - image_url = @image_urls[i] - image_checksum = @image_checksums[i] - - style = ["remove", "add"][i] - str += "<p class=\"#{style}\">" - - if image_checksum - str += image_checksum - elsif @filename.include? "-expected.png" and image_url - str += IMAGE_CHECKSUM_ERROR - end - - str += "<br>" - - if image_url - str += "<img class='image' src='" + image_url + "' />" - else - str += ["</p>Added", "</p>Removed"][i] - end - end - end - elsif @binary then - $last_prettify_part_count["binary"] += 1 - str += "<span class='text'>Binary file, nothing to see here</span>" - else - str += @sections.collect{ |section| section.to_html }.join("<br>\n") unless @sections.nil? - end - - if @from then - str += "<span class='revision'>" + @from + "</span>" - end - - str += "</div>\n" - end - - def self.parse(string) - haveSeenDiffHeader = false - linesForDiffs = [] - string.each_line do |line| - if (PrettyPatch.diff_header?(line)) - linesForDiffs << [] - haveSeenDiffHeader = true - elsif (!haveSeenDiffHeader && line =~ /^--- /) - linesForDiffs << [] - haveSeenDiffHeader = false - end - linesForDiffs.last << line unless linesForDiffs.last.nil? - end - - linesForDiffs.collect { |lines| FileDiff.new(lines) } - end - - def self.read_checksum_from_png(png_bytes) - # Ruby 1.9 added the concept of string encodings, so to avoid treating binary data as UTF-8, - # we can force the encoding to binary at this point. - if RUBY_VERSION >= "1.9" - png_bytes.force_encoding('binary') - end - match = png_bytes && png_bytes.match(/tEXtchecksum\0([a-fA-F0-9]{32})/) - match ? match[1] : nil - end - - def self.git_new_file_binary_patch(filename, encoded_chunk, git_index) - return <<END -diff --git a/#{filename} b/#{filename} -new file mode 100644 -index 0000000000000000000000000000000000000000..#{git_index} -GIT binary patch -#{encoded_chunk.join("")}literal 0 -HcmV?d00001 - -END - end - - def self.git_changed_file_binary_patch(to_filename, from_filename, encoded_chunk, to_git_index, from_git_index) - return <<END -diff --git a/#{from_filename} b/#{to_filename} -copy from #{from_filename} -+++ b/#{to_filename} -index #{from_git_index}..#{to_git_index} -GIT binary patch -#{encoded_chunk.join("")}literal 0 -HcmV?d00001 - -END - end - - def self.get_svn_uri(repository_path) - "http://src.chromium.org/blink/trunk/" + (repository_path) + "?p=" + $svn_revision.to_s - end - - def self.get_new_temp_filepath_and_name - tempfile = Tempfile.new("PrettyPatch") - filepath = tempfile.path + '.bin' - filename = File.basename(filepath) - return filepath, filename - end - - def self.download_from_revision_from_svn(repository_path) - filepath, filename = get_new_temp_filepath_and_name - svn_uri = get_svn_uri(repository_path) - open(filepath, 'wb') do |to_file| - to_file << open(svn_uri) { |from_file| from_file.read } - end - return filepath - end - - def self.run_git_apply_on_patch(output_filepath, patch) - # Apply the git binary patch using git-apply. - cmd = GIT_PATH + " apply --directory=" + File.dirname(output_filepath) - stdin, stdout, stderr = *Open3.popen3(cmd) - begin - stdin.puts(patch) - stdin.close - - error = stderr.read - if error != "" - error = "Error running " + cmd + "\n" + "with patch:\n" + patch[0..500] + "...\n" + error - end - raise error if error != "" - ensure - stdin.close unless stdin.closed? - stdout.close - stderr.close - end - end - - def self.extract_contents_from_git_binary_literal_chunk(encoded_chunk, git_index) - filepath, filename = get_new_temp_filepath_and_name - patch = FileDiff.git_new_file_binary_patch(filename, encoded_chunk, git_index) - run_git_apply_on_patch(filepath, patch) - return filepath - end - - def self.extract_contents_from_git_binary_delta_chunk(from_filepath, from_git_index, encoded_chunk, to_git_index) - to_filepath, to_filename = get_new_temp_filepath_and_name - from_filename = File.basename(from_filepath) - patch = FileDiff.git_changed_file_binary_patch(to_filename, from_filename, encoded_chunk, to_git_index, from_git_index) - run_git_apply_on_patch(to_filepath, patch) - return to_filepath - end - - def self.extract_contents_of_from_revision(repository_path, encoded_chunk, git_index) - # For literal encoded, simply reconstruct. - if GIT_LITERAL_FORMAT.match(encoded_chunk[0]) - return extract_contents_from_git_binary_literal_chunk(encoded_chunk, git_index) - end - # For delta encoded, download from svn. - if GIT_DELTA_FORMAT.match(encoded_chunk[0]) - return download_from_revision_from_svn(repository_path) - end - raise "Error: unknown git patch encoding" - end - - def self.extract_contents_of_to_revision(repository_path, encoded_chunk, git_index, from_filepath, from_git_index) - # For literal encoded, simply reconstruct. - if GIT_LITERAL_FORMAT.match(encoded_chunk[0]) - return extract_contents_from_git_binary_literal_chunk(encoded_chunk, git_index) - end - # For delta encoded, reconstruct using delta and previously constructed 'from' revision. - if GIT_DELTA_FORMAT.match(encoded_chunk[0]) - return extract_contents_from_git_binary_delta_chunk(from_filepath, from_git_index, encoded_chunk, git_index) - end - raise "Error: unknown git patch encoding" - end - end - - class DiffBlock - attr_accessor :parts - - def initialize(container) - @parts = [] - container << self - end - - def to_html - str = "<div class='DiffBlock'>\n" - str += @parts.collect{ |part| part.to_html }.join - str += "<div class='clear_float'></div></div>\n" - end - end - - class DiffBlockPart - attr_reader :className - attr :lines - - def initialize(className, container) - $last_prettify_part_count[className] += 1 - @className = className - @lines = [] - container.parts << self - end - - def to_html - str = "<div class='DiffBlockPart %s'>\n" % @className - str += @lines.collect{ |line| line.to_html }.join - # Don't put white-space after this so adjacent inline-block DiffBlockParts will not wrap. - str += "</div>" - end - end - - class DiffSection - def initialize(lines) - lines.length >= 1 or raise "DiffSection.parse only received %d lines" % lines.length - - matches = START_OF_SECTION_FORMAT.match(lines[0]) - - if matches - from, to = [matches[1].to_i, matches[3].to_i] - if matches[2] and matches[4] - from_end = from + matches[2].to_i - to_end = to + matches[4].to_i - end - end - - @blocks = [] - diff_block = nil - diff_block_part = nil - - for line in lines[1...lines.length] - startOfLine = line =~ /^[-\+ ]/ ? 1 : 0 - text = line[startOfLine...line.length].chomp - case line[0] - when ?- - if (diff_block_part.nil? or diff_block_part.className != 'remove') - diff_block = DiffBlock.new(@blocks) - diff_block_part = DiffBlockPart.new('remove', diff_block) - end - - diff_block_part.lines << CodeLine.new(from, nil, text) - from += 1 unless from.nil? - when ?+ - if (diff_block_part.nil? or diff_block_part.className != 'add') - # Put add lines that immediately follow remove lines into the same DiffBlock. - if (diff_block.nil? or diff_block_part.className != 'remove') - diff_block = DiffBlock.new(@blocks) - end - - diff_block_part = DiffBlockPart.new('add', diff_block) - end - - diff_block_part.lines << CodeLine.new(nil, to, text) - to += 1 unless to.nil? - else - if (diff_block_part.nil? or diff_block_part.className != 'shared') - diff_block = DiffBlock.new(@blocks) - diff_block_part = DiffBlockPart.new('shared', diff_block) - end - - diff_block_part.lines << CodeLine.new(from, to, text) - from += 1 unless from.nil? - to += 1 unless to.nil? - end - - break if from_end and to_end and from == from_end and to == to_end - end - - changes = [ [ [], [] ] ] - for block in @blocks - for block_part in block.parts - for line in block_part.lines - if (!line.fromLineNumber.nil? and !line.toLineNumber.nil?) then - changes << [ [], [] ] - next - end - changes.last.first << line if line.toLineNumber.nil? - changes.last.last << line if line.fromLineNumber.nil? - end - end - end - - for change in changes - next unless change.first.length == change.last.length - for i in (0...change.first.length) - from_text = change.first[i].text - to_text = change.last[i].text - next if from_text.length > MAXIMUM_INTRALINE_DIFF_LINE_LENGTH or to_text.length > MAXIMUM_INTRALINE_DIFF_LINE_LENGTH - raw_operations = HTMLDiff::DiffBuilder.new(from_text, to_text).operations - operations = [] - back = 0 - raw_operations.each_with_index do |operation, j| - if operation.action == :equal and j < raw_operations.length - 1 - length = operation.end_in_new - operation.start_in_new - if length < SMALLEST_EQUAL_OPERATION - back = length - next - end - end - operation.start_in_old -= back - operation.start_in_new -= back - back = 0 - operations << operation - end - change.first[i].operations = operations - change.last[i].operations = operations - end - end - - @blocks.unshift(ContextLine.new(matches[5])) unless matches.nil? || matches[5].empty? - end - - def to_html - str = "<div class='DiffSection'>\n" - str += @blocks.collect{ |block| block.to_html }.join - str += "</div>\n" - end - - def self.parse(lines) - linesForSections = lines.inject([[]]) do |sections, line| - sections << [] if line =~ /^@@/ - sections.last << line - sections - end - - linesForSections.delete_if { |lines| lines.nil? or lines.empty? } - linesForSections.collect { |lines| DiffSection.new(lines) } - end - end - - class Line - attr_reader :fromLineNumber - attr_reader :toLineNumber - attr_reader :text - - def initialize(from, to, text) - @fromLineNumber = from - @toLineNumber = to - @text = text - end - - def text_as_html - CGI.escapeHTML(text) - end - - def classes - lineClasses = ["Line", "LineContainer"] - lineClasses << ["add"] unless @toLineNumber.nil? or !@fromLineNumber.nil? - lineClasses << ["remove"] unless @fromLineNumber.nil? or !@toLineNumber.nil? - lineClasses - end - - def to_html - markedUpText = self.text_as_html - str = "<div class='%s'>\n" % self.classes.join(' ') - str += "<span class='from lineNumber'>%s</span><span class='to lineNumber'>%s</span>" % - [@fromLineNumber.nil? ? ' ' : @fromLineNumber, - @toLineNumber.nil? ? ' ' : @toLineNumber] unless @fromLineNumber.nil? and @toLineNumber.nil? - str += "<span class='text'>%s</span>\n" % markedUpText - str += "</div>\n" - end - end - - class CodeLine < Line - attr :operations, true - - def text_as_html - html = [] - tag = @fromLineNumber.nil? ? "ins" : "del" - if @operations.nil? or @operations.empty? - return CGI.escapeHTML(@text) - end - @operations.each do |operation| - start = @fromLineNumber.nil? ? operation.start_in_new : operation.start_in_old - eend = @fromLineNumber.nil? ? operation.end_in_new : operation.end_in_old - escaped_text = CGI.escapeHTML(@text[start...eend]) - if eend - start === 0 or operation.action === :equal - html << escaped_text - else - html << "<#{tag}>#{escaped_text}</#{tag}>" - end - end - html.join - end - end - - class ContextLine < Line - def initialize(context) - super("@", "@", context) - end - - def classes - super << "context" - end - end -end
diff --git a/third_party/blink/tools/blinkruby/PrettyPatch_test.rb b/third_party/blink/tools/blinkruby/PrettyPatch_test.rb deleted file mode 100755 index 0d5f943..0000000 --- a/third_party/blink/tools/blinkruby/PrettyPatch_test.rb +++ /dev/null
@@ -1,99 +0,0 @@ -#!/usr/bin/ruby - -require 'test/unit' -require 'open-uri' -require 'PrettyPatch' - -# Note: internet connection is needed to run this test suite. - -class PrettyPatch_test < Test::Unit::TestCase - class Info - TITLE = 0 - FILE = 1 - ADD = 2 - REMOVE = 3 - SHARED = 4 - end - - PATCHES = { - 20510 => ["Single change", 1, 1, 0, 2], - 20528 => ["No 'Index' or 'diff' in patch header", 1, 4, 3, 7], - 21151 => ["Leading '/' in the path of files", 4, 9, 1, 16], - # Binary files use shared blocks, there are three in 30488. - 30488 => ["Quoted filenames in git diff", 23, 28, 25, 64 + 3], - 23920 => ["Mac line ending", 3, 3, 0, 5], - 39615 => ["Git signature", 2, 2, 0, 3], - 80852 => ["Changes one line plus ChangeLog", 2, 2, 1, 4], - 83127 => ["Only add stuff", 2, 2, 0, 3], - 85071 => ["Adds and removes from a file plus git signature", 2, 5, 3, 9], - 106368 => ["Images with git delta binary patch", 69, 8, 23, 10], - } - - def get_patch_uri(id) - "https://bugs.webkit.org/attachment.cgi?id=" + id.to_s - end - - def get_patch(id) - result = nil - patch_uri = get_patch_uri(id) - begin - result = open(patch_uri) { |f| result = f.read } - rescue => exception - assert(false, "Fail to get patch " + patch_uri) - end - result - end - - def check_one_patch(id, info) - patch = get_patch(id) - description = get_patch_uri(id) - description += " (" + info[Info::TITLE] + ")" unless info[Info::TITLE].nil? - puts "Testing " + description - pretty = nil - assert_nothing_raised("Crash while prettifying " + description) { - pretty = PrettyPatch.prettify(patch) - } - assert(pretty, "Empty result while prettifying " + description) - assert_equal(info[Info::FILE], $last_prettify_file_count, "Wrong number of files changed in " + description) - assert_equal(info[Info::ADD], $last_prettify_part_count["add"], "Wrong number of 'add' parts in " + description) - assert_equal(info[Info::REMOVE], $last_prettify_part_count["remove"], "Wrong number of 'remove' parts in " + description) - assert_equal(info[Info::SHARED], $last_prettify_part_count["shared"], "Wrong number of 'shared' parts in " + description) - assert_equal(0, $last_prettify_part_count["binary"], "Wrong number of 'binary' parts in " + description) - assert_equal(0, $last_prettify_part_count["extract-error"], "Wrong number of 'extract-error' parts in " + description) - return pretty - end - - def test_patches - PATCHES.each { |id, info| check_one_patch(id, info) } - end - - def test_images_without_checksum - pretty = check_one_patch(144064, ["Images without checksums", 10, 5, 4, 8]) - matches = pretty.match("INVALID: Image lacks a checksum.") - # FIXME: This should match, but there's a bug when running the tests where the image data - # doesn't get properly written out to the temp files, so there is no image and we don't print - # the warning that the image is missing its checksum. - assert(!matches, "Should have invalid checksums") - # FIXME: This should only have 4 invalid images, but due to the above tempfile issue, there are 0. - assert_equal(0, pretty.scan(/INVALID\: Image lacks a checksum\./).size) - end - - def test_new_image - pretty = check_one_patch(145881, ["New image", 19, 36, 19, 56]) - matches = pretty.match("INVALID: Image lacks a checksum.") - assert(!matches, "Should not have invalid checksums") - end - - def test_images_correctly_without_checksum_git - pretty = check_one_patch(101620, ["Images correctly without checksums git", 7, 15, 10, 26]) - matches = pretty.match("INVALID: Image lacks a checksum.") - assert(!matches, "Png should lack a checksum without an error.") - end - - def test_images_correctly_without_checksum_svn - pretty = check_one_patch(31202, ["Images correctly without checksums svn", 4, 4, 1, 4]) - matches = pretty.match("INVALID: Image lacks a checksum.") - assert(!matches, "Png should lack a checksum without an error.") - end - -end
diff --git a/third_party/blink/tools/blinkruby/diff.rb b/third_party/blink/tools/blinkruby/diff.rb deleted file mode 100644 index e5c154a6..0000000 --- a/third_party/blink/tools/blinkruby/diff.rb +++ /dev/null
@@ -1,164 +0,0 @@ -module HTMLDiff - - Match = Struct.new(:start_in_old, :start_in_new, :size) - class Match - def end_in_old - self.start_in_old + self.size - end - - def end_in_new - self.start_in_new + self.size - end - end - - Operation = Struct.new(:action, :start_in_old, :end_in_old, :start_in_new, :end_in_new) - - class DiffBuilder - - def initialize(old_version, new_version) - @old_version, @new_version = old_version, new_version - split_inputs_to_words - index_new_words - end - - def split_inputs_to_words - @old_words = explode(@old_version) - @new_words = explode(@new_version) - end - - def index_new_words - @word_indices = Hash.new { |h, word| h[word] = [] } - @new_words.each_with_index { |word, i| @word_indices[word] << i } - end - - def operations - position_in_old = position_in_new = 0 - operations = [] - - matches = matching_blocks - # an empty match at the end forces the loop below to handle the unmatched tails - # I'm sure it can be done more gracefully, but not at 23:52 - matches << Match.new(@old_words.length, @new_words.length, 0) - - matches.each_with_index do |match, i| - match_starts_at_current_position_in_old = (position_in_old == match.start_in_old) - match_starts_at_current_position_in_new = (position_in_new == match.start_in_new) - - action_upto_match_positions = - case [match_starts_at_current_position_in_old, match_starts_at_current_position_in_new] - when [false, false] - :replace - when [true, false] - :insert - when [false, true] - :delete - else - # this happens if the first few words are same in both versions - :none - end - - if action_upto_match_positions != :none - operation_upto_match_positions = - Operation.new(action_upto_match_positions, - position_in_old, match.start_in_old, - position_in_new, match.start_in_new) - operations << operation_upto_match_positions - end - if match.size != 0 - match_operation = Operation.new(:equal, - match.start_in_old, match.end_in_old, - match.start_in_new, match.end_in_new) - operations << match_operation - end - - position_in_old = match.end_in_old - position_in_new = match.end_in_new - end - - operations - end - - def matching_blocks - matching_blocks = [] - recursively_find_matching_blocks(0, @old_words.size, 0, @new_words.size, matching_blocks) - matching_blocks - end - - def recursively_find_matching_blocks(start_in_old, end_in_old, start_in_new, end_in_new, matching_blocks) - match = find_match(start_in_old, end_in_old, start_in_new, end_in_new) - if match - if start_in_old < match.start_in_old and start_in_new < match.start_in_new - recursively_find_matching_blocks( - start_in_old, match.start_in_old, start_in_new, match.start_in_new, matching_blocks) - end - matching_blocks << match - if match.end_in_old < end_in_old and match.end_in_new < end_in_new - recursively_find_matching_blocks( - match.end_in_old, end_in_old, match.end_in_new, end_in_new, matching_blocks) - end - end - end - - def find_match(start_in_old, end_in_old, start_in_new, end_in_new) - - best_match_in_old = start_in_old - best_match_in_new = start_in_new - best_match_size = 0 - - match_length_at = Hash.new { |h, index| h[index] = 0 } - - start_in_old.upto(end_in_old - 1) do |index_in_old| - - new_match_length_at = Hash.new { |h, index| h[index] = 0 } - - @word_indices[@old_words[index_in_old]].each do |index_in_new| - next if index_in_new < start_in_new - break if index_in_new >= end_in_new - - new_match_length = match_length_at[index_in_new - 1] + 1 - new_match_length_at[index_in_new] = new_match_length - - if new_match_length > best_match_size - best_match_in_old = index_in_old - new_match_length + 1 - best_match_in_new = index_in_new - new_match_length + 1 - best_match_size = new_match_length - end - end - match_length_at = new_match_length_at - end - -# best_match_in_old, best_match_in_new, best_match_size = add_matching_words_left( -# best_match_in_old, best_match_in_new, best_match_size, start_in_old, start_in_new) -# best_match_in_old, best_match_in_new, match_size = add_matching_words_right( -# best_match_in_old, best_match_in_new, best_match_size, end_in_old, end_in_new) - - return (best_match_size != 0 ? Match.new(best_match_in_old, best_match_in_new, best_match_size) : nil) - end - - def add_matching_words_left(match_in_old, match_in_new, match_size, start_in_old, start_in_new) - while match_in_old > start_in_old and - match_in_new > start_in_new and - @old_words[match_in_old - 1] == @new_words[match_in_new - 1] - match_in_old -= 1 - match_in_new -= 1 - match_size += 1 - end - [match_in_old, match_in_new, match_size] - end - - def add_matching_words_right(match_in_old, match_in_new, match_size, end_in_old, end_in_new) - while match_in_old + match_size < end_in_old and - match_in_new + match_size < end_in_new and - @old_words[match_in_old + match_size] == @new_words[match_in_new + match_size] - match_size += 1 - end - [match_in_old, match_in_new, match_size] - end - - def explode(sequence) - sequence.is_a?(String) ? sequence.split(//) : sequence - end - - end # of class Diff Builder - -end
diff --git a/third_party/blink/tools/blinkruby/prettify.rb b/third_party/blink/tools/blinkruby/prettify.rb deleted file mode 100755 index a9c211f..0000000 --- a/third_party/blink/tools/blinkruby/prettify.rb +++ /dev/null
@@ -1,37 +0,0 @@ -#!/usr/bin/env ruby - -require 'optparse' -require 'pathname' -require 'webrick/htmlutils' - -$LOAD_PATH << Pathname.new(__FILE__).dirname.realpath.to_s - -require 'PrettyPatch' - -BACKTRACE_SEPARATOR = "\n\tfrom " - -options = { :html_exceptions => false } -OptionParser.new do |opts| - opts.banner = "Usage: #{File.basename($0)} [options] [patch-file]" - - opts.separator "" - - opts.on("--html-exceptions", "Print exceptions to stdout as HTML") { |h| options[:html_exceptions] = h } -end.parse! - -patch_data = nil -if ARGV.length == 0 || ARGV[0] == '-' then - patch_data = $stdin.read -else - File.open(ARGV[0]) { |file| patch_data = file.read } -end - -begin - puts PrettyPatch.prettify(patch_data) -rescue => exception - raise unless options[:html_exceptions] - - backtrace = exception.backtrace - backtrace[0] += ": " + exception + " (" + exception.class.to_s + ")" - print "<pre>\n", WEBrick::HTMLUtils::escape(backtrace.join(BACKTRACE_SEPARATOR)), "\n</pre>\n" -end
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js index b500ea18..12751a1a 100644 --- a/third_party/closure_compiler/externs/file_manager_private.js +++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -728,6 +728,17 @@ chrome.fileManagerPrivate.executeCustomAction = function( entries, actionId, callback) {}; +/** + * Returns true if crostini is enabled. + * @param {function(!boolean)} callback + */ +chrome.fileManagerPrivate.isCrostiniEnabled = function(callback) {}; + +/** + * Starts and mounts crostini container. + */ +chrome.fileManagerPrivate.mountCrostiniContainer = function() {}; + /** @type {!ChromeEvent} */ chrome.fileManagerPrivate.onMountCompleted;
diff --git a/third_party/fuchsia-sdk/fidl_library.gni b/third_party/fuchsia-sdk/fidl_library.gni index dcb8dde..1dd93e05 100644 --- a/third_party/fuchsia-sdk/fidl_library.gni +++ b/third_party/fuchsia-sdk/fidl_library.gni
@@ -4,6 +4,18 @@ assert(is_fuchsia) +# Template for FIDL libraries. Following parameters can be passed when +# instantiating these templates: +# sources - List of .fidl files. +# name - (optional) Name of the library. Must match the name specified +# in the .fidl files. target_name is used if name is not specified +# explicitly. +# deps - (optional) List of other fild_library() targets that this FIDL +# library depends on. +# namespace - (optional) Namespace for generated code. All classes in the +# generated code are placed under <namespace>::<name>:: namespace. +# 'fuchsia' namespace is used by default. +# template("fidl_library") { pkg_name = target_name @@ -12,10 +24,16 @@ pkg_name = invoker.name } + namespace = "fuchsia" + if (defined(invoker.namespace)) { + namespace = invoker.namespace + } + response_file = "$target_gen_dir/$target_name.rsp" json_representation = "$target_gen_dir/$pkg_name.fidl.json" output_gen_base = "$target_gen_dir/fidl" output_gen_dir = "$output_gen_base/fuchsia/cpp" + output_gen_dir_no_ns = "$output_gen_base/no_ns/fuchsia/cpp" tables_file = "$output_gen_base/$pkg_name.fidl-tables.cc" action("${target_name}_response_file") { @@ -31,7 +49,7 @@ "testonly", ]) - libraries_file = "$target_gen_dir/$pkg_name.fidl_libraries" + libraries_file = "$target_gen_dir/${invoker.target_name}.fidl_libraries" outputs = [ response_file, @@ -52,11 +70,21 @@ "--sources", ] + rebase_path(sources, root_build_dir) - if (defined(invoker.fidl_deps)) { + if (defined(invoker.deps) || defined(invoker.public_deps)) { + merged_deps = [] + + if (defined(invoker.deps)) { + merged_deps += invoker.deps + } + + if (defined(invoker.public_deps)) { + merged_deps += invoker.public_deps + } + dep_libraries = [] deps = [] - foreach(dep, invoker.fidl_deps) { + foreach(dep, merged_deps) { gen_dir = get_label_info(dep, "target_gen_dir") name = get_label_info(dep, "name") dep_libraries += [ "$gen_dir/$name.fidl_libraries" ] @@ -97,7 +125,7 @@ } action("${target_name}_cpp_gen") { - visibility = [ ":${invoker.target_name}" ] + visibility = [ ":${invoker.target_name}_update_namespace" ] deps = [ ":${invoker.target_name}_compile", @@ -108,8 +136,8 @@ ] outputs = [ - "$output_gen_dir/$pkg_name.h", - "$output_gen_dir/$pkg_name.cc", + "${output_gen_dir_no_ns}/${pkg_name}.h", + "${output_gen_dir_no_ns}/${pkg_name}.cc", ] script = "//build/gn_run_binary.py" @@ -121,9 +149,37 @@ "-json", rebase_path("$json_representation"), "-include-base", - rebase_path("$output_gen_base"), + rebase_path("$output_gen_base/no_ns"), "-output-base", - rebase_path("$output_gen_dir/$pkg_name"), + rebase_path("${output_gen_dir_no_ns}/${pkg_name}"), + ] + } + + # Move generated code to a different namespace to avoid conflicts with + # existing code in chromium. + # TODO(sergeyu): Remove this once FIDL-160 is resolved in Fuchsia. + action_foreach("${target_name}_update_namespace") { + visibility = [ ":${invoker.target_name}" ] + + deps = [ + ":${invoker.target_name}_cpp_gen", + ] + + sources = [ + "${output_gen_dir_no_ns}/${pkg_name}.cc", + "${output_gen_dir_no_ns}/${pkg_name}.h", + ] + + outputs = [ + "${output_gen_dir}/{{source_file_part}}", + ] + + script = "//third_party/fuchsia-sdk/update_namespace.py" + args = [ + namespace, + pkg_name, + "{{source}}", + rebase_path("${output_gen_dir}/{{source_file_part}}"), ] } @@ -152,7 +208,7 @@ } deps += [ ":${invoker.target_name}_compile", - ":${invoker.target_name}_cpp_gen", + ":${invoker.target_name}_update_namespace", ] if (!defined(public_deps)) {
diff --git a/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni b/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni index ca7d3da..24d59a7 100644 --- a/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni +++ b/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni
@@ -21,7 +21,6 @@ name = pkg_name forward_variables_from(invoker, [ - "deps", "public_deps", "testonly", "visibility", @@ -31,6 +30,13 @@ foreach(file, invoker.fidl_files) { sources += [ "sdk/fidl/${pkg_name}/${file}" ] } + + if (defined(invoker.fidl_deps)) { + deps = [] + foreach(fidl_dep, invoker.fidl_deps) { + deps += [ "${fidl_dep}_fidl" ] + } + } } }
diff --git a/third_party/fuchsia-sdk/update_namespace.py b/third_party/fuchsia-sdk/update_namespace.py new file mode 100755 index 0000000..8af1300 --- /dev/null +++ b/third_party/fuchsia-sdk/update_namespace.py
@@ -0,0 +1,39 @@ +#!/usr/bin/env python +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# Helper script used to update namespace in C++ files generated by fidlgen. This +# is necessary to avoid naming conflicts with existing code in chromium. For +# example ui::Event FIDL interface collides with ui::Event class in chromium. +# This script moves it to fuchsia::ui::Event. +# +# TODO(sergeyu): Remove this script once FIDL files in fuchsia are updated to +# use fuchsia namespace. + +import sys +import re + +def main(namespace, libname, input_file, output_file): + with open(input_file) as f: + text = f.read() + + text = re.sub(r'^namespace\ %s\ \{$' % libname, + r'namespace %s {\nnamespace %s {' % + (namespace, libname), + text, flags=re.MULTILINE) + + text = re.sub(r'}\ \ // namespace\ %s$' % libname, + r'} // namespace %s\n} // namespace %s' + % (libname, namespace), + text, flags=re.MULTILINE) + + text = re.sub(r'(?<![a-z0-9_])%s::' % libname, + r'%s::%s::' % (namespace, libname), + text) + + with open(output_file, "w") as f: + f.write(text) + +if __name__ == "__main__": + sys.exit(main(*sys.argv[1:]))
diff --git a/third_party/polymer/v1_0/bower.json b/third_party/polymer/v1_0/bower.json index 6e37546e..ca3c042 100644 --- a/third_party/polymer/v1_0/bower.json +++ b/third_party/polymer/v1_0/bower.json
@@ -17,7 +17,7 @@ "iron-icon": "PolymerElements/iron-icon#2.0.1", "iron-iconset-svg": "PolymerElements/iron-iconset-svg#2.1.1", "iron-icons": "PolymerElements/iron-icons#2.0.1", - "iron-input": "PolymerElements/iron-input#1.0.10", + "iron-input": "PolymerElements/iron-input#2.1.3", "iron-list": "PolymerElements/iron-list#2.0.14", "iron-location": "PolymerElements/iron-location#2.0.3", "iron-media-query": "PolymerElements/iron-media-query#2.0.0",
diff --git a/third_party/polymer/v1_0/chromium.patch b/third_party/polymer/v1_0/chromium.patch index 3873231..a5ea235 100644 --- a/third_party/polymer/v1_0/chromium.patch +++ b/third_party/polymer/v1_0/chromium.patch
@@ -9,6 +9,35 @@ -<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic"> -<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono:400,700"> +<link rel="stylesheet" href="chrome://resources/css/roboto.css"> +diff --git a/components-chromium/paper-input/paper-input-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-extracted.js +index 754820fb5d0c..3f8e640ffa71 100644 +--- a/components-chromium/paper-input/paper-input-extracted.js ++++ b/components-chromium/paper-input/paper-input-extracted.js +@@ -7,13 +7,7 @@ Polymer({ + ], + + beforeRegister: function() { +- // We need to tell which kind of of template to stamp based on +- // what kind of `iron-input` we got, but because of polyfills and +- // custom elements differences between v0 and v1, the safest bet is +- // to check a particular method we know the iron-input#2.x can have. +- // If it doesn't have it, then it's an iron-input#1.x. +- var ironInput = document.createElement('iron-input'); +- var version = typeof ironInput._initSlottedInput == 'function' ? 'v1' : 'v0'; ++ var version = 'v1'; // Hard coded Polymer 2 style iron-input. + var template = Polymer.DomModule.import('paper-input', 'template'); + var inputTemplate = Polymer.DomModule.import('paper-input', 'template#' + version); + var inputPlaceholder = template.content.querySelector('#template-placeholder'); +@@ -30,7 +24,8 @@ Polymer({ + * @return {!HTMLElement} + */ + get _focusableElement() { +- return Polymer.Element ? this.inputElement._inputElement : this.inputElement; ++ // TODO(hcarmona): remove this patch after polymer is v2. ++ return this.inputElement._inputElement; + }, + + // Note: This event is only available in the 1.0 version of this element. diff --git a/components-chromium/paper-input/paper-textarea-extracted.js b/components-chromium/paper-input/paper-textarea-extracted.js index 11bc05a37471..8d425e02c30b 100644 --- a/components-chromium/paper-input/paper-textarea-extracted.js
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/bower.json b/third_party/polymer/v1_0/components-chromium/iron-input/bower.json index 018f4a16..5797690 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-input/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-input", - "version": "1.0.10", + "version": "2.1.3", "description": "An input element with data binding", "authors": [ "The Polymer Authors" @@ -20,16 +20,41 @@ "homepage": "https://github.com/PolymerElements/iron-input", "ignore": [], "dependencies": { - "iron-a11y-announcer": "PolymerElements/iron-a11y-announcer#^1.0.0", - "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "iron-a11y-announcer": "PolymerElements/iron-a11y-announcer#1 - 2", + "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#1 - 2", + "polymer": "Polymer/polymer#1.9 - 2" }, "devDependencies": { - "paper-styles": "polymerelements/paper-styles#^1.0.2", - "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", - "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0", - "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "^4.0.0", - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" + "iron-component-page": "polymerelements/iron-component-page#1 - 2", + "iron-demo-helpers": "polymerelements/iron-demo-helpers#1 - 2", + "iron-validator-behavior": "PolymerElements/iron-validator-behavior#1 - 2", + "paper-styles": "polymerelements/paper-styles#1 - 2", + "test-fixture": "PolymerElements/test-fixture#^3.0.0-rc.1", + "web-component-tester": "^6.0.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0" + }, + "variants": { + "1.x": { + "dependencies": { + "iron-a11y-announcer": "PolymerElements/iron-a11y-announcer#^1.0.0", + "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#^1.0.0", + "polymer": "Polymer/polymer#^1.9" + }, + "devDependencies": { + "iron-component-page": "polymerelements/iron-component-page#^1.0.0", + "iron-demo-helpers": "polymerelements/iron-demo-helpers#^1.0.0", + "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0", + "paper-styles": "polymerelements/paper-styles#^1.0.0", + "test-fixture": "PolymerElements/test-fixture#^1.0.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", + "web-component-tester": "Polymer/web-component-tester#^4.0.0" + }, + "resolutions": { + "webcomponentsjs": "^0.7" + } + } + }, + "resolutions": { + "webcomponentsjs": "^1.0.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js index 340dfc6..d0522f20 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js
@@ -1,288 +1,262 @@ -/* -`<iron-input>` adds two-way binding and custom validators using `Polymer.IronValidatorBehavior` -to `<input>`. +Polymer({ + is: 'iron-input', -### Two-way binding - -By default you can only get notified of changes to an `input`'s `value` due to user input: - - <input value="{{myValue::input}}"> - -`iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used -for two-way data binding. `bind-value` will notify if it is changed either by user input or by script. - - <input is="iron-input" bind-value="{{myValue}}"> - -### Custom validators - -You can use custom validators that implement `Polymer.IronValidatorBehavior` with `<iron-input>`. - - <input is="iron-input" validator="my-custom-validator"> - -### Stopping invalid input - -It may be desirable to only allow users to enter certain characters. You can use the -`prevent-invalid-input` and `allowed-pattern` attributes together to accomplish this. This feature -is separate from validation, and `allowed-pattern` does not affect how the input is validated. - - <!-- only allow characters that match [0-9] --> - <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> - -@hero hero.svg -@demo demo/index.html -*/ - - Polymer({ - - is: 'iron-input', - - extends: 'input', - - behaviors: [ - Polymer.IronValidatableBehavior - ], - - properties: { + behaviors: [Polymer.IronValidatableBehavior], /** - * Use this property instead of `value` for two-way data binding. + * Fired whenever `validate()` is called. + * + * @event iron-input-validate */ - bindValue: { - observer: '_bindValueChanged', - type: String + + properties: { + + /** + * Use this property instead of `value` for two-way data binding, or to + * set a default value for the input. **Do not** use the distributed + * input's `value` property to set a default value. + */ + bindValue: {type: String, value: ''}, + + /** + * Computed property that echoes `bindValue` (mostly used for Polymer 1.0 + * backcompatibility, if you were one-way binding to the Polymer 1.0 + * `input is="iron-input"` value attribute). + */ + value: {type: String, computed: '_computeValue(bindValue)'}, + + /** + * Regex-like list of characters allowed as input; all characters not in the + * list will be rejected. The recommended format should be a list of allowed + * characters, for example, `[a-zA-Z0-9.+-!;:]`. + * + * This pattern represents the allowed characters for the field; as the user + * inputs text, each individual character will be checked against the + * pattern (rather than checking the entire value as a whole). If a + * character is not a match, it will be rejected. + * + * Pasted input will have each character checked individually; if any + * character doesn't match `allowedPattern`, the entire pasted string will + * be rejected. + * + * Note: if you were using `iron-input` in 1.0, you were also required to + * set `prevent-invalid-input`. This is no longer needed as of Polymer 2.0, + * and will be set automatically for you if an `allowedPattern` is provided. + * + */ + allowedPattern: {type: String}, + + /** + * Set to true to auto-validate the input value as you type. + */ + autoValidate: {type: Boolean, value: false}, + + /** + * The native input element. + */ + _inputElement: Object, }, - /** - * Set to true to prevent the user from entering invalid input. If `allowedPattern` is set, - * any character typed by the user will be matched against that pattern, and rejected if it's not a match. - * Pasted input will have each character checked individually; if any character - * doesn't match `allowedPattern`, the entire pasted string will be rejected. - * If `allowedPattern` is not set, it will use the `type` attribute (only supported for `type=number`). - */ - preventInvalidInput: { - type: Boolean + observers: ['_bindValueChanged(bindValue, _inputElement)'], + + listeners: {'input': '_onInput', 'keypress': '_onKeypress'}, + + created: function() { + Polymer.IronA11yAnnouncer.requestAvailability(); + this._previousValidInput = ''; + this._patternAlreadyChecked = false; }, - /** - * Regular expression that list the characters allowed as input. - * This pattern represents the allowed characters for the field; as the user inputs text, - * each individual character will be checked against the pattern (rather than checking - * the entire value as a whole). The recommended format should be a list of allowed characters; - * for example, `[a-zA-Z0-9.+-!;:]` - */ - allowedPattern: { - type: String, - observer: "_allowedPatternChanged" + attached: function() { + // If the input is added at a later time, update the internal reference. + this._observer = Polymer.dom(this).observeNodes(function(info) { + this._initSlottedInput(); + }.bind(this)); }, - _previousValidInput: { - type: String, - value: '' - }, - - _patternAlreadyChecked: { - type: Boolean, - value: false - } - - }, - - listeners: { - 'input': '_onInput', - 'keypress': '_onKeypress' - }, - - /** @suppress {checkTypes} */ - registered: function() { - // Feature detect whether we need to patch dispatchEvent (i.e. on FF and IE). - if (!this._canDispatchEventOnDisabled()) { - this._origDispatchEvent = this.dispatchEvent; - this.dispatchEvent = this._dispatchEventFirefoxIE; - } - }, - - created: function() { - Polymer.IronA11yAnnouncer.requestAvailability(); - }, - - _canDispatchEventOnDisabled: function() { - var input = document.createElement('input'); - var canDispatch = false; - input.disabled = true; - - input.addEventListener('feature-check-dispatch-event', function() { - canDispatch = true; - }); - - try { - input.dispatchEvent(new Event('feature-check-dispatch-event')); - } catch(e) {} - - return canDispatch; - }, - - _dispatchEventFirefoxIE: function() { - // Due to Firefox bug, events fired on disabled form controls can throw - // errors; furthermore, neither IE nor Firefox will actually dispatch - // events from disabled form controls; as such, we toggle disable around - // the dispatch to allow notifying properties to notify - // See issue #47 for details - var disabled = this.disabled; - this.disabled = false; - this._origDispatchEvent.apply(this, arguments); - this.disabled = disabled; - }, - - get _patternRegExp() { - var pattern; - if (this.allowedPattern) { - pattern = new RegExp(this.allowedPattern); - } else { - switch (this.type) { - case 'number': - pattern = /[0-9.,e-]/; - break; + detached: function() { + if (this._observer) { + Polymer.dom(this).unobserveNodes(this._observer); + this._observer = null; } - } - return pattern; - }, + }, - ready: function() { - this.bindValue = this.value; - }, + /** + * Returns the distributed input element. + */ + get inputElement() { + return this._inputElement; + }, - /** - * @suppress {checkTypes} - */ - _bindValueChanged: function() { - if (this.value !== this.bindValue) { - this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue === false) ? '' : this.bindValue; - } - // manually notify because we don't want to notify until after setting value - this.fire('bind-value-changed', {value: this.bindValue}); - }, + _initSlottedInput: function() { + this._inputElement = this.getEffectiveChildren()[0]; - _allowedPatternChanged: function() { - // Force to prevent invalid input when an `allowed-pattern` is set - this.preventInvalidInput = this.allowedPattern ? true : false; - }, - - _onInput: function() { - // Need to validate each of the characters pasted if they haven't - // been validated inside `_onKeypress` already. - if (this.preventInvalidInput && !this._patternAlreadyChecked) { - var valid = this._checkPatternValidity(); - if (!valid) { - this._announceInvalidCharacter('Invalid string of characters not entered.'); - this.value = this._previousValidInput; + if (this.inputElement && this.inputElement.value) { + this.bindValue = this.inputElement.value; } - } - this.bindValue = this.value; - this._previousValidInput = this.value; - this._patternAlreadyChecked = false; - }, + this.fire('iron-input-ready'); + }, - _isPrintable: function(event) { - // What a control/printable character is varies wildly based on the browser. - // - most control characters (arrows, backspace) do not send a `keypress` event - // in Chrome, but the *do* on Firefox - // - in Firefox, when they do send a `keypress` event, control chars have - // a charCode = 0, keyCode = xx (for ex. 40 for down arrow) - // - printable characters always send a keypress event. - // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the keyCode - // always matches the charCode. - // None of this makes any sense. + get _patternRegExp() { + var pattern; + if (this.allowedPattern) { + pattern = new RegExp(this.allowedPattern); + } else { + switch (this.inputElement.type) { + case 'number': + pattern = /[0-9.,e-]/; + break; + } + } + return pattern; + }, - // For these keys, ASCII code == browser keycode. - var anyNonPrintable = - (event.keyCode == 8) || // backspace - (event.keyCode == 9) || // tab - (event.keyCode == 13) || // enter - (event.keyCode == 27); // escape + /** + * @suppress {checkTypes} + */ + _bindValueChanged: function(bindValue, inputElement) { + // The observer could have run before attached() when we have actually + // initialized this property. + if (!inputElement) { + return; + } - // For these keys, make sure it's a browser keycode and not an ASCII code. - var mozNonPrintable = - (event.keyCode == 19) || // pause - (event.keyCode == 20) || // caps lock - (event.keyCode == 45) || // insert - (event.keyCode == 46) || // delete - (event.keyCode == 144) || // num lock - (event.keyCode == 145) || // scroll lock - (event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, home, arrows - (event.keyCode > 111 && event.keyCode < 124); // fn keys + if (bindValue === undefined) { + inputElement.value = null; + } else if (bindValue !== inputElement.value) { + this.inputElement.value = bindValue; + } - return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); - }, + if (this.autoValidate) { + this.validate(); + } - _onKeypress: function(event) { - if (!this.preventInvalidInput && this.type !== 'number') { - return; - } - var regexp = this._patternRegExp; - if (!regexp) { - return; - } + // manually notify because we don't want to notify until after setting value + this.fire('bind-value-changed', {value: bindValue}); + }, - // Handle special keys and backspace - if (event.metaKey || event.ctrlKey || event.altKey) - return; + _onInput: function() { + // Need to validate each of the characters pasted if they haven't + // been validated inside `_onKeypress` already. + if (this.allowedPattern && !this._patternAlreadyChecked) { + var valid = this._checkPatternValidity(); + if (!valid) { + this._announceInvalidCharacter( + 'Invalid string of characters not entered.'); + this.inputElement.value = this._previousValidInput; + } + } + this.bindValue = this._previousValidInput = this.inputElement.value; + this._patternAlreadyChecked = false; + }, - // Check the pattern either here or in `_onInput`, but not in both. - this._patternAlreadyChecked = true; + _isPrintable: function(event) { + // What a control/printable character is varies wildly based on the browser. + // - most control characters (arrows, backspace) do not send a `keypress` + // event + // in Chrome, but the *do* on Firefox + // - in Firefox, when they do send a `keypress` event, control chars have + // a charCode = 0, keyCode = xx (for ex. 40 for down arrow) + // - printable characters always send a keypress event. + // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the + // keyCode + // always matches the charCode. + // None of this makes any sense. - var thisChar = String.fromCharCode(event.charCode); - if (this._isPrintable(event) && !regexp.test(thisChar)) { - event.preventDefault(); - this._announceInvalidCharacter('Invalid character ' + thisChar + ' not entered.'); - } - }, + // For these keys, ASCII code == browser keycode. + var anyNonPrintable = (event.keyCode == 8) || // backspace + (event.keyCode == 9) || // tab + (event.keyCode == 13) || // enter + (event.keyCode == 27); // escape - _checkPatternValidity: function() { - var regexp = this._patternRegExp; - if (!regexp) { + // For these keys, make sure it's a browser keycode and not an ASCII code. + var mozNonPrintable = (event.keyCode == 19) || // pause + (event.keyCode == 20) || // caps lock + (event.keyCode == 45) || // insert + (event.keyCode == 46) || // delete + (event.keyCode == 144) || // num lock + (event.keyCode == 145) || // scroll lock + (event.keyCode > 32 && + event.keyCode < 41) || // page up/down, end, home, arrows + (event.keyCode > 111 && event.keyCode < 124); // fn keys + + return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); + }, + + _onKeypress: function(event) { + if (!this.allowedPattern && this.inputElement.type !== 'number') { + return; + } + var regexp = this._patternRegExp; + if (!regexp) { + return; + } + + // Handle special keys and backspace + if (event.metaKey || event.ctrlKey || event.altKey) { + return; + } + + // Check the pattern either here or in `_onInput`, but not in both. + this._patternAlreadyChecked = true; + + var thisChar = String.fromCharCode(event.charCode); + if (this._isPrintable(event) && !regexp.test(thisChar)) { + event.preventDefault(); + this._announceInvalidCharacter( + 'Invalid character ' + thisChar + ' not entered.'); + } + }, + + _checkPatternValidity: function() { + var regexp = this._patternRegExp; + if (!regexp) { + return true; + } + for (var i = 0; i < this.inputElement.value.length; i++) { + if (!regexp.test(this.inputElement.value[i])) { + return false; + } + } return true; - } - for (var i = 0; i < this.value.length; i++) { - if (!regexp.test(this.value[i])) { - return false; + }, + + /** + * Returns true if `value` is valid. The validator provided in `validator` + * will be used first, then any constraints. + * @return {boolean} True if the value is valid. + */ + validate: function() { + if (!this.inputElement) { + this.invalid = false; + return true; } - } - return true; - }, - /** - * Returns true if `value` is valid. The validator provided in `validator` will be used first, - * then any constraints. - * @return {boolean} True if the value is valid. - */ - validate: function() { - // First, check what the browser thinks. Some inputs (like type=number) - // behave weirdly and will set the value to "" if something invalid is - // entered, but will set the validity correctly. - var valid = this.checkValidity(); + // Use the nested input's native validity. + var valid = this.inputElement.checkValidity(); - // Only do extra checking if the browser thought this was valid. - if (valid) { - // Empty, required input is invalid - if (this.required && this.value === '') { - valid = false; - } else if (this.hasValidator()) { - valid = Polymer.IronValidatableBehavior.validate.call(this, this.value); + // Only do extra checking if the browser thought this was valid. + if (valid) { + // Empty, required input is invalid + if (this.required && this.bindValue === '') { + valid = false; + } else if (this.hasValidator()) { + valid = + Polymer.IronValidatableBehavior.validate.call(this, this.bindValue); + } } + + this.invalid = !valid; + this.fire('iron-input-validate'); + return valid; + }, + + _announceInvalidCharacter: function(message) { + this.fire('iron-announce', {text: message}); + }, + + _computeValue: function(bindValue) { + return bindValue; } - - this.invalid = !valid; - this.fire('iron-input-validate'); - return valid; - }, - - _announceInvalidCharacter: function(message) { - this.fire('iron-announce', { text: message }); - } - }); - - /* - The `iron-input-validate` event is fired whenever `validate()` is called. - @event iron-input-validate - */ \ No newline at end of file + }); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/iron-input.html b/third_party/polymer/v1_0/components-chromium/iron-input/iron-input.html index 1225baa5..844735b 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/iron-input.html +++ b/third_party/polymer/v1_0/components-chromium/iron-input/iron-input.html
@@ -10,4 +10,92 @@ <link rel="import" href="../iron-a11y-announcer/iron-a11y-announcer.html"> <link rel="import" href="../iron-validatable-behavior/iron-validatable-behavior.html"> -</head><body><script src="iron-input-extracted.js"></script></body></html> \ No newline at end of file +<!-- +`<iron-input>` is a wrapper to a native `<input>` element, that adds two-way binding +and prevention of invalid input. To use it, you must distribute a native `<input>` +yourself. You can continue to use the native `input` as you would normally: + + <iron-input> + <input> + </iron-input> + + <iron-input> + <input type="email" disabled> + </iron-input> + +### Two-way binding + +By default you can only get notified of changes to a native `<input>`'s `value` +due to user input: + + <input value="{{myValue::input}}"> + +This means that if you imperatively set the value (i.e. `someNativeInput.value = 'foo'`), +no events will be fired and this change cannot be observed. + +`iron-input` adds the `bind-value` property that mirrors the native `input`'s '`value` property; this +property can be used for two-way data binding. +`bind-value` will notify if it is changed either by user input or by script. + + <iron-input bind-value="{{myValue}}"> + <input> + </iron-input> + +Note: this means that if you want to imperatively set the native `input`'s, you _must_ +set `bind-value` instead, so that the wrapper `iron-input` can be notified. + +### Validation + +`iron-input` uses the native `input`'s validation. For simplicity, `iron-input` +has a `validate()` method (which internally just checks the distributed `input`'s +validity), which sets an `invalid` attribute that can also be used for styling. + +To validate automatically as you type, you can use the `auto-validate` attribute. + +`iron-input` also fires an `iron-input-validate` event after `validate()` is +called. You can use it to implement a custom validator: + + var CatsOnlyValidator = { + validate: function(ironInput) { + var valid = !ironInput.bindValue || ironInput.bindValue === 'cat'; + ironInput.invalid = !valid; + return valid; + } + } + ironInput.addEventListener('iron-input-validate', function() { + CatsOnly.validate(input2); + }); + +You can also use an element implementing an [`IronValidatorBehavior`](/element/PolymerElements/iron-validatable-behavior). +This example can also be found in the demo for this element: + + <iron-input validator="cats-only"> + <input> + </iron-input> + +### Preventing invalid input + +It may be desirable to only allow users to enter certain characters. You can use the +`allowed-pattern` attribute to accomplish this. This feature +is separate from validation, and `allowed-pattern` does not affect how the input is validated. + + // Only allow typing digits, but a valid input has exactly 5 digits. + <iron-input allowed-pattern="[0-9]"> + <input pattern="\d{5}"> + </iron-input> + +@hero hero.svg +@demo demo/index.html +--> + +</head><body><dom-module id="iron-input"> + <template> + <style> + :host { + display: inline-block; + } + </style> + <slot id="content"></slot> + </template> + </dom-module> +<script src="iron-input-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-extracted.js index bd4bd0980..3cb605bba 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-extracted.js
@@ -7,13 +7,7 @@ ], beforeRegister: function() { - // We need to tell which kind of of template to stamp based on - // what kind of `iron-input` we got, but because of polyfills and - // custom elements differences between v0 and v1, the safest bet is - // to check a particular method we know the iron-input#2.x can have. - // If it doesn't have it, then it's an iron-input#1.x. - var ironInput = document.createElement('iron-input'); - var version = typeof ironInput._initSlottedInput == 'function' ? 'v1' : 'v0'; + var version = 'v1'; // Hard coded Polymer 2 style iron-input. var template = Polymer.DomModule.import('paper-input', 'template'); var inputTemplate = Polymer.DomModule.import('paper-input', 'template#' + version); var inputPlaceholder = template.content.querySelector('#template-placeholder'); @@ -30,7 +24,8 @@ * @return {!HTMLElement} */ get _focusableElement() { - return Polymer.Element ? this.inputElement._inputElement : this.inputElement; + // TODO(hcarmona): remove this patch after polymer is v2. + return this.inputElement._inputElement; }, // Note: This event is only available in the 1.0 version of this element.
diff --git a/third_party/polymer/v1_0/components_summary.txt b/third_party/polymer/v1_0/components_summary.txt index b7fc464..a8aee486 100644 --- a/third_party/polymer/v1_0/components_summary.txt +++ b/third_party/polymer/v1_0/components_summary.txt
@@ -90,9 +90,9 @@ Name: iron-input Repository: https://github.com/PolymerElements/iron-input.git -Tree: 1.0.10 -Revision: 01d17407672ad8033ee447c9c7a65162f13c8f49 -Tree link: https://github.com/PolymerElements/iron-input/tree/1.0.10 +Tree: v2.1.3 +Revision: 72a4a9e898a4b825602eacd78944e8e25ee41f5c +Tree link: https://github.com/PolymerElements/iron-input/tree/v2.1.3 Name: iron-list Repository: https://github.com/PolymerElements/iron-list.git
diff --git a/third_party/protobuf/.gitignore b/third_party/protobuf/.gitignore index 51d092c..a130b8b 100644 --- a/third_party/protobuf/.gitignore +++ b/third_party/protobuf/.gitignore
@@ -53,6 +53,7 @@ *.pyc *.egg-info *_pb2.py +!python/google/protobuf/descriptor_pb2.py python/*.egg python/.eggs/ python/.tox
diff --git a/third_party/protobuf/patches/0021-Fix-protobuf-s-library-.gitinore-file.patch b/third_party/protobuf/patches/0021-Fix-protobuf-s-library-.gitinore-file.patch new file mode 100644 index 0000000..014abf9 --- /dev/null +++ b/third_party/protobuf/patches/0021-Fix-protobuf-s-library-.gitinore-file.patch
@@ -0,0 +1,25 @@ +From db78edb2e3f0a60317b167b3a4002d0f5aa5a2a7 Mon Sep 17 00:00:00 2001 +From: Artem Titov <titovartem@chromium.org> +Date: Mon, 7 May 2018 13:13:08 +0200 +Subject: [PATCH] Fix protobuf's library .gitinore file. Fix .gitignore file + for protobuf library not to exclude file, that is checkid in into repo. + +--- + third_party/protobuf/.gitignore | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/third_party/protobuf/.gitignore b/third_party/protobuf/.gitignore +index 51d092c72475..a130b8bcc028 100644 +--- a/third_party/protobuf/.gitignore ++++ b/third_party/protobuf/.gitignore +@@ -53,6 +53,7 @@ src/google/protobuf/util/**/*.pb.h + *.pyc + *.egg-info + *_pb2.py ++!python/google/protobuf/descriptor_pb2.py + python/*.egg + python/.eggs/ + python/.tox +-- +2.17.0.441.gb46fe60e1d-goog +
diff --git a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h index 5c788192..f9d9b484 100644 --- a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h +++ b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.14.0 */ +/* Generated by wayland-scanner 1.13.0 */ #ifndef REMOTE_SHELL_UNSTABLE_V1_CLIENT_PROTOCOL_H #define REMOTE_SHELL_UNSTABLE_V1_CLIENT_PROTOCOL_H @@ -1778,12 +1778,17 @@ } #define ZCR_NOTIFICATION_SURFACE_V1_DESTROY 0 +#define ZCR_NOTIFICATION_SURFACE_V1_SET_APP_ID 1 /** * @ingroup iface_zcr_notification_surface_v1 */ #define ZCR_NOTIFICATION_SURFACE_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_notification_surface_v1 + */ +#define ZCR_NOTIFICATION_SURFACE_V1_SET_APP_ID_SINCE_VERSION 2 /** @ingroup iface_zcr_notification_surface_v1 */ static inline void @@ -1819,6 +1824,18 @@ wl_proxy_destroy((struct wl_proxy *) zcr_notification_surface_v1); } +/** + * @ingroup iface_zcr_notification_surface_v1 + * + * Set an application identifier for the notification surface. + */ +static inline void +zcr_notification_surface_v1_set_app_id(struct zcr_notification_surface_v1 *zcr_notification_surface_v1, const char *app_id) +{ + wl_proxy_marshal((struct wl_proxy *) zcr_notification_surface_v1, + ZCR_NOTIFICATION_SURFACE_V1_SET_APP_ID, app_id); +} + #ifdef __cplusplus } #endif
diff --git a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h index 4c9a3b7..24568d8 100644 --- a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h +++ b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.14.0 */ +/* Generated by wayland-scanner 1.13.0 */ #ifndef REMOTE_SHELL_UNSTABLE_V1_SERVER_PROTOCOL_H #define REMOTE_SHELL_UNSTABLE_V1_SERVER_PROTOCOL_H @@ -1494,6 +1494,15 @@ */ void (*destroy)(struct wl_client *client, struct wl_resource *resource); + /** + * set application ID + * + * Set an application identifier for the notification surface. + * @since 2 + */ + void (*set_app_id)(struct wl_client *client, + struct wl_resource *resource, + const char *app_id); }; @@ -1501,6 +1510,10 @@ * @ingroup iface_zcr_notification_surface_v1 */ #define ZCR_NOTIFICATION_SURFACE_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zcr_notification_surface_v1 + */ +#define ZCR_NOTIFICATION_SURFACE_V1_SET_APP_ID_SINCE_VERSION 2 #ifdef __cplusplus }
diff --git a/third_party/wayland-protocols/protocol/remote-shell-protocol.c b/third_party/wayland-protocols/protocol/remote-shell-protocol.c index b23c9fa..22d79d5 100644 --- a/third_party/wayland-protocols/protocol/remote-shell-protocol.c +++ b/third_party/wayland-protocols/protocol/remote-shell-protocol.c
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.14.0 */ +/* Generated by wayland-scanner 1.13.0 */ /* * Copyright 2016 The Chromium Authors. @@ -137,11 +137,12 @@ static const struct wl_message zcr_notification_surface_v1_requests[] = { { "destroy", "", types + 0 }, + { "set_app_id", "2s", types + 0 }, }; WL_EXPORT const struct wl_interface zcr_notification_surface_v1_interface = { - "zcr_notification_surface_v1", 1, - 1, zcr_notification_surface_v1_requests, + "zcr_notification_surface_v1", 2, + 2, zcr_notification_surface_v1_requests, 0, NULL, };
diff --git a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml index b31392ac..30e0e7b 100644 --- a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml +++ b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
@@ -894,7 +894,7 @@ </interface> - <interface name="zcr_notification_surface_v1" version="1"> + <interface name="zcr_notification_surface_v1" version="2"> <description summary="A notification window"> An interface that may be implemented by a wl_surface to host notification contents. @@ -905,6 +905,15 @@ Unmap and destroy the notification surface. </description> </request> + + <!-- Version 2 additions --> + + <request name="set_app_id" since="2"> + <description summary="set application ID"> + Set an application identifier for the notification surface. + </description> + <arg name="app_id" type="string"/> + </request> </interface> </protocol>
diff --git a/tools/clang/scripts/run_tool.py b/tools/clang/scripts/run_tool.py index 0a3903c..52597dd 100755 --- a/tools/clang/scripts/run_tool.py +++ b/tools/clang/scripts/run_tool.py
@@ -48,7 +48,6 @@ """ import argparse -from collections import namedtuple import functools import json import multiprocessing @@ -56,7 +55,6 @@ import os.path import re import subprocess -import shlex import sys script_dir = os.path.dirname(os.path.realpath(__file__)) @@ -66,8 +64,6 @@ from clang import compile_db -CompDBEntry = namedtuple('CompDBEntry', ['directory', 'filename', 'command']) - def _PruneGitFiles(git_files, paths): """Prunes the list of files from git to include only those that are either in |paths| or start with one item in |paths|. @@ -136,22 +132,14 @@ return files -def _GetEntriesFromCompileDB(build_directory, source_filenames): - """ Gets the list of files and args mentioned in the compilation database. +def _GetFilesFromCompileDB(build_directory): + """ Gets the list of files mentioned in the compilation database. Args: build_directory: Directory that contains the compile database. - source_filenames: If not None, only include entries for the given list of - filenames. """ - - filenames_set = None if source_filenames is None else set(source_filenames) - return [ - CompDBEntry(entry['directory'], entry['file'], entry['command']) - for entry in compile_db.Read(build_directory) - if filenames_set is None or os.path.realpath( - os.path.join(entry['directory'], entry['file'])) in filenames_set - ] + return [os.path.join(entry['directory'], entry['file']) + for entry in compile_db.Read(build_directory)] def _UpdateCompileCommandsIfNeeded(compile_commands, files_list): @@ -179,7 +167,7 @@ return compile_db.ProcessCompileDatabaseIfNeeded(filtered_compile_commands) -def _ExecuteTool(toolname, tool_args, build_directory, compdb_entry): +def _ExecuteTool(toolname, tool_args, build_directory, filename): """Executes the clang tool. This is defined outside the class so it can be pickled for the multiprocessing @@ -189,7 +177,7 @@ toolname: Name of the clang tool to execute. tool_args: Arguments to be passed to the clang tool. Can be None. build_directory: Directory that contains the compile database. - compdb_entry: The file and args to run the clang tool over. + filename: The file to run the clang tool over. Returns: A dictionary that must contain the key "status" and a boolean value @@ -201,59 +189,38 @@ Otherwise, the filename and the output from stderr are associated with the keys "filename" and "stderr_text" respectively. """ - - args = [toolname, compdb_entry.filename] + args = [toolname, '-p', build_directory, filename] if (tool_args): args.extend(tool_args) - - args.append('--') - args.extend([ - a for a in shlex.split(compdb_entry.command) - # 'command' contains the full command line, including the input - # source file itself. We need to filter it out otherwise it's - # passed to the tool twice - once directly and once via - # the compile args. - if a != compdb_entry.filename - ]) - command = subprocess.Popen( - args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=build_directory) + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_text, stderr_text = command.communicate() stderr_text = re.sub( r"^warning: .*'linker' input unused \[-Wunused-command-line-argument\]\n", "", stderr_text, flags=re.MULTILINE) - if command.returncode != 0: - return { - 'status': False, - 'filename': compdb_entry.filename, - 'stderr_text': stderr_text, - } + return {'status': False, 'filename': filename, 'stderr_text': stderr_text} else: - return { - 'status': True, - 'filename': compdb_entry.filename, - 'stdout_text': stdout_text, - 'stderr_text': stderr_text, - } + return {'status': True, 'filename': filename, 'stdout_text': stdout_text, + 'stderr_text': stderr_text} class _CompilerDispatcher(object): """Multiprocessing controller for running clang tools in parallel.""" - def __init__(self, toolname, tool_args, build_directory, compdb_entries): + def __init__(self, toolname, tool_args, build_directory, filenames): """Initializer method. Args: toolname: Path to the tool to execute. tool_args: Arguments to be passed to the tool. Can be None. build_directory: Directory that contains the compile database. - compdb_entries: The files and args to run the tool over. + filenames: The files to run the tool over. """ self.__toolname = toolname self.__tool_args = tool_args self.__build_directory = build_directory - self.__compdb_entries = compdb_entries + self.__filenames = filenames self.__success_count = 0 self.__failed_count = 0 @@ -267,7 +234,7 @@ result_iterator = pool.imap_unordered( functools.partial(_ExecuteTool, self.__toolname, self.__tool_args, self.__build_directory), - self.__compdb_entries) + self.__filenames) for result in result_iterator: self.__ProcessResult(result) sys.stderr.write('\n') @@ -288,7 +255,7 @@ sys.stderr.write(result['stderr_text']) sys.stderr.write('\n') done_count = self.__success_count + self.__failed_count - percentage = (float(done_count) / len(self.__compdb_entries)) * 100 + percentage = (float(done_count) / len(self.__filenames)) * 100 sys.stderr.write( 'Processed %d files with %s tool (%d failures) [%.2f%%]\r' % (done_count, self.__toolname, self.__failed_count, percentage)) @@ -354,25 +321,26 @@ with open(os.path.join(args.p, 'compile_commands.json'), 'w') as f: f.write(json.dumps(compile_commands, indent=2)) - compdb_entries = set(_GetEntriesFromCompileDB(args.p, source_filenames)) + if args.all: + source_filenames = set(_GetFilesFromCompileDB(args.p)) if args.shard: - total_length = len(compdb_entries) + total_length = len(source_filenames) match = re.match(r'(\d+)-of-(\d+)$', args.shard) # Input is 1-based, but modular arithmetic is 0-based. shard_number = int(match.group(1)) - 1 shard_count = int(match.group(2)) - compdb_entries = [ - f for i, f in enumerate(sorted(compdb_entries)) - if i % shard_count == shard_number + source_filenames = [ + f[1] for f in enumerate(sorted(source_filenames)) + if f[0] % shard_count == shard_number ] print 'Shard %d-of-%d will process %d entries out of %d' % ( - shard_number, shard_count, len(compdb_entries), total_length) + shard_number, shard_count, len(source_filenames), total_length) dispatcher = _CompilerDispatcher(os.path.join(tool_path, args.tool), args.tool_arg, args.p, - compdb_entries) + source_filenames) dispatcher.Run() return -dispatcher.failed_count
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py index 5a707cf6..962f8515 100755 --- a/tools/code_coverage/coverage.py +++ b/tools/code_coverage/coverage.py
@@ -213,6 +213,8 @@ self._header_template = jinja_env.get_template('header.html') self._table_template = jinja_env.get_template('table.html') self._footer_template = jinja_env.get_template('footer.html') + self._style_overrides = open( + os.path.join(template_dir, 'style_overrides.css')).read() def AddLinkToAnotherReport(self, html_report_path, name, summary): """Adds a link to another html report in this report. @@ -312,7 +314,8 @@ component_view_href=_GetRelativePathToDirectoryOfFile( component_view_path, self._output_path), file_view_href=_GetRelativePathToDirectoryOfFile( - file_view_path, self._output_path)) + file_view_path, self._output_path), + style_overrides=self._style_overrides) html_table = self._table_template.render( entries=self._table_entries,
diff --git a/tools/code_coverage/html_templates/header.html b/tools/code_coverage/html_templates/header.html index 7696ca3..fedf0c8 100644 --- a/tools/code_coverage/html_templates/header.html +++ b/tools/code_coverage/html_templates/header.html
@@ -4,13 +4,14 @@ <meta name='viewport' content='width=device-width,initial-scale=1'> <meta charset='UTF-8'> <link rel='stylesheet' type='text/css' href='{{ css_path }}'> + <!-- Custom style overrides --> + <style> + {{ style_overrides }} + </style> </head> <body> <h2>Coverage Report</h2> <p> - Click <a href='http://clang.llvm.org/docs/SourceBasedCodeCoverage.html#interpreting-reports'>here</a> for information about interpreting this report. - </p> - <p> - View results by: <a href='{{ directory_view_href }}'>Directories</a> | <a href='{{ component_view_href }}'>Components</a> | <a href='{{ file_view_href }}'>Files</a> + View results by: <a href='{{ component_view_href }}'>Components</a> | <a href='{{ directory_view_href }}'>Directories</a> | <a href='{{ file_view_href }}'>Files</a> </p> <div class='centered'> \ No newline at end of file
diff --git a/tools/code_coverage/html_templates/style_overrides.css b/tools/code_coverage/html_templates/style_overrides.css new file mode 100644 index 0000000..e59c22a --- /dev/null +++ b/tools/code_coverage/html_templates/style_overrides.css
@@ -0,0 +1,28 @@ +/* Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +th, td { + padding: 5px 16px; +} + +tbody td, tfoot td { + font-size: 14px; +} + +thead th { + font-size: 16px; +} + +thead th, tfoot td { + background-color: #f5f5f5; + border-left: 1px solid #e4e4e4; + border-right: 1px solid #e4e4e4; + color: #484848; + text-transform: uppercase; +} + +tbody tr:hover td, tfoot tr:hover td { + background-color: #f5f5f5; + border-color: #e4e4e4 !important; +} \ No newline at end of file
diff --git a/tools/code_coverage/html_templates/table.html b/tools/code_coverage/html_templates/table.html index 226b29d..28f88952 100644 --- a/tools/code_coverage/html_templates/table.html +++ b/tools/code_coverage/html_templates/table.html
@@ -1,34 +1,46 @@ <table> - <tr> - <td class="column-entry-bold">{{ table_entry_type }}</td> - <td class="column-entry-bold">Line Coverage</td> - <td class="column-entry-bold">Function Coverage</td> - <td class="column-entry-bold">Region Coverage</td> - </tr> + <thead> + <tr> + <th class="column-entry-bold">{{ table_entry_type }}</th> + <th class="column-entry-bold" title= + "Line coverage is the percentage of code lines which have been executed at least once. Only executable lines within function bodies are considered to be code lines."> + Line Coverage</th> + <th class="column-entry-bold" title= + "Function coverage is the percentage of functions which have been executed at least once. A function is considered to be executed if any of its instantiations are executed."> + Function Coverage</th> + <th class="column-entry-bold" title= + "Region coverage is the percentage of code regions which have been executed at least once. A code region may span multiple lines (e.g in a large function body with no control flow). However, it's also possible for a single line to contain multiple code regions (e.g in 'return x || y && z')."> + Region Coverage</th> + </tr> + </thead> + <tbody> {% for entry in entries %} - <tr class="light-row"> - <td> - {% if entry["is_dir"] == True %} - <pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}/</a></pre> - {% else %} - <pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}</a></pre> - {% endif %} - </td> - {% for feature in ("lines", "functions", "regions") %} - <td class='column-entry-{{ entry[feature]["color_class"] }}'> - <pre>{{ entry[feature]["percentage"] }}% ({{ entry[feature]["covered"] }}/{{ entry[feature]["total"] }})</pre> - </td> + <tr class="light-row"> + <td> + {% if entry["is_dir"] == True %} + <pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}/</a></pre> + {% else %} + <pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}</a></pre> + {% endif %} + </td> + {% for feature in ("lines", "functions", "regions") %} + <td class='column-entry-{{ entry[feature]["color_class"] }}'> + <pre>{{ entry[feature]["percentage"] }}% ({{ entry[feature]["covered"] }}/{{ entry[feature]["total"] }})</pre> + </td> + {% endfor %} + </tr> {% endfor %} - </tr> - {% endfor %} - <tr class="light-row-bold"> - <td> - <pre>Totals</pre> - </td> - {% for feature in ("lines", "functions", "regions") %} - <td class='column-entry-{{ total_entry[feature]["color_class"] }}'> - <pre>{{ total_entry[feature]["percentage"] }}% ({{ total_entry[feature]["covered"] }}/{{ total_entry[feature]["total"] }})</pre> - </td> - {% endfor %} - </tr> + </tbody> + <tfoot> + <tr class="light-row-bold"> + <td> + <pre>Totals</pre> + </td> + {% for feature in ("lines", "functions", "regions") %} + <td class='column-entry-{{ total_entry[feature]["color_class"] }}'> + <pre>{{ total_entry[feature]["percentage"] }}% ({{ total_entry[feature]["covered"] }}/{{ total_entry[feature]["total"] }})</pre> + </td> + {% endfor %} + </tr> + </tfoot> </table> \ No newline at end of file
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index 69223f2a..7e838ac9 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -406,6 +406,10 @@ "includes": [28750], }, + "chromecast/renderer/resources/extensions_renderer_resources.grd": { + "includes": [28900], + }, + # END "everything else" section. # Everything but chrome/, components/, content/, and ios/
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 04229a4..cea0cb3 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -56,6 +56,7 @@ 'Deterministic Android (dbg)': 'android_debug_bot', 'KitKat Phone Tester (rel)': 'android_release_bot_minimal_symbols', 'Marshmallow Phone Tester (rel)': 'android_release_bot_minimal_symbols_arm64', + 'android-kitkat-arm-rel': 'android_release_bot_minimal_symbols', }, 'chromium.android.fyi': { @@ -320,28 +321,22 @@ }, 'chromium.linux': { - 'Android Arm64 Builder (dbg)': 'android_debug_static_bot_arm64', - 'Android Builder (dbg)': 'android_debug_static_bot', - 'Android Builder': 'android_release_bot_minimal_symbols', - 'Android Clang Builder (dbg)': 'android_clang_asan_debug_bot_minimal_symbols', - 'Android Tests (dbg)': 'android_debug_static_bot', - 'Android Tests': 'android_release_bot_minimal_symbols', - 'Cast Android (dbg)': 'android_cast_debug_static_bot', - 'Cast Linux': 'cast_release_bot', 'Cast Audio Linux': 'cast_audio_release_bot', - 'linux-jumbo-rel': 'jumbo_release_bot_minimal_symbols', - 'Leak Detection Linux': 'release_bot', - 'Linux Builder (dbg)': 'debug_bot', - 'Linux Builder (dbg)(32)': 'debug_bot_x86', - 'Linux Builder': 'release_bot', - 'Deterministic Linux': 'release_bot', + 'Cast Linux': 'cast_release_bot', 'Deterministic Linux (dbg)': 'debug_bot', + 'Deterministic Linux': 'release_bot', 'Fuchsia ARM64 Cast Audio': 'release_bot_fuchsia_arm64_cast_audio', 'Fuchsia ARM64': 'release_bot_fuchsia_arm64', 'Fuchsia x64 Cast Audio': 'release_bot_fuchsia_cast_audio', 'Fuchsia x64': 'release_bot_fuchsia', + 'Leak Detection Linux': 'release_bot', + 'Linux Builder (dbg)': 'debug_bot', + 'Linux Builder (dbg)(32)': 'debug_bot_x86', + 'Linux Builder': 'release_bot', 'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11', + 'linux-jumbo-rel': 'jumbo_release_bot_minimal_symbols', 'linux-ozone-rel': 'ozone_linux_release_bot', + 'linux-xenial-rel': 'release_bot', }, 'chromium.lkgr': { @@ -538,6 +533,7 @@ }, 'tryserver.chromium.android': { + 'android-kitkat-arm-rel': 'android_release_trybot', 'android_archive_rel_ng': 'android_release_trybot', 'android_arm64_dbg_recipe': 'android_debug_trybot_compile_only_arm64', 'android_blink_rel': 'android_release_trybot',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 056b0424..3b24fa2 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -18043,6 +18043,12 @@ <description>Please enter the description of this user action.</description> </action> +<action name="StatusArea_Audio_Muted"> + <owner>shihuis@chromium.org</owner> + <owner>tetsui@chromium.org</owner> + <description>User muted audio from the button in SystemTray.</description> +</action> + <action name="StatusArea_Audio_SwitchInputDevice"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> @@ -18053,6 +18059,12 @@ <description>Please enter the description of this user action.</description> </action> +<action name="StatusArea_Audio_Unmuted"> + <owner>shihuis@chromium.org</owner> + <owner>tetsui@chromium.org</owner> + <description>User unmuted audio from the button in SystemTray.</description> +</action> + <action name="StatusArea_AutoClickDisabled"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 969b1e74..d483fd79 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2780,8 +2780,8 @@ </enum> <enum name="AVDAFrameInformation"> - <int value="0" label="SurfaceTexture Insecure"/> - <int value="1" label="SurfaceTexture L3"/> + <int value="0" label="Non Overlay Insecure"/> + <int value="1" label="Non Overlay L3"/> <int value="2" label="Overlay L3"/> <int value="3" label="Overlay L1"/> <int value="4" label="Overlay Insecure Player-element Fullscreen"/> @@ -6226,6 +6226,9 @@ </enum> <enum name="ColorSpaceNonlinearFitConverged"> + <obsolete> + Nonlinear fit code moved to skcms on 2018-04-25. + </obsolete> <int value="0" label="Did not converge."/> <int value="1" label="Converged."/> </enum> @@ -8131,6 +8134,12 @@ <int value="1" label="Ctrl + S to read selection"/> </enum> +<enum name="CrosSelectToSpeakStateChangeEvent"> + <int value="0" label="Start selection"/> + <int value="1" label="Cancel speech"/> + <int value="2" label="Cancel selection"/> +</enum> + <enum name="CrosShelfClickTarget"> <obsolete> Deprecated as of 12/2013. Default pinned apps trial is finished. @@ -8173,6 +8182,11 @@ <int value="2" label="The system clock is known to be inaccurate"/> </enum> +<enum name="CrosSystemTrayInteraction"> + <int value="0" label="Tap"/> + <int value="1" label="Click"/> +</enum> + <enum name="CrostiniAppLaunchAppType"> <int value="0" label="Unknown App"/> <int value="1" label="Terminal"/> @@ -15386,6 +15400,8 @@ <int value="1247" label="WALLPAPERPRIVATE_GETCURRENTWALLPAPERTHUMBNAIL"/> <int value="1248" label="ACCESSIBILITY_PRIVATE_ONSELECTTOSPEAKSTATECHANGED"/> <int value="1249" label="INPUTMETHODPRIVATE_GETCOMPOSITIONBOUNDS"/> + <int value="1250" label="FILEMANAGERPRIVATE_ISCROSTINIENABLED"/> + <int value="1251" label="FILEMANAGERPRIVATE_MOUNTCROSTINICONTAINER"/> </enum> <enum name="ExtensionIconState"> @@ -23054,23 +23070,30 @@ <enum name="ICCProfileAnalyzeResult"> <int value="0" - label="Extracted primary matrix and numerical transfer function"/> + label="Extracted primary matrix and numerical transfer function + (Obsolete)"/> <int value="1" - label="Extracted primary matrix and approximated transfer function"/> + label="Extracted primary matrix and approximated transfer function + (Obsolete)"/> <int value="2" - label="Failed to converge in approximation of transfer function"/> - <int value="3" label="Failed to extract transfer function"/> - <int value="4" label="Failed to extract primary matrix"/> + label="Failed to converge in approximation of transfer function + (Obsolete)"/> + <int value="3" label="Failed to extract transfer function (Obsolete)"/> + <int value="4" label="Failed to extract primary matrix (Obsolete)"/> <int value="5" label="Failed to parse"/> - <int value="6" label="Parsed, but failed to extract SkColorSpace"/> + <int value="6" label="Parsed, but failed to extract SkColorSpace (Obsolete)"/> <int value="7" label="Parsed and extracteed SkColorSpace, but failed to create - SkColorSpaceXform to this space"/> + SkColorSpaceXform to this space (Obsolete)"/> <int value="8" label="Converged to an insufficiently accurate approximation of - transfer function"/> - <int value="9" label="Extracted an sRGB profile directly"/> + transfer function (Obsolete)"/> + <int value="9" label="Extracted an sRGB profile directly (Obsolete)"/> <int value="10" label="No profile specified"/> + <int value="11" label="Parsed, but failed to make a usable approximation"/> + <int value="12" + label="Got an exact color space (or accurate approximation) from the + profile"/> </enum> <enum name="IceCandidatePairTypes"> @@ -27666,6 +27689,7 @@ <int value="963671232" label="DrawOcclusion:disabled"/> <int value="972228058" label="SyncUSSSessions:disabled"/> <int value="975104092" label="show-taps"/> + <int value="976079108" label="TouchpadOverscrollHistoryNavigation:disabled"/> <int value="979445973" label="OmniboxSpareRenderer:enabled"/> <int value="980396200" label="enable-new-korean-ime"/> <int value="981818901" label="AppBanners:enabled"/> @@ -27825,6 +27849,7 @@ <int value="1292763218" label="SystemTrayUnified:disabled"/> <int value="1294131571" label="disable-winrt-midi-api"/> <int value="1296958520" label="hide-active-apps-from-shelf"/> + <int value="1298927156" label="TouchpadOverscrollHistoryNavigation:enabled"/> <int value="1298981651" label="disable-new-task-manager"/> <int value="1300282719" label="OfflinePagesBackgroundLoading:enabled"/> <int value="1302421166" label="NativeNotifications:disabled"/> @@ -34306,6 +34331,15 @@ <int value="7" label="FAIL_DIFFERENT_PROXY_LIST"/> </enum> +<enum name="PacUrlScheme"> + <int value="0" label="Other"/> + <int value="1" label="Http"/> + <int value="2" label="Https"/> + <int value="3" label="Ftp"/> + <int value="4" label="File"/> + <int value="5" label="Data"/> +</enum> + <enum name="PageEndReason"> <int value="0" label="END_NONE"> Page lifetime has not yet ended (page is still active) @@ -36490,6 +36524,33 @@ <int value="7" label="Overflow"/> </enum> +<enum name="PostOperationState"> + <int value="0" label="Succeeded">The operation succeeded</int> + <int value="1" label="Failed: file not found"> + The operation failed and the file operated on is not found. + </int> + <int value="2" label="Failed: path not found"> + The operation failed and the path to the file operated on is not found. + </int> + <int value="3" label="Failed: access denied"> + The operation failed and the process does not have permission to read the + attributes of the path. + </int> + <int value="4" label="Failed: cannot get attributes"> + The operation failed as did a subsequent call to GetFileAttributes. + </int> + <int value="5" label="Failed: empty directory"> + The operation failed leaving behind an empty directory. + </int> + <int value="6" label="Failed: non-empty directory"> + The operation failed leaving behind a non-empty directory. + </int> + <int value="7" label="Failed: not a directory"> + The operation failed leaving behind something other than a directory + (perhaps a simple file). + </int> +</enum> + <enum name="PostSubmitNavigation"> <int value="0" label="Same domain"/> <int value="1" label="Different domain"/> @@ -37246,6 +37307,7 @@ <int value="8" label="PRINT_WITH_CLOUD_PRINT"/> <int value="9" label="PRINT_WITH_PRIVET"/> <int value="10" label="PRINT_WITH_EXTENSION"/> + <int value="11" label="OPEN_IN_MAC_PREVIEW"/> </enum> <enum name="PrintSettings">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 6402037..ed6fcae6 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -269,6 +269,18 @@ </summary> </histogram> +<histogram name="Accessibility.CrosSelectToSpeak.StateChangeEvent" + enum="CrosSelectToSpeakStateChangeEvent"> + <owner>katie@chromium.org</owner> + <summary> + A user has tapped a button in the tray to change Select-to-Speak's state. + The tap was interpreted by Select-to-Speak as a request to start selection, + to cancel speech, or to cancel selection, depending on Select-to-Speak's + internal state when the tap occured. This tracks when the button was tapped + and the event that it generated. + </summary> +</histogram> + <histogram name="Accessibility.CrosSelectToSpeak.WordHighlighting" enum="BooleanEnabled"> <owner>katie@chromium.org</owner> @@ -1979,6 +1991,37 @@ </summary> </histogram> +<histogram name="Android.WebView.Startup.CreationTime.Stage1.FactoryInit" + units="ms"> + <owner>changwan@chromium.org</owner> + <summary> + How long it takes to initialize a WebViewChromiumFactoryProvider. This is + the first major phase of the WebViewChromium construction. + </summary> +</histogram> + +<histogram name="Android.WebView.Startup.CreationTime.Stage2.ProviderInit.Cold" + units="ms"> + <owner>changwan@chromium.org</owner> + <summary> + How long it takes to initialize a WebViewProvider, the first time that one + is initialized. WebViewProvider initialization is the second major phase of + WebViewChromium construction. The first initialization is recorded + separately because it is usually much slower than subsequent ones. + </summary> +</histogram> + +<histogram name="Android.WebView.Startup.CreationTime.Stage2.ProviderInit.Warm" + units="ms"> + <owner>changwan@chromium.org</owner> + <summary> + How long it takes to initialize a WebViewProvider, the first time that one + is initialized. WebViewProvider initialization is the second major phase of + WebViewChromium construction. When it is not the first time, it is faster + and thus recorded separately. + </summary> +</histogram> + <histogram name="Android.WebView.TargetSdkVersion" enum="AndroidApiLevel"> <owner>changwan@chromium.org</owner> <summary> @@ -7494,6 +7537,9 @@ <histogram name="Blink.ColorSpace.Destination.NonlinearFitConverged" enum="ColorSpaceNonlinearFitConverged"> + <obsolete> + Nonlinear fit code moved to skcms on 2018-04-25. + </obsolete> <owner>ccameron@chromium.org</owner> <summary> Whether or not the nonlinear least squares fit of the table-based ICC @@ -7502,6 +7548,9 @@ </histogram> <histogram name="Blink.ColorSpace.Destination.NonlinearFitError"> + <obsolete> + Nonlinear fit code moved to skcms on 2018-04-25. + </obsolete> <owner>ccameron@chromium.org</owner> <summary> The L-infinity error (in 8-bit values) of the numerical approximation of @@ -10693,6 +10742,16 @@ </summary> </histogram> +<histogram name="ChromeOS.SystemTray.Interaction" + enum="CrosSystemTrayInteraction"> + <owner>tetsui@chromium.org</owner> + <summary> + An enum value how system tray bubble is interacted e.g. by tap (touch + screen), or click (mouse, trackpad, etc.) Reported every time the region + inside system tray bubble is tapped or clicked. + </summary> +</histogram> + <histogram name="ChromeOS.SystemTray.TimeToClick" units="ms"> <owner>tetsui@chromium.org</owner> <summary> @@ -29752,6 +29811,11 @@ <summary>Whether or not a frame displays an overlay.</summary> </histogram> +<histogram name="GPU.DirectComposition.SwapBuffersLastError" enum="Hresult"> + <owner>sunnyps@chromium.org</owner> + <summary>Last error when presentation using DirectComposition fails.</summary> +</histogram> + <histogram name="GPU.DirectComposition.SwapchainFormat" enum="SwapchainFormat"> <owner>jbauman@chromium.org</owner> <summary>What type of swapchain was actually created for an overlay.</summary> @@ -36563,7 +36627,7 @@ <owner>liberato@chromium.org</owner> <summary> Record a count for each frame sent to the client by AVDA, separated by what - type of frame it is: SurfaceTexture, secure overlay, etc. + type of frame it is: Non Overlay, secure overlay, etc. </summary> </histogram> @@ -36572,7 +36636,7 @@ <summary> Record a count for each frame sent to the client by AVDA. True counts indicate that the frame was an overlay (SurfaceView). False counts are for - SurfaceTexture frames. This will be deprecated in favor of + Non Overlay frames. This will be deprecated in favor of Media.AVDA.FrameInformation in M63. </summary> </histogram> @@ -36626,7 +36690,7 @@ <histogram name="Media.AvdaCodecImage.WaitTimeForFrame" units="ms"> <owner>liberato@chromium.org</owner> <summary> - Time spent waiting for a frame to become available in a SurfaceTexture after + Time spent waiting for a frame to become available in a Non Overlay after requesting that MediaCodec renders it. </summary> </histogram> @@ -48344,6 +48408,16 @@ </summary> </histogram> +<histogram name="Net.ProxyResolutionService.PacUrlScheme" enum="PacUrlScheme"> + <owner>eroman@chromium.org</owner> + <summary> + The breakdown of URL schemes seen for explicitly configured ProxyAutoConfig + (PAC). This metric is emitted once each time the proxy settings change + (including initial value). Note that this does not count implicitly inferred + PAC URLs (from WPAD). + </summary> +</histogram> + <histogram name="Net.ProxyResolver.AbandonedExecutionTotalTime" units="ms"> <obsolete> Removed in Chrome 39. @@ -60442,7 +60516,7 @@ <summary> Time it takes for the omnibox to become responsive to user input after the user has typed N characters. This measures the time it takes to start all - the asynchronous autocomplete providers (but not wait for them to finish). + autocomplete providers (but not wait for the asynchronous ones to finish). </summary> </histogram> @@ -72462,6 +72536,14 @@ </summary> </histogram> +<histogram name="PrintPreview.PageCount.OpenInMacPreview"> + <owner>thestig@chromium.org</owner> + <summary> + The final page count (after page selection) of documents printed to PDF and + opened in Preview.app on Mac. + </summary> +</histogram> + <histogram name="PrintPreview.PageCount.PrintToCloudPrint"> <owner>vitalybuka@chromium.org</owner> <summary> @@ -72532,6 +72614,20 @@ <summary>Print preview events.</summary> </histogram> +<histogram name="PrintPreview.PrintDocumentSize.HTML" units="KB"> + <owner>thestig@chromium.org</owner> + <summary> + The average size of a page in the printed document when the source is HTML. + </summary> +</histogram> + +<histogram name="PrintPreview.PrintDocumentSize.PDF" units="KB"> + <owner>thestig@chromium.org</owner> + <summary> + The average size of a page in the printed document when the source is PDF. + </summary> +</histogram> + <histogram name="PrintPreview.PrintDocumentType" enum="PrintPreviewPrintDocumentTypeBuckets"> <owner>rbpotter@chromium.org</owner> @@ -107104,6 +107200,14 @@ </summary> </histogram> +<histogram base="true" name="Windows.FilesystemError" enum="WinGetLastError"> + <owner>grt@chromium.org</owner> + <summary> + The Windows error code relating to a failed attempt to operate on a file or + a directory. + </summary> +</histogram> + <histogram name="Windows.GetVersionExVersion" enum="WindowsVersion"> <owner>scottmg@chromium.org</owner> <summary> @@ -107181,6 +107285,14 @@ </summary> </histogram> +<histogram base="true" name="Windows.PostOperationState" + enum="PostOperationState"> + <owner>grt@chromium.org</owner> + <summary> + The state of an item in the filesystem following an operation on it. + </summary> +</histogram> + <histogram name="Windows.Tablet" enum="BooleanTablet"> <owner>zturner@chromium.org</owner> <summary>Count of browser launches from a Windows tablet pc.</summary> @@ -110590,6 +110702,13 @@ <affected-histogram name="FileBrowser.Load"/> </histogram_suffixes> +<histogram_suffixes name="FileOperations" separator="."> + <suffix name="DeleteFile.NonRecursive"/> + <suffix name="DeleteFile.Recursive"/> + <affected-histogram name="Windows.FilesystemError"/> + <affected-histogram name="Windows.PostOperationState"/> +</histogram_suffixes> + <histogram_suffixes name="FirstPacketSplit" separator="_"> <suffix name="first_packet_intact" label="with GET/POST headers often using only 1 packet"/>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index a816d6a3..5ebec94 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -458,7 +458,12 @@ 'blink_perf.parser', 'blink_perf.shadow_dom', 'blink_perf.svg', - 'memory.top_10_mobile' + 'memory.top_10_mobile', + 'system_health.common_desktop', + 'system_health.common_mobile', + 'system_health.memory_desktop', + 'system_health.memory_mobile', + 'system_health.webview_startup', ]
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index e2276fe..034cda31 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -208,6 +208,7 @@ crbug.com/755556 [ Mac ] smoothness.tough_animation_cases/mix_blend_mode_animation_hue.html [ Skip ] crbug.com/829499 [ Android_One ] smoothness.tough_animation_cases/css_animations_many_keyframes.html?N=0316 [ Skip ] crbug.com/829499 [ Android_One ] smoothness.tough_animation_cases/web_animations_many_keyframes.html?N=0316 [ Skip ] +crbug.com/840964 [ Nexus_5X ] smoothness.tough_animation_cases/web_animations_many_keyframes.html?N=0316 [ Skip ] # Benchmark: smoothness.tough_canvas_cases crbug.com/785485 [ Android_Webview ] smoothness.tough_canvas_cases/http://www.kevs3d.co.uk/dev/canvask3d/k3d_test.html [ Skip ] @@ -421,6 +422,8 @@ [ Android_One ] wasm/WasmSpaceBuggy [ Skip ] crbug.com/814012 [ Mac ] wasm/AsmJsZenGarden [ Skip ] crbug.com/814012 [ Win ] wasm/AsmJsZenGarden [ Skip ] +crbug.com/840935 [ All ] wasm/WasmStylizedRenderer [ Skip ] +crbug.com/840935 [ All ] wasm/WasmSunTemple [ Skip ] ##### Perf FYI benchmarks go after here ##### # Benchmark: loading.desktop.network_service
diff --git a/tools/traffic_annotation/auditor/auditor_result.h b/tools/traffic_annotation/auditor/auditor_result.h index 51c60d32..9d1ba078 100644 --- a/tools/traffic_annotation/auditor/auditor_result.h +++ b/tools/traffic_annotation/auditor/auditor_result.h
@@ -67,6 +67,7 @@ Type type() const { return type_; }; std::string file_path() const { return file_path_; } + void set_file_path(const std::string& file_path) { file_path_ = file_path; } // Formats the error message into one line of text. std::string ToText() const;
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc index 83df5e4..25271c58 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor.cc
@@ -100,6 +100,32 @@ return false; } +// If normalized |file_path| starts with |base_directory|, returns the +// relative path to |file_path|, otherwise the original |file_path| is returned. +std::string MakeRelativePath(const base::FilePath& base_directory, + const std::string& file_path) { + DCHECK(base_directory.IsAbsolute()); + +#if defined(OS_WIN) + base::FilePath converted_file_path = base::FilePath( + base::FilePath::StringPieceType((base::UTF8ToWide(file_path)))); +#else + base::FilePath converted_file_path(file_path); +#endif + base::FilePath normalized_path; + if (base::NormalizeFilePath(converted_file_path, &normalized_path) && + normalized_path.IsAbsolute()) { + normalized_path = normalized_path.NormalizePathSeparatorsTo('/'); + std::string file_str = normalized_path.MaybeAsASCII(); + std::string base_str = base_directory.MaybeAsASCII(); + if (file_str.find(base_str) == 0) { + return file_str.substr(base_str.length() + 1, + file_str.length() - base_str.length() - 1); + } + } + return file_path; +} + } // namespace TrafficAnnotationAuditor::TrafficAnnotationAuditor( @@ -115,6 +141,15 @@ DCHECK(!build_path.empty()); DCHECK(!clang_tool_path.empty()); + // Get absolute source path. + base::FilePath original_path; + base::GetCurrentDirectory(&original_path); + base::SetCurrentDirectory(source_path_); + base::GetCurrentDirectory(&absolute_source_path_); + base::SetCurrentDirectory(original_path); + absolute_source_path_ = absolute_source_path_.NormalizePathSeparatorsTo('/'); + DCHECK(absolute_source_path_.IsAbsolute()); + base::FilePath switches_file = base::MakeAbsoluteFilePath(source_path_.Append(kClangToolSwitchesPath)); std::string file_content; @@ -406,12 +441,16 @@ if (block_type == "ANNOTATION") { AnnotationInstance new_annotation; result = new_annotation.Deserialize(lines, current, end_line); - if (IsSafeListed(new_annotation.proto.source().file(), + result.set_file_path( + MakeRelativePath(absolute_source_path_, result.file_path())); + if (IsSafeListed(result.file_path(), AuditorException::ExceptionType::ALL)) { result = AuditorResult(AuditorResult::Type::RESULT_IGNORE); } switch (result.type()) { case AuditorResult::Type::RESULT_OK: + new_annotation.proto.mutable_source()->set_file(MakeRelativePath( + absolute_source_path_, new_annotation.proto.source().file())); extracted_annotations_.push_back(new_annotation); break; case AuditorResult::Type::ERROR_MISSING_TAG_USED: @@ -432,6 +471,8 @@ } else if (block_type == "CALL") { CallInstance new_call; result = new_call.Deserialize(lines, current, end_line); + new_call.file_path = + MakeRelativePath(absolute_source_path_, new_call.file_path); if (IsSafeListed(new_call.file_path, AuditorException::ExceptionType::ALL)) { result = AuditorResult(AuditorResult::Type::RESULT_IGNORE); @@ -441,6 +482,8 @@ } else if (block_type == "ASSIGNMENT") { AssignmentInstance new_assignment; result = new_assignment.Deserialize(lines, current, end_line); + new_assignment.file_path = + MakeRelativePath(absolute_source_path_, new_assignment.file_path); if (IsSafeListed(new_assignment.file_path, AuditorException::ExceptionType::ALL)) { result = AuditorResult(AuditorResult::Type::RESULT_IGNORE);
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor.h b/tools/traffic_annotation/auditor/traffic_annotation_auditor.h index a453036d..2ef563f 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor.h +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor.h
@@ -162,6 +162,8 @@ const base::FilePath build_path_; const base::FilePath clang_tool_path_; + base::FilePath absolute_source_path_; + std::vector<std::string> clang_tool_switches_; TrafficAnnotationExporter exporter_;
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc b/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc index e0731e3..6ccb370 100644 --- a/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc +++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor_ui.cc
@@ -349,16 +349,6 @@ if (tool_path.empty()) tool_path = command_line.GetProgram().DirName(); - // If source path is not provided, guess it using build path or current - // directory. - if (source_path.empty()) { - if (build_path.empty()) - base::GetCurrentDirectory(&source_path); - else - source_path = build_path.Append(base::FilePath::kParentDirectory) - .Append(base::FilePath::kParentDirectory); - } - // Get build directory, if it is empty issue an error. if (build_path.empty()) { LOG(ERROR) @@ -368,6 +358,12 @@ return 1; } + // If source path is not provided, guess it using build path. + if (source_path.empty()) { + source_path = build_path.Append(base::FilePath::kParentDirectory) + .Append(base::FilePath::kParentDirectory); + } + TrafficAnnotationAuditor auditor(source_path, build_path, tool_path); // Extract annotations.
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index 85604a5..e716ceb 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -73,8 +73,6 @@ "platform/ax_android_constants.h", "platform/ax_platform_node.cc", "platform/ax_platform_node.h", - "platform/ax_snapshot_node_android_platform.cc", - "platform/ax_snapshot_node_android_platform.h", "platform/ax_unique_id.cc", "platform/ax_unique_id.h", ] @@ -151,6 +149,16 @@ } } +source_set("ax_assistant") { + sources = [ + "ax_assistant_structure.cc", + "ax_assistant_structure.h", + ] + deps = [ + ":accessibility", + ] +} + static_library("test_support") { testonly = true sources = [
diff --git a/ui/accessibility/DEPS b/ui/accessibility/DEPS index 33a31c8..ab5cea7 100644 --- a/ui/accessibility/DEPS +++ b/ui/accessibility/DEPS
@@ -13,5 +13,8 @@ specific_include_rules = { "run_all_unittests.cc": [ "+mojo/edk/embedder", - ] + ], + "ax_assistant_util.h": [ + "+ui/accessibility/mojom", + ], }
diff --git a/ui/accessibility/platform/ax_snapshot_node_android_platform.cc b/ui/accessibility/ax_assistant_structure.cc similarity index 84% rename from ui/accessibility/platform/ax_snapshot_node_android_platform.cc rename to ui/accessibility/ax_assistant_structure.cc index 7ef8a5c..d47df20 100644 --- a/ui/accessibility/platform/ax_snapshot_node_android_platform.cc +++ b/ui/accessibility/ax_assistant_structure.cc
@@ -1,12 +1,13 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h" +#include "ui/accessibility/ax_assistant_structure.h" #include <string> #include "base/logging.h" +#include "base/optional.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -15,6 +16,7 @@ #include "ui/accessibility/ax_serializable_tree.h" #include "ui/accessibility/platform/ax_android_constants.h" #include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/range/range.h" #include "ui/gfx/transform.h" namespace ui { @@ -211,11 +213,11 @@ } } - if (text.empty() && (AXSnapshotNodeAndroid::AXRoleIsLink(node->data().role) || + if (text.empty() && (AXRoleIsLink(node->data().role) || node->data().role == ax::mojom::Role::kImage)) { base::string16 url = node->data().GetString16Attribute(ax::mojom::StringAttribute::kUrl); - text = AXSnapshotNodeAndroid::AXUrlBaseText(url); + text = AXUrlBaseText(url); } return text; } @@ -264,36 +266,135 @@ } } -} // namespace +AssistantNode* AddChild(AssistantTree* tree) { + auto node = std::make_unique<AssistantNode>(); + tree->nodes.push_back(std::move(node)); + return tree->nodes.back().get(); +} -AXSnapshotNodeAndroid::AXSnapshotNodeAndroid() = default; -AX_EXPORT AXSnapshotNodeAndroid::~AXSnapshotNodeAndroid() = default; +struct WalkAXTreeConfig { + bool should_select_leaf; + const bool show_password; +}; -// static -AX_EXPORT std::unique_ptr<AXSnapshotNodeAndroid> AXSnapshotNodeAndroid::Create( - const AXTreeUpdate& update, - bool show_password) { - auto tree = std::make_unique<AXSerializableTree>(); - if (!tree->Unserialize(update)) { - LOG(FATAL) << tree->error(); +void WalkAXTreeDepthFirst(const AXNode* node, + const gfx::Rect& rect, + const AXTreeUpdate& update, + const AXTree* tree, + WalkAXTreeConfig* config, + AssistantTree* assistant_tree, + AssistantNode* result) { + result->text = GetText(node, config->show_password); + result->class_name = + AXRoleToAndroidClassName(node->data().role, node->parent() != nullptr); + result->role = AXRoleToString(node->data().role); + + result->text_size = -1.0; + result->bgcolor = 0; + result->color = 0; + result->bold = 0; + result->italic = 0; + result->line_through = 0; + result->underline = 0; + + if (node->data().HasFloatAttribute(ax::mojom::FloatAttribute::kFontSize)) { + gfx::RectF text_size_rect( + 0, 0, 1, + node->data().GetFloatAttribute(ax::mojom::FloatAttribute::kFontSize)); + gfx::Rect scaled_text_size_rect = + gfx::ToEnclosingRect(tree->RelativeToTreeBounds(node, text_size_rect)); + result->text_size = scaled_text_size_rect.height(); + + const int32_t text_style = + node->data().GetIntAttribute(ax::mojom::IntAttribute::kTextStyle); + result->color = + node->data().GetIntAttribute(ax::mojom::IntAttribute::kColor); + result->bgcolor = + node->data().GetIntAttribute(ax::mojom::IntAttribute::kBackgroundColor); + result->bold = + (text_style & + static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleBold)) != 0; + result->italic = + (text_style & + static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleItalic)) != 0; + result->line_through = + (text_style & static_cast<int32_t>( + ax::mojom::TextStyle::kTextStyleLineThrough)) != 0; + result->underline = + (text_style & + static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleUnderline)) != 0; } + const gfx::Rect& absolute_rect = + gfx::ToEnclosingRect(tree->GetTreeBounds(node)); + gfx::Rect parent_relative_rect = absolute_rect; + bool is_root = node->parent() == nullptr; + if (!is_root) { + parent_relative_rect.Offset(-rect.OffsetFromOrigin()); + } + result->rect = gfx::Rect(parent_relative_rect.x(), parent_relative_rect.y(), + absolute_rect.width(), absolute_rect.height()); + + if (IsLeaf(node) && update.has_tree_data) { + int start_selection = 0; + int end_selection = 0; + if (update.tree_data.sel_anchor_object_id == node->id()) { + start_selection = update.tree_data.sel_anchor_offset; + config->should_select_leaf = true; + } + + if (config->should_select_leaf) { + end_selection = + static_cast<int32_t>(GetText(node, config->show_password).length()); + } + + if (update.tree_data.sel_focus_object_id == node->id()) { + end_selection = update.tree_data.sel_focus_offset; + config->should_select_leaf = false; + } + if (end_selection > 0) + result->selection = + base::make_optional<gfx::Range>(start_selection, end_selection); + } + + for (auto* child : node->children()) { + auto* n = AddChild(assistant_tree); + result->children_indices.push_back(assistant_tree->nodes.size() - 1); + WalkAXTreeDepthFirst(child, absolute_rect, update, tree, config, + assistant_tree, n); + } +} + +} // namespace + +AssistantNode::AssistantNode() = default; +AssistantNode::AssistantNode(const AssistantNode& other) = default; +AssistantNode::~AssistantNode() = default; + +AssistantTree::AssistantTree() = default; +AssistantTree::~AssistantTree() = default; + +std::unique_ptr<AssistantTree> CreateAssistantTree(const AXTreeUpdate& update, + bool show_password) { + auto tree = std::make_unique<AXSerializableTree>(); + auto assistant_tree = std::make_unique<AssistantTree>(); + auto* root = AddChild(assistant_tree.get()); + if (!tree->Unserialize(update)) + LOG(FATAL) << tree->error(); WalkAXTreeConfig config{ false, // should_select_leaf show_password // show_password }; - return WalkAXTreeDepthFirst(tree->root(), gfx::Rect(), update, tree.get(), - config); + WalkAXTreeDepthFirst(tree->root(), gfx::Rect(), update, tree.get(), &config, + assistant_tree.get(), root); + return assistant_tree; } -// static -AX_EXPORT bool AXSnapshotNodeAndroid::AXRoleIsLink(ax::mojom::Role role) { +bool AXRoleIsLink(ax::mojom::Role role) { return role == ax::mojom::Role::kLink; } -// static -AX_EXPORT base::string16 AXSnapshotNodeAndroid::AXUrlBaseText( - base::string16 url) { +base::string16 AXUrlBaseText(base::string16 url) { // Given a url like http://foo.com/bar/baz.png, just return the // base text, e.g., "baz". int trailing_slashes = 0; @@ -312,10 +413,7 @@ return url; } -// static -AX_EXPORT const char* AXSnapshotNodeAndroid::AXRoleToAndroidClassName( - ax::mojom::Role role, - bool has_parent) { +const char* AXRoleToAndroidClassName(ax::mojom::Role role, bool has_parent) { switch (role) { case ax::mojom::Role::kSearchBox: case ax::mojom::Role::kSpinButton: @@ -370,98 +468,4 @@ } } -// static -std::unique_ptr<AXSnapshotNodeAndroid> -AXSnapshotNodeAndroid::WalkAXTreeDepthFirst( - const AXNode* node, - gfx::Rect rect, - const AXTreeUpdate& update, - const AXTree* tree, - AXSnapshotNodeAndroid::WalkAXTreeConfig& config) { - auto result = - std::unique_ptr<AXSnapshotNodeAndroid>(new AXSnapshotNodeAndroid()); - result->text = GetText(node, config.show_password); - result->class_name = AXSnapshotNodeAndroid::AXRoleToAndroidClassName( - node->data().role, node->parent() != nullptr); - result->role = AXRoleToString(node->data().role); - - result->text_size = -1.0; - result->bgcolor = 0; - result->color = 0; - result->bold = 0; - result->italic = 0; - result->line_through = 0; - result->underline = 0; - - if (node->data().HasFloatAttribute(ax::mojom::FloatAttribute::kFontSize)) { - gfx::RectF text_size_rect( - 0, 0, 1, - node->data().GetFloatAttribute(ax::mojom::FloatAttribute::kFontSize)); - gfx::Rect scaled_text_size_rect = - gfx::ToEnclosingRect(tree->RelativeToTreeBounds(node, text_size_rect)); - result->text_size = scaled_text_size_rect.height(); - - const int32_t text_style = - node->data().GetIntAttribute(ax::mojom::IntAttribute::kTextStyle); - result->color = - node->data().GetIntAttribute(ax::mojom::IntAttribute::kColor); - result->bgcolor = - node->data().GetIntAttribute(ax::mojom::IntAttribute::kBackgroundColor); - result->bold = - (text_style & - static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleBold)) != 0; - result->italic = - (text_style & - static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleItalic)) != 0; - result->line_through = - (text_style & static_cast<int32_t>( - ax::mojom::TextStyle::kTextStyleLineThrough)) != 0; - result->underline = - (text_style & - static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleUnderline)) != 0; - } - - const gfx::Rect& absolute_rect = - gfx::ToEnclosingRect(tree->GetTreeBounds(node)); - gfx::Rect parent_relative_rect = absolute_rect; - bool is_root = node->parent() == nullptr; - if (!is_root) { - parent_relative_rect.Offset(-rect.OffsetFromOrigin()); - } - result->rect = gfx::Rect(parent_relative_rect.x(), parent_relative_rect.y(), - absolute_rect.width(), absolute_rect.height()); - result->has_selection = false; - - if (IsLeaf(node) && update.has_tree_data) { - int start_selection = 0; - int end_selection = 0; - if (update.tree_data.sel_anchor_object_id == node->id()) { - start_selection = update.tree_data.sel_anchor_offset; - config.should_select_leaf = true; - } - - if (config.should_select_leaf) { - end_selection = - static_cast<int32_t>(GetText(node, config.show_password).length()); - } - - if (update.tree_data.sel_focus_object_id == node->id()) { - end_selection = update.tree_data.sel_focus_offset; - config.should_select_leaf = false; - } - if (end_selection > 0) { - result->has_selection = true; - result->start_selection = start_selection; - result->end_selection = end_selection; - } - } - - for (auto* child : node->children()) { - result->children.push_back( - WalkAXTreeDepthFirst(child, absolute_rect, update, tree, config)); - } - - return result; -} - } // namespace ui
diff --git a/ui/accessibility/ax_assistant_structure.h b/ui/accessibility/ax_assistant_structure.h new file mode 100644 index 0000000..19a9cf52 --- /dev/null +++ b/ui/accessibility/ax_assistant_structure.h
@@ -0,0 +1,75 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_ACCESSIBILITY_AX_ASSISTANT_STRUCTURE_H_ +#define UI_ACCESSIBILITY_AX_ASSISTANT_STRUCTURE_H_ + +#include <cstdint> +#include <vector> + +#include "base/macros.h" +#include "base/optional.h" +#include "base/strings/string16.h" +#include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/ax_export.h" +#include "ui/accessibility/ax_tree_update.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/range/range.h" + +namespace ui { + +struct AssistantNode { + AssistantNode(); + AssistantNode(const AssistantNode& other); + ~AssistantNode(); + + std::vector<int32_t> children_indices; + + // Geometry of the view in pixels + gfx::Rect rect; + + // Text of the view. + base::string16 text; + + // Text properties + float text_size; + uint32_t color; + uint32_t bgcolor; + bool bold; + bool italic; + bool underline; + bool line_through; + + // Selected portion of the text. + base::Optional<gfx::Range> selection; + + // Fake Android view class name of the element. Each node is assigned + // a closest approximation of Android's views to keep the server happy. + std::string class_name; + + // Accessibility functionality of the node inferred from DOM or based on HTML + // role attribute. + base::Optional<std::string> role; +}; + +struct AssistantTree { + AssistantTree(); + ~AssistantTree(); + + std::vector<std::unique_ptr<AssistantNode>> nodes; + + private: + DISALLOW_COPY_AND_ASSIGN(AssistantTree); +}; + +std::unique_ptr<AssistantTree> CreateAssistantTree(const AXTreeUpdate& update, + bool show_password); + +bool AXRoleIsLink(ax::mojom::Role role); +base::string16 AXUrlBaseText(base::string16 url); +const char* AXRoleToAndroidClassName(ax::mojom::Role role, bool has_parent); + +} // namespace ui + +#endif // UI_ACCESSIBILITY_AX_ASSISTANT_STRUCTURE_H_
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc index 130d47ee..55dfa1f 100644 --- a/ui/accessibility/ax_node.cc +++ b/ui/accessibility/ax_node.cc
@@ -83,7 +83,7 @@ data_ = src; } -void AXNode::SetLocation(int offset_container_id, +void AXNode::SetLocation(int32_t offset_container_id, const gfx::RectF& location, gfx::Transform* transform) { data_.offset_container_id = offset_container_id; @@ -170,4 +170,8 @@ return base::UTF8ToUTF16(GetInheritedStringAttribute(attribute)); } +std::ostream& operator<<(std::ostream& stream, const AXNode& node) { + return stream << node.data().ToString(); +} + } // namespace ui
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h index c832a6a..ca5aa32 100644 --- a/ui/accessibility/ax_node.h +++ b/ui/accessibility/ax_node.h
@@ -7,14 +7,16 @@ #include <stdint.h> +#include <ostream> #include <vector> +#include "ui/accessibility/ax_export.h" #include "ui/accessibility/ax_node_data.h" namespace ui { // One node in an AXTree. -class AX_EXPORT AXNode { +class AX_EXPORT AXNode final { public: // The constructor requires a parent, id, and index in parent, but // the data is not required. After initialization, only index_in_parent @@ -42,18 +44,18 @@ // Returns true if the node has any of the text related roles. bool IsTextNode() const; - // Set the node's accessibility data. This may be done during initial - // initialization or later when the node data changes. + // Set the node's accessibility data. This may be done during initialization + // or later when the node data changes. void SetData(const AXNodeData& src); - // Update this node's location. This is separate from SetData just because + // Update this node's location. This is separate from |SetData| just because // changing only the location is common and should be more efficient than // re-copying all of the data. // // The node's location is stored as a relative bounding box, the ID of // the element it's relative to, and an optional transformation matrix. // See ax_node_data.h for details. - void SetLocation(int offset_container_id, + void SetLocation(int32_t offset_container_id, const gfx::RectF& location, gfx::Transform* transform); @@ -78,6 +80,102 @@ // by computing them and caching the result. std::vector<int> GetOrComputeLineStartOffsets(); + // Accessing accessibility attributes. + // See |AXNodeData| for more information. + + constexpr bool HasBoolAttribute(ax::mojom::BoolAttribute attribute) const { + return data().HasBoolAttribute(attribute); + } + constexpr bool GetBoolAttribute(ax::mojom::BoolAttribute attribute) const { + return data().GetBoolAttribute(attribute); + } + constexpr bool GetBoolAttribute(ax::mojom::BoolAttribute attribute, + bool* value) const { + return data().GetBoolAttribute(attribute, value); + } + + constexpr bool HasFloatAttribute(ax::mojom::FloatAttribute attribute) const { + return data().HasFloatAttribute(attribute); + } + constexpr float GetFloatAttribute(ax::mojom::FloatAttribute attribute) const { + return data().GetFloatAttribute(attribute); + } + constexpr bool GetFloatAttribute(ax::mojom::FloatAttribute attribute, + float* value) const { + return data().GetFloatAttribute(attribute, value); + } + + constexpr bool HasIntAttribute(ax::mojom::IntAttribute attribute) const { + return data().HasIntAttribute(attribute); + } + constexpr int32_t GetIntAttribute(ax::mojom::IntAttribute attribute) const { + return data().GetIntAttribute(attribute); + } + constexpr bool GetIntAttribute(ax::mojom::IntAttribute attribute, + int* value) const { + return data().GetIntAttribute(attribute, value); + } + + constexpr bool HasStringAttribute( + ax::mojom::StringAttribute attribute) const { + return data().HasStringAttribute(attribute); + } + constexpr const std::string& GetStringAttribute( + ax::mojom::StringAttribute attribute) const { + return data().GetStringAttribute(attribute); + } + constexpr bool GetStringAttribute(ax::mojom::StringAttribute attribute, + std::string* value) const { + return data().GetStringAttribute(attribute, value); + } + + constexpr bool GetString16Attribute(ax::mojom::StringAttribute attribute, + base::string16* value) const { + return data().GetString16Attribute(attribute, value); + } + // Cannot be constexpr because |base::string16| doesn't have a constexpr + // constructor. + base::string16 GetString16Attribute( + ax::mojom::StringAttribute attribute) const { + return data().GetString16Attribute(attribute); + } + + constexpr bool HasIntListAttribute( + ax::mojom::IntListAttribute attribute) const { + return data().HasIntListAttribute(attribute); + } + constexpr const std::vector<int32_t>& GetIntListAttribute( + ax::mojom::IntListAttribute attribute) const { + return data().GetIntListAttribute(attribute); + } + constexpr bool GetIntListAttribute(ax::mojom::IntListAttribute attribute, + std::vector<int32_t>* value) const { + return data().GetIntListAttribute(attribute, value); + } + + constexpr bool HasStringListAttribute( + ax::mojom::StringListAttribute attribute) const { + return data().HasStringListAttribute(attribute); + } + constexpr const std::vector<std::string>& GetStringListAttribute( + ax::mojom::StringListAttribute attribute) const { + return data().GetStringListAttribute(attribute); + } + constexpr bool GetStringListAttribute( + ax::mojom::StringListAttribute attribute, + std::vector<std::string>* value) const { + return data().GetStringListAttribute(attribute, value); + } + + constexpr bool GetHtmlAttribute(const char* attribute, + base::string16* value) const { + return data().GetHtmlAttribute(attribute, value); + } + constexpr bool GetHtmlAttribute(const char* attribute, + std::string* value) const { + return data().GetHtmlAttribute(attribute, value); + } + const std::string& GetInheritedStringAttribute( ax::mojom::StringAttribute attribute) const; base::string16 GetInheritedString16Attribute( @@ -95,6 +193,8 @@ AXNodeData data_; }; +AX_EXPORT std::ostream& operator<<(std::ostream& stream, const AXNode& node); + } // namespace ui #endif // UI_ACCESSIBILITY_AX_NODE_H_
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h index 8d665a2..531a3c2 100644 --- a/ui/accessibility/ax_node_data.h +++ b/ui/accessibility/ax_node_data.h
@@ -57,13 +57,14 @@ // attribute is not present. In addition, strings can be returned as // either std::string or base::string16, for convenience. - bool HasBoolAttribute(ax::mojom::BoolAttribute attr) const; - bool GetBoolAttribute(ax::mojom::BoolAttribute attr) const; - bool GetBoolAttribute(ax::mojom::BoolAttribute attr, bool* value) const; + bool HasBoolAttribute(ax::mojom::BoolAttribute attribute) const; + bool GetBoolAttribute(ax::mojom::BoolAttribute attribute) const; + bool GetBoolAttribute(ax::mojom::BoolAttribute attribute, bool* value) const; - bool HasFloatAttribute(ax::mojom::FloatAttribute attr) const; - float GetFloatAttribute(ax::mojom::FloatAttribute attr) const; - bool GetFloatAttribute(ax::mojom::FloatAttribute attr, float* value) const; + bool HasFloatAttribute(ax::mojom::FloatAttribute attribute) const; + float GetFloatAttribute(ax::mojom::FloatAttribute attribute) const; + bool GetFloatAttribute(ax::mojom::FloatAttribute attribute, + float* value) const; bool HasIntAttribute(ax::mojom::IntAttribute attribute) const; int32_t GetIntAttribute(ax::mojom::IntAttribute attribute) const; @@ -92,8 +93,8 @@ bool GetStringListAttribute(ax::mojom::StringListAttribute attribute, std::vector<std::string>* value) const; - bool GetHtmlAttribute(const char* attr, base::string16* value) const; - bool GetHtmlAttribute(const char* attr, std::string* value) const; + bool GetHtmlAttribute(const char* attribute, base::string16* value) const; + bool GetHtmlAttribute(const char* attribute, std::string* value) const; // Setting accessibility attributes. void AddStringAttribute(ax::mojom::StringAttribute attribute, @@ -223,7 +224,7 @@ // The id of an ancestor node in the same AXTree that this object's // bounding box is relative to, or -1 if there's no offset container. - int offset_container_id = -1; + int32_t offset_container_id = -1; // The relative bounding box of this node. gfx::RectF location;
diff --git a/ui/accessibility/ax_relative_bounds.cc b/ui/accessibility/ax_relative_bounds.cc index 322a068..e41cb3d6 100644 --- a/ui/accessibility/ax_relative_bounds.cc +++ b/ui/accessibility/ax_relative_bounds.cc
@@ -66,4 +66,8 @@ return result; } +std::ostream& operator<<(std::ostream& stream, const AXRelativeBounds& bounds) { + return stream << bounds.ToString(); +} + } // namespace ui
diff --git a/ui/accessibility/ax_relative_bounds.h b/ui/accessibility/ax_relative_bounds.h index 478275a..bb43598 100644 --- a/ui/accessibility/ax_relative_bounds.h +++ b/ui/accessibility/ax_relative_bounds.h
@@ -5,7 +5,10 @@ #ifndef UI_ACCESSIBILITY_AX_RELATIVE_BOUNDS_H_ #define UI_ACCESSIBILITY_AX_RELATIVE_BOUNDS_H_ +#include <stdint.h> + #include <memory> +#include <ostream> #include "ui/accessibility/ax_export.h" #include "ui/gfx/geometry/rect_f.h" @@ -30,7 +33,7 @@ // Otherwise, for a node other than the root, the bounds are relative to // the root of the tree, and for the root of a tree, the bounds are relative // to its immediate containing node. -struct AX_EXPORT AXRelativeBounds { +struct AX_EXPORT AXRelativeBounds final { AXRelativeBounds(); virtual ~AXRelativeBounds(); @@ -43,7 +46,7 @@ // The id of an ancestor node in the same AXTree that this object's // bounding box is relative to, or -1 if there's no offset container. - int offset_container_id; + int32_t offset_container_id; // The relative bounding box of this node. gfx::RectF bounds; @@ -56,6 +59,9 @@ std::unique_ptr<gfx::Transform> transform; }; +AX_EXPORT std::ostream& operator<<(std::ostream& stream, + const AXRelativeBounds& bounds); + } // namespace ui #endif // UI_ACCESSIBILITY_AX_NODE_DATA_H_
diff --git a/ui/accessibility/mojom/BUILD.gn b/ui/accessibility/mojom/BUILD.gn index 289e5ca..33ab51f 100644 --- a/ui/accessibility/mojom/BUILD.gn +++ b/ui/accessibility/mojom/BUILD.gn
@@ -6,6 +6,7 @@ mojom("mojom") { sources = [ + "ax_assistant_structure.mojom", "ax_node_data.mojom", "ax_tree_data.mojom", "ax_tree_update.mojom", @@ -16,5 +17,6 @@ "//ui/accessibility:ax_enums_mojo", "//ui/gfx/geometry/mojo", "//ui/gfx/mojo", + "//ui/gfx/range/mojo", ] }
diff --git a/ui/accessibility/mojom/ax_assistant_structure.mojom b/ui/accessibility/mojom/ax_assistant_structure.mojom new file mode 100644 index 0000000..94b2165 --- /dev/null +++ b/ui/accessibility/mojom/ax_assistant_structure.mojom
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ax.mojom; + +import "mojo/public/mojom/base/string16.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; +import "ui/gfx/range/mojo/range.mojom"; + +// Tree structure for assistant. The tree is represented as a flat array of +// nodes, each containing a children_indices vector that points to its child +// nodes. The purpose is to work around max depth restriction of recursive +// data structure in mojo. +struct AssistantTree { + array<AssistantNode> nodes; +}; + +// Represents view structure to be passed to assistant. The view structure is +// synthesized from the AXNode. +struct AssistantNode { + array<int32> children_indices; + + // Geometry of the view in pixels + gfx.mojom.Rect rect; + + // Text of the view. + mojo_base.mojom.String16 text; + + // Text properties + float text_size; + uint32 color; + uint32 bgcolor; + bool bold; + bool italic; + bool underline; + bool line_through; + + // Selected portion of the text. + gfx.mojom.Range? selection; + + // Fake Android view class name of the element. Each node is assigned + // a closest approximation of Android's views to keep the server happy. + string class_name; + + // Accessibility functionality of the node inferred from DOM or based on HTML + // role attribute. + string? role; +}; +
diff --git a/ui/accessibility/mojom/ax_assistant_structure.typemap b/ui/accessibility/mojom/ax_assistant_structure.typemap new file mode 100644 index 0000000..fe2b8aa --- /dev/null +++ b/ui/accessibility/mojom/ax_assistant_structure.typemap
@@ -0,0 +1,24 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//ui/accessibility/mojom/ax_assistant_structure.mojom" +public_headers = [ "//ui/accessibility/ax_assistant_structure.h" ] +traits_headers = + [ "//ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h" ] +sources = [ + "ax_assistant_structure_mojom_traits.cc", + "ax_assistant_structure_mojom_traits.h", +] +public_deps = [ + "//ui/accessibility:ax_assistant", + "//ui/gfx", + "//ui/gfx/geometry/mojo", + "//ui/gfx/geometry/mojo:struct_traits", + "//ui/gfx/range/mojo", + "//ui/gfx/range/mojo:struct_traits", +] +type_mappings = [ + "ax.mojom.AssistantTree=ui::AssistantTree[move_only]", + "ax.mojom.AssistantNode=std::unique_ptr<ui::AssistantNode>[move_only]", +]
diff --git a/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.cc b/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.cc new file mode 100644 index 0000000..54a2014 --- /dev/null +++ b/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.cc
@@ -0,0 +1,56 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h" + +#include "mojo/public/cpp/base/string16_mojom_traits.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "ui/gfx/range/mojo/range_struct_traits.h" + +namespace mojo { + +// static +bool StructTraits<ax::mojom::AssistantTreeDataView, ui::AssistantTree>::Read( + ax::mojom::AssistantTreeDataView data, + ui::AssistantTree* out) { + if (!data.ReadNodes(&out->nodes)) + return false; + for (size_t i = 0; i < out->nodes.size(); i++) { + // Each child's index should be greater than its parent and within the array + // bounds. This implies that there is no circle in the tree. + for (size_t child_index : out->nodes[i]->children_indices) { + if (child_index <= i || child_index >= out->nodes.size()) + return false; + } + } + return true; +} + +// static +bool StructTraits<ax::mojom::AssistantNodeDataView, + std::unique_ptr<ui::AssistantNode>>:: + Read(ax::mojom::AssistantNodeDataView data, + std::unique_ptr<ui::AssistantNode>* out) { + DCHECK(!out->get()); + *out = std::make_unique<ui::AssistantNode>(); + (*out)->bgcolor = data.bgcolor(); + (*out)->bold = data.bold(); + + (*out)->color = data.color(); + (*out)->italic = data.italic(); + (*out)->line_through = data.line_through(); + (*out)->underline = data.underline(); + + if (!data.ReadRect(&(*out)->rect) || !data.ReadText(&(*out)->text) || + !data.ReadRole(&(*out)->role) || + !data.ReadSelection(&(*out)->selection) || + !data.ReadChildrenIndices(&(*out)->children_indices) || + !data.ReadClassName(&(*out)->class_name)) { + return false; + } + + return true; +} + +} // namespace mojo
diff --git a/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h b/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h new file mode 100644 index 0000000..dbbac8ec --- /dev/null +++ b/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h
@@ -0,0 +1,74 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_ACCESSIBILITY_MOJOM_AX_ASSISTANT_STRUCTURE_MOJOM_TRAITS_H_ +#define UI_ACCESSIBILITY_MOJOM_AX_ASSISTANT_STRUCTURE_MOJOM_TRAITS_H_ + +#include <memory> + +#include "ui/accessibility/ax_assistant_structure.h" +#include "ui/accessibility/mojom/ax_assistant_structure.mojom-shared.h" +#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<ax::mojom::AssistantTreeDataView, ui::AssistantTree> { + static bool Read(ax::mojom::AssistantTreeDataView data, + ui::AssistantTree* out); +}; + +template <> +struct StructTraits<ax::mojom::AssistantNodeDataView, + std::unique_ptr<ui::AssistantNode>> { + static std::vector<int32_t> children_indices( + const std::unique_ptr<ui::AssistantNode>& node) { + return node->children_indices; + } + static gfx::Rect rect(const std::unique_ptr<ui::AssistantNode>& node) { + return node->rect; + } + static base::string16 text(const std::unique_ptr<ui::AssistantNode>& node) { + return node->text; + } + static float text_size(const std::unique_ptr<ui::AssistantNode>& node) { + return node->text_size; + } + static uint32_t color(const std::unique_ptr<ui::AssistantNode>& node) { + return node->color; + } + static uint32_t bgcolor(const std::unique_ptr<ui::AssistantNode>& node) { + return node->bgcolor; + } + static bool bold(const std::unique_ptr<ui::AssistantNode>& node) { + return node->bold; + } + static bool italic(const std::unique_ptr<ui::AssistantNode>& node) { + return node->italic; + } + static bool underline(const std::unique_ptr<ui::AssistantNode>& node) { + return node->underline; + } + static bool line_through(const std::unique_ptr<ui::AssistantNode>& node) { + return node->line_through; + } + static base::Optional<gfx::Range> selection( + const std::unique_ptr<ui::AssistantNode>& node) { + return node->selection; + } + static std::string class_name( + const std::unique_ptr<ui::AssistantNode>& node) { + return node->class_name; + } + static base::Optional<std::string> role( + const std::unique_ptr<ui::AssistantNode>& node) { + return node->role; + } + static bool Read(ax::mojom::AssistantNodeDataView data, + std::unique_ptr<ui::AssistantNode>* out); +}; + +} // namespace mojo + +#endif // UI_ACCESSIBILITY_MOJOM_AX_ASSISTANT_STRUCTURE_MOJOM_TRAITS_H_
diff --git a/ui/accessibility/mojom/typemaps.gni b/ui/accessibility/mojom/typemaps.gni index 019293d4..cd4fbb9d4 100644 --- a/ui/accessibility/mojom/typemaps.gni +++ b/ui/accessibility/mojom/typemaps.gni
@@ -6,4 +6,5 @@ "//ui/accessibility/mojom/ax_node_data.typemap", "//ui/accessibility/mojom/ax_tree_data.typemap", "//ui/accessibility/mojom/ax_tree_update.typemap", + "//ui/accessibility/mojom/ax_assistant_structure.typemap", ]
diff --git a/ui/accessibility/platform/ax_snapshot_node_android_platform.h b/ui/accessibility/platform/ax_snapshot_node_android_platform.h deleted file mode 100644 index f550221..0000000 --- a/ui/accessibility/platform/ax_snapshot_node_android_platform.h +++ /dev/null
@@ -1,83 +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_ACCESSIBILITY_PLATFORM_AX_SNAPSHOT_ANDROID_H_ -#define UI_ACCESSIBILITY_PLATFORM_AX_SNAPSHOT_ANDROID_H_ - -#include <cstdint> -#include <memory> -#include <vector> - -#include "base/optional.h" -#include "base/strings/string16.h" -#include "ui/accessibility/ax_enums.mojom.h" -#include "ui/accessibility/ax_export.h" -#include "ui/accessibility/ax_tree_update.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { - -class AXNode; -class AXTree; - -// An intermediate representation of the accessibility snapshot -// in order to share code between ARC and Android. The field names -// are kept consistent with AccessibilitySnapshotNode.java. -struct AXSnapshotNodeAndroid { - // Builds a whole tree of AXSnapshotNodeAndroid objects from - // an AXTreeUpdate. - AX_EXPORT static std::unique_ptr<AXSnapshotNodeAndroid> Create( - const AXTreeUpdate& update, - bool show_password); - - // Returns a fake Android view class that is a closest - // approximation of the ax::mojom::Role. - AX_EXPORT static const char* AXRoleToAndroidClassName(ax::mojom::Role role, - bool has_parent); - - AX_EXPORT static bool AXRoleIsLink(ax::mojom::Role role); - - AX_EXPORT static base::string16 AXUrlBaseText(base::string16 url); - - AX_EXPORT ~AXSnapshotNodeAndroid(); - - gfx::Rect rect; - base::string16 text; - float text_size; - int32_t color; - int32_t bgcolor; - bool bold; - bool italic; - bool underline; - bool line_through; - - bool has_selection; - int32_t start_selection; - int32_t end_selection; - - base::Optional<std::string> role; - std::string class_name; - std::vector<std::unique_ptr<AXSnapshotNodeAndroid>> children; - - private: - AXSnapshotNodeAndroid(); - - struct WalkAXTreeConfig { - bool should_select_leaf; - const bool show_password; - }; - - static std::unique_ptr<AXSnapshotNodeAndroid> WalkAXTreeDepthFirst( - const AXNode* node, - gfx::Rect rect, - const AXTreeUpdate& update, - const AXTree* tree, - WalkAXTreeConfig& config); - - DISALLOW_COPY_AND_ASSIGN(AXSnapshotNodeAndroid); -}; - -} // namespace ui - -#endif // UI_ACCESSIBILITY_PLATFORM_AX_SNAPSHOT_ANDROID_H_
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc index 1c5c7c92..ad15a65 100644 --- a/ui/android/delegated_frame_host_android.cc +++ b/ui/android/delegated_frame_host_android.cc
@@ -4,6 +4,7 @@ #include "ui/android/delegated_frame_host_android.h" +#include "base/android/build_info.h" #include "base/bind.h" #include "base/logging.h" #include "cc/layers/solid_color_layer.h" @@ -25,6 +26,16 @@ namespace { +// Wait up to 5 seconds for the first frame to be produced. Having Android +// display a placeholder for a longer period of time is preferable to drawing +// nothing, and the first frame can take a while on low-end systems. +static const int64_t kFirstFrameTimeoutSeconds = 5; + +// Wait up to 1 second for a frame of the correct size to be produced. Android +// OS will only wait 4 seconds, so we limit this to 1 second to make sure we +// have always produced a frame before the OS stops waiting. +static const int64_t kResizeTimeoutSeconds = 1; + constexpr viz::LocalSurfaceId kInvalidLocalSurfaceId; scoped_refptr<cc::SurfaceLayer> CreateSurfaceLayer( @@ -99,7 +110,12 @@ support_->SubmitCompositorFrame(local_surface_id, std::move(frame), std::move(hit_test_region_list)); } + compositor_attach_until_frame_lock_.reset(); + + DCHECK(content_layer_); + if (content_layer_->bounds() == expected_pixel_size_) + compositor_pending_resize_lock_.reset(); } void DelegatedFrameHostAndroid::DidNotProduceFrame( @@ -196,8 +212,8 @@ // frame from being produced. If we already have delegated content, no need // to take the lock. if (compositor->IsDrawingFirstVisibleFrame() && !HasDelegatedContent()) { - compositor_attach_until_frame_lock_ = - compositor->GetCompositorLock(this, base::TimeDelta::FromSeconds(5)); + compositor_attach_until_frame_lock_ = compositor->GetCompositorLock( + this, base::TimeDelta::FromSeconds(kFirstFrameTimeoutSeconds)); } compositor->AddChildFrameSink(frame_sink_id_); client_->SetBeginFrameSource(&begin_frame_source_); @@ -208,6 +224,7 @@ if (!registered_parent_compositor_) return; compositor_attach_until_frame_lock_.reset(); + compositor_pending_resize_lock_.reset(); client_->SetBeginFrameSource(nullptr); support_->SetNeedsBeginFrame(false); registered_parent_compositor_->RemoveChildFrameSink(frame_sink_id_); @@ -221,6 +238,26 @@ // delegated_frame_host.cc. https://crbug.com/801350 } +void DelegatedFrameHostAndroid::PixelSizeWillChange( + const gfx::Size& pixel_size) { + // We never take the resize lock unless we're on O+, as previous versions of + // Android won't wait for us to produce the correct sized frame and will end + // up looking worse. + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_OREO) { + return; + } + + expected_pixel_size_ = pixel_size; + if (registered_parent_compositor_) { + if (!content_layer_ || content_layer_->bounds() != expected_pixel_size_) { + compositor_pending_resize_lock_ = + registered_parent_compositor_->GetCompositorLock( + this, base::TimeDelta::FromSeconds(kResizeTimeoutSeconds)); + } + } +} + void DelegatedFrameHostAndroid::DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) { client_->ReclaimResources(resources);
diff --git a/ui/android/delegated_frame_host_android.h b/ui/android/delegated_frame_host_android.h index 63277a6..97945c5 100644 --- a/ui/android/delegated_frame_host_android.h +++ b/ui/android/delegated_frame_host_android.h
@@ -89,6 +89,10 @@ void SynchronizeVisualProperties(); + // Called when we begin a resize operation. Takes the compositor lock until we + // receive a frame of the expected size. + void PixelSizeWillChange(const gfx::Size& pixel_size); + // Returns the ID for the current Surface. Returns an invalid ID if no // surface exists (!HasDelegatedContent()). const viz::SurfaceId& SurfaceId() const; @@ -143,11 +147,19 @@ const bool enable_surface_synchronization_; viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_; + // The size we are resizing to. Once we receive a frame of this size we can + // release any resize compositor lock. + gfx::Size expected_pixel_size_; + // A lock that is held from the point at which we attach to the compositor to // the point at which we submit our first frame to the compositor. This // ensures that the compositor doesn't swap without a frame available. std::unique_ptr<ui::CompositorLock> compositor_attach_until_frame_lock_; + // A lock that is held from the point we begin resizing this frame to the + // point at which we receive a frame of the correct size. + std::unique_ptr<ui::CompositorLock> compositor_pending_resize_lock_; + DISALLOW_COPY_AND_ASSIGN(DelegatedFrameHostAndroid); };
diff --git a/ui/android/delegated_frame_host_android_unittest.cc b/ui/android/delegated_frame_host_android_unittest.cc index fc0c6c4b..288f21f 100644 --- a/ui/android/delegated_frame_host_android_unittest.cc +++ b/ui/android/delegated_frame_host_android_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ui/android/delegated_frame_host_android.h" +#include "base/android/build_info.h" #include "base/test/test_mock_time_task_runner.h" #include "cc/layers/layer.h" #include "cc/layers/solid_color_layer.h" @@ -90,10 +91,10 @@ return lock_manager_.GetCompositorLock(client, time_delta).release(); } - void SubmitCompositorFrame() { + void SubmitCompositorFrame(const gfx::Size& frame_size = gfx::Size(10, 10)) { viz::CompositorFrame frame; auto render_pass = viz::RenderPass::Create(); - render_pass->output_rect = gfx::Rect(10, 10); + render_pass->output_rect = gfx::Rect(frame_size); frame.render_pass_list.push_back(std::move(render_pass)); frame.metadata.begin_frame_ack.sequence_number = 1; frame.metadata.device_scale_factor = 1; @@ -101,6 +102,20 @@ viz::mojom::HitTestRegionList::New()); } + void SetUpValidFrame(const gfx::Size& frame_size) { + EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()) + .WillOnce(Return(true)); + EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) + .WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock)); + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true)) + .Times(1); + frame_host_->AttachToCompositor(&compositor_); + + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false)) + .Times(1); + SubmitCompositorFrame(frame_size); + } + protected: MockWindowAndroidCompositor compositor_; ui::ViewAndroid view_; @@ -163,5 +178,97 @@ frame_host_->DetachFromCompositor(); } +TEST_F(DelegatedFrameHostAndroidTest, ResizeLockBasic) { + // Resize lock is only enabled on O+. + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_OREO) { + return; + } + + SetUpValidFrame(gfx::Size(10, 10)); + + // Tell the frame host to resize, it should take a lock. + EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) + .WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock)); + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true)) + .Times(1); + frame_host_->PixelSizeWillChange(gfx::Size(50, 50)); + + // Submit a frame of the wrong size, nothing should change. + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false)) + .Times(0); + SubmitCompositorFrame(gfx::Size(20, 20)); + + // Submit a frame with the right size, the lock should release. + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false)) + .Times(1); + SubmitCompositorFrame(gfx::Size(50, 50)); +} + +TEST_F(DelegatedFrameHostAndroidTest, ResizeLockNotTakenIfNoSizeChange) { + // Resize lock is only enabled on O+. + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_OREO) { + return; + } + + SetUpValidFrame(gfx::Size(10, 10)); + + // Tell the frame host to resize to the existing size, nothing should happen. + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true)) + .Times(0); + frame_host_->PixelSizeWillChange(gfx::Size(10, 10)); +} + +TEST_F(DelegatedFrameHostAndroidTest, ResizeLockReleasedWithDetach) { + // Resize lock is only enabled on O+. + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_OREO) { + return; + } + + SetUpValidFrame(gfx::Size(10, 10)); + + // Tell the frame host to resize, it should take a lock. + EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) + .WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock)); + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true)) + .Times(1); + frame_host_->PixelSizeWillChange(gfx::Size(50, 50)); + + // Lock should be released when we detach. + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false)) + .Times(1); + frame_host_->DetachFromCompositor(); +} + +TEST_F(DelegatedFrameHostAndroidTest, TestBothCompositorLocks) { + // Resize lock is only enabled on O+. + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_OREO) { + return; + } + + // Attach during the first frame, first lock will be taken. + EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).WillOnce(Return(true)); + EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) + .WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock)); + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true)) + .Times(1); + frame_host_->AttachToCompositor(&compositor_); + + // Tell the frame host to resize, it should take a second lock. + EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) + .WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock)); + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true)) + .Times(0); + frame_host_->PixelSizeWillChange(gfx::Size(50, 50)); + + // Submit a compositor frame of the right size, both locks should release. + EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false)) + .Times(1); + SubmitCompositorFrame(gfx::Size(50, 50)); +} + } // namespace } // namespace ui
diff --git a/ui/arc/notification/arc_notification_content_view_unittest.cc b/ui/arc/notification/arc_notification_content_view_unittest.cc index 2a2fb6f..ee3bf45 100644 --- a/ui/arc/notification/arc_notification_content_view_unittest.cc +++ b/ui/arc/notification/arc_notification_content_view_unittest.cc
@@ -10,9 +10,9 @@ #include "ash/message_center/message_center_view.h" #include "ash/shell.h" +#include "ash/system/message_center/notification_tray.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" -#include "ash/system/web_notification/web_notification_tray.h" #include "ash/test/ash_test_base.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" @@ -320,7 +320,7 @@ // Show MessageCenterView and activate its widget. auto* notification_tray = ash::StatusAreaWidgetTestHelper::GetStatusAreaWidget() - ->web_notification_tray(); + ->notification_tray(); notification_tray->ShowBubble(false /* show_by_click */); notification_tray->GetBubbleView() ->GetWidget()
diff --git a/ui/aura/test/aura_test_suite_setup.cc b/ui/aura/test/aura_test_suite_setup.cc index 7965032..35b2307 100644 --- a/ui/aura/test/aura_test_suite_setup.cc +++ b/ui/aura/test/aura_test_suite_setup.cc
@@ -41,7 +41,7 @@ DCHECK(!Env::GetInstanceDontCreate()); #if BUILDFLAG(ENABLE_MUS) const Env::Mode env_mode = - features::IsMusEnabled() ? Env::Mode::MUS : Env::Mode::LOCAL; + features::IsMashEnabled() ? Env::Mode::MUS : Env::Mode::LOCAL; env_ = Env::CreateInstance(env_mode); if (env_mode == Env::Mode::MUS) ConfigureMus();
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 64d19b6..a162bb8 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -359,6 +359,7 @@ "dragdrop/cocoa_dnd_util.mm", "dragdrop/file_info.cc", "dragdrop/file_info.h", + "emoji/emoji_panel_helper.h", "idle/idle.cc", "idle/idle.h", "idle/idle_chromeos.cc", @@ -375,6 +376,15 @@ } if (is_mac) { + sources += [ "emoji/emoji_panel_helper_mac.mm" ] + } else if (is_win) { + sources += [ "emoji/emoji_panel_helper_win.cc" ] + } else { + # Empty implementation for all other platforms. + sources += [ "emoji/emoji_panel_helper.cc" ] + } + + if (is_mac) { sources += [ "accelerators/media_keys_listener_mac.mm" ] } else { sources += [ "accelerators/media_keys_listener_stub.cc" ]
diff --git a/ui/base/emoji/emoji_panel_helper.cc b/ui/base/emoji/emoji_panel_helper.cc new file mode 100644 index 0000000..03a82065 --- /dev/null +++ b/ui/base/emoji/emoji_panel_helper.cc
@@ -0,0 +1,15 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/emoji/emoji_panel_helper.h" + +namespace ui { + +bool IsEmojiPanelSupported() { + return false; +} + +void ShowEmojiPanel() {} + +} // namespace ui
diff --git a/ui/base/emoji/emoji_panel_helper.h b/ui/base/emoji/emoji_panel_helper.h new file mode 100644 index 0000000..0fbb9a80 --- /dev/null +++ b/ui/base/emoji/emoji_panel_helper.h
@@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_EMOJI_EMOJI_PANEL_HELPER_H_ +#define UI_BASE_EMOJI_EMOJI_PANEL_HELPER_H_ + +#include "ui/base/ui_base_export.h" + +namespace ui { + +// Returns whether showing the Emoji Panel is supported on this version of +// the operating system. +UI_BASE_EXPORT bool IsEmojiPanelSupported(); + +// Invokes the commands to show the Emoji Panel. +UI_BASE_EXPORT void ShowEmojiPanel(); + +} // namespace ui + +#endif // UI_BASE_EMOJI_EMOJI_PANEL_HELPER_H_ \ No newline at end of file
diff --git a/ui/base/emoji/emoji_panel_helper_mac.mm b/ui/base/emoji/emoji_panel_helper_mac.mm new file mode 100644 index 0000000..d322ea5 --- /dev/null +++ b/ui/base/emoji/emoji_panel_helper_mac.mm
@@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/emoji/emoji_panel_helper.h" + +#import <Cocoa/Cocoa.h> + +#include "base/feature_list.h" +#include "ui/base/ui_base_features.h" + +namespace ui { + +bool IsEmojiPanelSupported() { + return base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu); +} + +void ShowEmojiPanel() { + [NSApp orderFrontCharacterPalette:nil]; +} + +} // namespace ui
diff --git a/ui/base/emoji/emoji_panel_helper_win.cc b/ui/base/emoji/emoji_panel_helper_win.cc new file mode 100644 index 0000000..23124db1 --- /dev/null +++ b/ui/base/emoji/emoji_panel_helper_win.cc
@@ -0,0 +1,44 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/emoji/emoji_panel_helper.h" + +#include <windows.h> + +#include "base/feature_list.h" +#include "base/win/windows_version.h" +#include "ui/base/ui_base_features.h" +#include "ui/events/keycodes/keyboard_code_conversion_win.h" + +namespace ui { + +bool IsEmojiPanelSupported() { + return base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu) && + // Emoji picker is supported on Windows 10's Spring 2018 Update and + // above. + base::win::GetVersion() >= base::win::Version::VERSION_WIN10_RS4; +} + +void ShowEmojiPanel() { + // This sends Windows Key + '.' (both keydown and keyup events). + // "SendInput" is used because Windows needs to receive these events and + // open the Emoji picker. + // TODO(crbug.com/827404): Move to a specialized Windows API once it is + // available. + INPUT input[4] = {}; + input[0].type = INPUT_KEYBOARD; + input[0].ki.wVk = ui::WindowsKeyCodeForKeyboardCode(ui::VKEY_COMMAND); + input[1].type = INPUT_KEYBOARD; + input[1].ki.wVk = ui::WindowsKeyCodeForKeyboardCode(ui::VKEY_OEM_PERIOD); + + input[2].type = INPUT_KEYBOARD; + input[2].ki.wVk = ui::WindowsKeyCodeForKeyboardCode(ui::VKEY_COMMAND); + input[2].ki.dwFlags |= KEYEVENTF_KEYUP; + input[3].type = INPUT_KEYBOARD; + input[3].ki.wVk = ui::WindowsKeyCodeForKeyboardCode(ui::VKEY_OEM_PERIOD); + input[3].ki.dwFlags |= KEYEVENTF_KEYUP; + ::SendInput(4, input, sizeof(INPUT)); +} + +} // namespace ui
diff --git a/ui/base/models/menu_model.cc b/ui/base/models/menu_model.cc index 2bed400..91ed8f1b 100644 --- a/ui/base/models/menu_model.cc +++ b/ui/base/models/menu_model.cc
@@ -17,7 +17,14 @@ const int item_count = (*model)->GetItemCount(); for (int i = 0; i < item_count; ++i) { const int candidate_index = i; - if ((*model)->GetTypeAt(candidate_index) == TYPE_SUBMENU) { + // Actionable submenus have commands. + if ((*model)->GetTypeAt(candidate_index) == TYPE_ACTIONABLE_SUBMENU && + (*model)->GetCommandIdAt(candidate_index) == command_id) { + *index = candidate_index; + return true; + } + if ((*model)->GetTypeAt(candidate_index) == TYPE_SUBMENU || + (*model)->GetTypeAt(candidate_index) == TYPE_ACTIONABLE_SUBMENU) { MenuModel* submenu_model = (*model)->GetSubmenuModelAt(candidate_index); if (GetModelAndIndexForCommandId(command_id, &submenu_model, index)) { *model = submenu_model;
diff --git a/ui/base/models/menu_model.h b/ui/base/models/menu_model.h index 605dc1b..a19e6e9 100644 --- a/ui/base/models/menu_model.h +++ b/ui/base/models/menu_model.h
@@ -28,12 +28,13 @@ public: // The type of item. enum ItemType { - TYPE_COMMAND, - TYPE_CHECK, - TYPE_RADIO, - TYPE_SEPARATOR, - TYPE_BUTTON_ITEM, - TYPE_SUBMENU + TYPE_COMMAND, // Performs an action when selected. + TYPE_CHECK, // Can be selected/checked to toggle a boolean state. + TYPE_RADIO, // Can be selected/checked among a group of choices. + TYPE_SEPARATOR, // Shows a horizontal line separator. + TYPE_BUTTON_ITEM, // Shows a row of buttons. + TYPE_SUBMENU, // Presents a submenu within another menu. + TYPE_ACTIONABLE_SUBMENU, // A SUBMENU that is also a COMMAND. }; virtual ~MenuModel() {}
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc index b7b3429..1b8eefc 100644 --- a/ui/base/models/simple_menu_model.cc +++ b/ui/base/models/simple_menu_model.cc
@@ -159,6 +159,26 @@ AddSubMenu(command_id, l10n_util::GetStringUTF16(string_id), model); } +void SimpleMenuModel::AddActionableSubMenu(int command_id, + const base::string16& label, + MenuModel* model) { + Item item(command_id, TYPE_ACTIONABLE_SUBMENU, label); + item.submenu = model; + AppendItem(std::move(item)); +} + +void SimpleMenuModel::AddActionableSubmenuWithStringIdAndIcon( + int command_id, + int string_id, + MenuModel* model, + const gfx::ImageSkia& icon) { + Item item(command_id, TYPE_ACTIONABLE_SUBMENU, + l10n_util::GetStringUTF16(string_id)); + item.submenu = model; + item.icon = gfx::Image(icon); + AppendItem(std::move(item)); +} + void SimpleMenuModel::InsertItemAt(int index, int command_id, const base::string16& label) {
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h index ecc620a..feb3d66 100644 --- a/ui/base/models/simple_menu_model.h +++ b/ui/base/models/simple_menu_model.h
@@ -93,13 +93,20 @@ // or SPACING. NORMAL separators are silently ignored if the model is empty. void AddSeparator(MenuSeparatorType separator_type); - // These three methods take pointers to various sub-models. These models - // should be owned by the same owner of this SimpleMenuModel. + // These methods take pointers to various sub-models. These models should be + // owned by the same owner of this SimpleMenuModel. void AddButtonItem(int command_id, ButtonMenuItemModel* model); void AddSubMenu(int command_id, const base::string16& label, MenuModel* model); void AddSubMenuWithStringId(int command_id, int string_id, MenuModel* model); + void AddActionableSubMenu(int command_id, + const base::string16& label, + MenuModel* model); + void AddActionableSubmenuWithStringIdAndIcon(int command_id, + int string_id, + MenuModel* model, + const gfx::ImageSkia& icon); // Methods for inserting items into the model. void InsertItemAt(int index, int command_id, const base::string16& label);
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 23e3147..227c00b 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -87,21 +87,12 @@ "PrecisionTouchpadScrollPhase", base::FEATURE_ENABLED_BY_DEFAULT}; #endif // defined(OS_WIN) -// Used to have ash run in its own process. This implicitly turns on the -// WindowService. That is, if this is set IsMusEnabled() returns true. +// Used to have ash (Chrome OS system UI) run in its own process. +// TODO(jamescook): Make flag only available in Chrome OS. const base::Feature kMash = {"Mash", base::FEATURE_DISABLED_BY_DEFAULT}; -// Used to control the mus service (aka the UI service). This makes mus run in -// process. -const base::Feature kMus = {"Mus", base::FEATURE_DISABLED_BY_DEFAULT}; - -bool IsMusEnabled() { -#if defined(USE_AURA) - return base::FeatureList::IsEnabled(features::kMus) || - base::FeatureList::IsEnabled(features::kMash); -#else - return false; -#endif +bool IsMashEnabled() { + return base::FeatureList::IsEnabled(features::kMash); } #if defined(OS_MACOSX)
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index cc7a15d..85e6084b 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -37,15 +37,9 @@ // TODO(sky): rename this to something that better conveys what it means. UI_BASE_EXPORT extern const base::Feature kMash; -// WARNING: generally you should only use this in tests to enable the feature. -// Outside of tests use IsMusEnabled() to detect if mus is enabled. -// TODO(sky): rename this to kWindowService. -UI_BASE_EXPORT extern const base::Feature kMus; -// Returns true if mus (the Window Service) is enabled. -// NOTE: this returns true if either kMus or kMash is specified. -// TODO(sky): rename this to IsWindowServiceEnabled(). -UI_BASE_EXPORT bool IsMusEnabled(); +// Returns true if mash (out-of-process ash system UI) is enabled. +UI_BASE_EXPORT bool IsMashEnabled(); #if defined(OS_MACOSX) // Returns true if the NSWindows for apps will be created in the app's process,
diff --git a/ui/base/ui_features.gni b/ui/base/ui_features.gni index 25f9980..2691c6f 100644 --- a/ui/base/ui_features.gni +++ b/ui/base/ui_features.gni
@@ -17,8 +17,7 @@ # Whether the message center should be included for displaying notifications. enable_message_center = is_win || is_mac || is_linux || is_chromeos - # Set to true to if mus (aka the UI service) is enabled. Use the features kMus - # (or kMash in chrome code) to start in mus/mash. + # Set to true to if mus (aka the window service) is enabled. enable_mus = is_chromeos }
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 455c6739..5ca9d25 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -279,7 +279,7 @@ void Compositor::SetLocalSurfaceId( const viz::LocalSurfaceId& local_surface_id) { - host_->SetLocalSurfaceId(local_surface_id); + host_->SetLocalSurfaceIdFromParent(local_surface_id); } void Compositor::SetLayerTreeFrameSink( @@ -367,7 +367,7 @@ if (size_ != size_in_pixel && local_surface_id.is_valid()) { // A new LocalSurfaceId must be set when the compositor size changes. - DCHECK_NE(local_surface_id, host_->local_surface_id()); + DCHECK_NE(local_surface_id, host_->local_surface_id_from_parent()); } if (!size_in_pixel.IsEmpty()) {
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index f1cccf22..fc8f445 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -1614,20 +1614,21 @@ ManagedDisplayMode display_mode; if (!GetActiveModeForDisplayId(display_id, &display_mode)) return false; - const std::vector<double> zooms = GetDisplayZoomFactors(display_mode); auto iter = display_info_.find(display_id); if (iter == display_info_.end()) return false; - const double current_display_zoom = iter->second.zoom_factor(); + const float current_display_zoom = iter->second.zoom_factor(); // Find the index of |current_display_zoom| in |zooms|. The nearest value is // used if the exact match is not found. + const std::vector<float> zooms = GetDisplayZoomFactors(display_mode); std::size_t zoom_idx = 0; - double min_diff = std::abs(zooms[zoom_idx] - current_display_zoom); + float min_diff = std::abs(zooms[zoom_idx] - current_display_zoom); for (std::size_t i = 1; i < zooms.size(); i++) { - if (std::abs(current_display_zoom - zooms[i]) < min_diff) { - min_diff = std::abs(current_display_zoom - zooms[i]); + const float diff = std::abs(current_display_zoom - zooms[i]); + if (diff < min_diff) { + min_diff = diff; zoom_idx = i; } } @@ -1652,7 +1653,7 @@ auto iter = display_info_.find(display_id); if (iter == display_info_.end()) return; - if (std::abs(iter->second.zoom_factor() - 1.f) > 0.001) { + if (std::abs(iter->second.zoom_factor() - 1.f) > 0.001f) { iter->second.set_zoom_factor(1.f); UpdateDisplays(); }
diff --git a/ui/display/manager/display_util.cc b/ui/display/manager/display_util.cc index e3ff3d3..bbb6c05 100644 --- a/ui/display/manager/display_util.cc +++ b/ui/display/manager/display_util.cc
@@ -16,11 +16,6 @@ namespace display { namespace { -// The list of deltas between two consecutive zoom level. Any display must have -// one of these values as the difference between two consecutive zoom level. -constexpr std::array<double, 7> kZoomFactorDeltas = {0.05f, 0.1f, 0.15f, 0.2f, - 0.25f, 0.5f, 1.f}; - // The maximum logical resolution width allowed when zooming out for a display. constexpr int kDefaultMaxZoomWidth = 4096; @@ -30,6 +25,37 @@ // The total number of display zoom factors to enumerate. constexpr int kNumOfZoomFactors = 9; +bool WithinEpsilon(float a, float b) { + return std::abs(a - b) < std::numeric_limits<float>::epsilon(); +} + +// Clamps the delta between consecutive zoom factors to a user friendly and UI +// friendly value. +float ClampToUserFriendlyDelta(float delta) { + // NOTE: If these thresholds are updated, please also update aura-shell.xml. + // The list of deltas between two consecutive zoom level. Any display must + // have one of these values as the difference between two consecutive zoom + // level. + // The array of pair represents which user friendly delta value must the given + // raw |delta| be clamped to. + // std::pair::first - represents the threshold. + // std::pair::second - represents the user friendly clamped delta + constexpr std::array<std::pair<float, float>, 7> kZoomFactorDeltas = { + {{0.05f, 0.05f}, + {0.1f, 0.1f}, + {0.15f, 0.15f}, + {0.2f, 0.2f}, + {0.25f, 0.25f}, + {0.7f, 0.3f}, + {1.f, 0.5f}}}; + std::size_t delta_index = 0; + while (delta_index < kZoomFactorDeltas.size() && + delta >= kZoomFactorDeltas[delta_index].first) { + delta_index++; + } + return kZoomFactorDeltas[delta_index - 1].second; +} + } // namespace std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) { @@ -90,7 +116,7 @@ return !(type & DISPLAY_CONNECTION_TYPE_NETWORK); } -std::vector<double> GetDisplayZoomFactors(const ManagedDisplayMode& mode) { +std::vector<float> GetDisplayZoomFactors(const ManagedDisplayMode& mode) { const int effective_width = std::round( static_cast<float>(mode.size().width()) / mode.device_scale_factor()); @@ -110,19 +136,19 @@ // and clamping was performed, then update the total range of logical // resolutions and ensure that everything lies within the maximum and minimum // resolution range. - const int interval = std::round(static_cast<double>(effective_width) * 1.5f); + const int interval = std::round(static_cast<float>(effective_width) * 1.5f); if (max_effective_width == max_width) min_effective_width = std::max(max_effective_width - interval, min_width); if (min_effective_width == min_width) max_effective_width = std::min(min_effective_width + interval, max_width); - double max_zoom = static_cast<double>(effective_width) / - static_cast<double>(min_effective_width); - double min_zoom = static_cast<double>(effective_width) / - static_cast<double>(max_effective_width); + float max_zoom = static_cast<float>(effective_width) / + static_cast<float>(min_effective_width); + float min_zoom = static_cast<float>(effective_width) / + static_cast<float>(max_effective_width); - double delta = - (max_zoom - min_zoom) / static_cast<double>(kNumOfZoomFactors - 1); + float delta = + (max_zoom - min_zoom) / static_cast<float>(kNumOfZoomFactors - 1); // Number of zoom values above 100% zoom. const int zoom_in_count = std::round((max_zoom - 1.f) / delta); @@ -130,21 +156,65 @@ // Number of zoom values below 100% zoom. const int zoom_out_count = kNumOfZoomFactors - zoom_in_count - 1; - // Clamp the delta between consecutive zoom factors to a user friendly and UI - // friendly value. - std::size_t delta_index = 0; - while (delta_index < kZoomFactorDeltas.size() && - delta >= kZoomFactorDeltas[delta_index]) { - delta_index++; - } - delta = kZoomFactorDeltas[delta_index - 1]; + delta = ClampToUserFriendlyDelta(delta); + // Populate the zoom values list. min_zoom = 1.f - delta * zoom_out_count; - - std::vector<double> zoom_values; + std::vector<float> zoom_values; for (int i = 0; i < kNumOfZoomFactors; i++) zoom_values.push_back(min_zoom + i * delta); + + // Make sure the inverse of the internal device scale factor is included in + // the list. This ensures that the users have a way to go to the native + // resolution and 1.0 effective device scale factor. + InsertInverseDsfIntoList(&zoom_values, 1.f / mode.device_scale_factor()); + + DCHECK_EQ(zoom_values.size(), static_cast<std::size_t>(kNumOfZoomFactors)); return zoom_values; } +void InsertInverseDsfIntoList(std::vector<float>* zoom_values, + float inverse_dsf) { + // We can never set the device scale factor of a display that is < 1. Hence + // the inverse can never be greater than 1. + DCHECK(inverse_dsf <= 1.f); + + // 1.0 is already in the list of |zoom_values|. We do not need to add it. + if (WithinEpsilon(inverse_dsf, 1.f)) + return; + + auto it = + std::lower_bound(zoom_values->begin(), zoom_values->end(), inverse_dsf); + + // We dont need to add it if the inverse dsf is already in the list. + if (WithinEpsilon(*it, inverse_dsf)) + return; + + if (it != zoom_values->begin()) { + // True if |inverse_dsf| is closer to |it| than it is to |it-1|. + const bool inverse_dsf_closer_to_it = + std::abs(*it - inverse_dsf) < std::abs(*(it - 1) - inverse_dsf); + + if (WithinEpsilon(*it, 1.f) || !inverse_dsf_closer_to_it) { + // This cases handles the following 2 situations: + // - |it| points to 1.0 zoom level which we cannot replace. + // - If |it-1| is closer to |inverse_dsf| than |it|. + *(it - 1) = inverse_dsf; + } else { + // |inverse_dsf| is closer to |it| than it is to |it - 1|. + *it = inverse_dsf; + } + } else { + if (WithinEpsilon(*it, 1.f)) { + // If the first element in the list is 1.0 then we cannot replace it. The + // |inverse_dsf| needs to be inserted before it and the last item in the + // list needs to be removed to keep the list size fixed. + zoom_values->insert(zoom_values->begin(), inverse_dsf); + zoom_values->pop_back(); + } else { + *it = inverse_dsf; + } + } +} + } // namespace display
diff --git a/ui/display/manager/display_util.h b/ui/display/manager/display_util.h index 3c5686e..97c7dc1 100644 --- a/ui/display/manager/display_util.h +++ b/ui/display/manager/display_util.h
@@ -37,9 +37,17 @@ bool IsPhysicalDisplayType(DisplayConnectionType type); // Returns a list of display zooms supported by the given |mode|. -std::vector<double> DISPLAY_MANAGER_EXPORT +std::vector<float> DISPLAY_MANAGER_EXPORT GetDisplayZoomFactors(const ManagedDisplayMode& mode); +// This function adds |inverse_dsf| to the vector of |zoom_values| by replacing +// the element it is closest to in the list. It also ensures that it never +// replaces the default zoom value of 1.0 from the list and that the size of the +// list never changes. +// Exposed for testing. +void DISPLAY_MANAGER_EXPORT +InsertInverseDsfIntoList(std::vector<float>* zoom_values, float inverse_dsf); + } // namespace display #endif // UI_DISPLAY_MANAGER_DISPLAY_UTIL_H_
diff --git a/ui/display/manager/display_utils_unittest.cc b/ui/display/manager/display_utils_unittest.cc index 446e916..5a83713 100644 --- a/ui/display/manager/display_utils_unittest.cc +++ b/ui/display/manager/display_utils_unittest.cc
@@ -18,13 +18,25 @@ constexpr std::size_t kNumOfZoomFactors = 9; constexpr int kDefaultMaxZoomWidth = 4096; constexpr int kDefaultMinZoomWidth = 640; + +// Returns the index of element |val| in list |list|. Returns the size of list +// if element is not found. +std::size_t GetIndexOfElement(const std::vector<float>& list, float val) { + return std::find(list.begin(), list.end(), val) - list.begin(); +} + +// Returns true if |a| and |b| are equal within the error limits. +bool WithinEpsilon(float a, float b) { + return std::abs(a - b) < std::numeric_limits<float>::epsilon(); +} + } // namespace using DisplayUtilTest = testing::Test; TEST_F(DisplayUtilTest, DisplayZooms) { // A vector of pairs where each pair is the resolution width correspoinding // to its list of available display zoom values. - const std::vector<std::pair<int, std::vector<double>>> expected_zoom_values{ + const std::vector<std::pair<int, std::vector<float>>> expected_zoom_values{ {480, {0.60f, 0.65f, 0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f}}, {640, {0.60f, 0.65f, 0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f}}, {720, {0.65f, 0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f, 1.05f}}, @@ -37,31 +49,32 @@ {1600, {0.55f, 0.70f, 0.85f, 1.f, 1.15f, 1.30f, 1.45f, 1.60f, 1.75f}}, {1920, {0.55f, 0.70f, 0.85f, 1.f, 1.15f, 1.30f, 1.45f, 1.60f, 1.75f}}, {2160, {0.60f, 0.80f, 1.f, 1.20f, 1.40f, 1.60f, 1.80f, 2.00f, 2.20f}}, + {2400, {0.75f, 1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f}}, {2560, {0.75f, 1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f}}, {2880, {0.75f, 1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f}}, - {3200, {1.f, 1.50f, 2.00f, 2.50f, 3.00f, 3.50f, 4.00f, 4.50f, 5.00f}}, - {3840, {1.f, 1.50f, 2.00f, 2.50f, 3.00f, 3.50f, 4.00f, 4.50f, 5.00f}}, - {4096, {1.f, 1.50f, 2.00f, 2.50f, 3.00f, 3.50f, 4.00f, 4.50f, 5.00f}}, - {5120, {1.f, 1.50f, 2.00f, 2.50f, 3.00f, 3.50f, 4.00f, 4.50f, 5.00f}}, - {7680, {1.f, 2.00f, 3.00f, 4.00f, 5.00f, 6.00f, 7.00f, 8.00f, 9.00f}}, - {8192, {1.f, 2.00f, 3.00f, 4.00f, 5.00f, 6.00f, 7.00f, 8.00f, 9.00f}}, + {3200, {1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f, 3.00f}}, + {3840, {1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f, 3.00f}}, + {4096, {1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f, 3.00f}}, + {5120, {1.f, 1.30f, 1.60f, 1.90f, 2.20f, 2.50f, 2.80f, 3.10f, 3.40f}}, + {7680, {1.f, 1.50f, 2.00f, 2.50f, 3.00f, 3.50f, 4.00f, 4.50f, 5.00f}}, + {8192, {1.f, 1.50f, 2.00f, 2.50f, 3.00f, 3.50f, 4.00f, 4.50f, 5.00f}}, }; for (const auto& pair : expected_zoom_values) { const int size = pair.first; ManagedDisplayMode mode(gfx::Size(size, size), 60, false, true, 1.f, 1.f); - const std::vector<double> zoom_values = GetDisplayZoomFactors(mode); - EXPECT_EQ(zoom_values.size(), kNumOfZoomFactors); + const std::vector<float> zoom_values = GetDisplayZoomFactors(mode); + EXPECT_FLOAT_EQ(zoom_values.size(), kNumOfZoomFactors); for (std::size_t j = 0; j < kNumOfZoomFactors; j++) { - EXPECT_NEAR(zoom_values[j], pair.second[j], 0.001); + EXPECT_FLOAT_EQ(zoom_values[j], pair.second[j]); - // Display pref stores the zoom value only upto 2 decimal places. This - // check ensures that the expected precision is only upto 2 decimal - // points. Before changing this line please ensure that you have updated + // Display pref stores the zoom value as double. This check ensures that + // the values dont lose precision. + // Before changing this line please ensure that you have updated // chromeos/display/display_prefs.cc - int percentage_value = std::round(zoom_values[j] * 100.f); - float fractional_value = static_cast<float>(percentage_value) / 100.f; - EXPECT_NEAR(zoom_values[j], fractional_value, 0.0001f); + double double_value = static_cast<double>(zoom_values[j]); + float float_value = static_cast<float>(double_value); + EXPECT_FLOAT_EQ(zoom_values[j], float_value); } const int effective_minimum_width_possible = size / zoom_values.back(); @@ -76,24 +89,50 @@ } TEST_F(DisplayUtilTest, DisplayZoomsWithInternalDsf) { - const std::vector<int> sizes = {1280, 1366, 1440, 1600, 1920, 2160, 2560, - 2880, 3200, 3840, 4096, 5120, 7680, 8192}; + const std::vector<int> sizes = {1280, 1366, 1440, 1600, 1920, + 2160, 2400, 2560, 2880, 3200, + 3840, 4096, 5120, 7680, 8192}; const std::vector<float> dsfs = {1.25f, 1.5f, 1.6f, 1.8f, 2.f, 2.25f}; for (float dsf : dsfs) { for (int size : sizes) { ManagedDisplayMode mode(gfx::Size(size, size), 60, false, true, 1.f, dsf); - const std::vector<double> zoom_values = GetDisplayZoomFactors(mode); + const std::vector<float> zoom_values = GetDisplayZoomFactors(mode); const int effective_size = std::round(static_cast<float>(size) / dsf); ManagedDisplayMode expected_mode( gfx::Size(effective_size, effective_size), 60, false, true, 1.f, 1.f); - const std::vector<double> expected_zoom_values = + const std::vector<float> expected_zoom_values = GetDisplayZoomFactors(expected_mode); EXPECT_EQ(zoom_values.size(), kNumOfZoomFactors); - for (std::size_t i = 0; i < kNumOfZoomFactors; i++) - EXPECT_NEAR(zoom_values[i], expected_zoom_values[i], 0.001); + + // There should be exactly 1 entry for the inverse dsf in the list. + const float inverse_dsf = 1.f / dsf; + const std::size_t count_of_inverse_dsf = + std::count_if(zoom_values.begin(), zoom_values.end(), + [inverse_dsf](float zoom_value) -> bool { + return WithinEpsilon(zoom_value, inverse_dsf); + }); + EXPECT_EQ(count_of_inverse_dsf, 1UL); + + // Check all values in |zoom_values| are present in |expected_zoom_values| + // except for |inverse_dsf|. + auto it = expected_zoom_values.begin(); + for (const auto& zoom_value : zoom_values) { + // |inverse_dsf| is not expected to be in the expected list since it was + // added later on. + if (WithinEpsilon(zoom_value, inverse_dsf)) + continue; + + // Check if |zoom_value| is present in |expected_zoom_values|. + it = std::find_if(it, expected_zoom_values.end(), + [&zoom_value](float expected_zoom) -> bool { + return WithinEpsilon(zoom_value, expected_zoom); + }); + EXPECT_TRUE(it != expected_zoom_values.end()) + << zoom_value << " not found"; + } const int effective_minimum_width_possible = size / zoom_values.back(); const int effective_maximum_width_possible = size * zoom_values.front(); @@ -107,5 +146,52 @@ } } +TEST_F(DisplayUtilTest, InsertInverseDsfIntoList) { + std::vector<float> list; + float inverse_dsf; + + list = {0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 0.95f, 1.f}; + inverse_dsf = 0.6f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 0UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); + + list = {0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 0.95f, 1.f, 1.05f}; + inverse_dsf = 0.6f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 0UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); + + list = {0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f, 1.4f}; + inverse_dsf = 0.67f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 1UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); + + list = {0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f, 1.4f}; + inverse_dsf = 0.9f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 3UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); + + list = {0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f, 1.4f}; + inverse_dsf = 0.99f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 3UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); + + list = {0.8f, 1.f, 1.2f, 1.4f, 1.6f, 1.8f, 2.f, 2.2f, 2.4f}; + inverse_dsf = 0.99f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 0UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); + + list = {1.f, 1.25f, 1.5f, 1.75f, 2.f, 2.25f, 2.5f, 2.75f, 3.f}; + inverse_dsf = 0.85f; + InsertInverseDsfIntoList(&list, inverse_dsf); + EXPECT_EQ(GetIndexOfElement(list, inverse_dsf), 0UL); + EXPECT_EQ(list.size(), kNumOfZoomFactors); +} + } // namespace test } // namespace display
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 7560d1c..965ef35 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -690,6 +690,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin( const WebGestureEvent& gesture_event) { + TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollBegin"); if (gesture_scroll_on_impl_thread_) CancelCurrentFling(); @@ -725,9 +726,7 @@ in_inertial_scrolling_ = false; switch (scroll_status.thread) { case cc::InputHandler::SCROLL_ON_IMPL_THREAD: - TRACE_EVENT_INSTANT0("input", - "InputHandlerProxy::handle_input gesture scroll", - TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_INSTANT0("input", "Handle On Impl", TRACE_EVENT_SCOPE_THREAD); gesture_scroll_on_impl_thread_ = true; if (input_handler_->IsCurrentlyScrollingViewport()) client_->DidStartScrollingViewport(); @@ -739,9 +738,11 @@ break; case cc::InputHandler::SCROLL_UNKNOWN: case cc::InputHandler::SCROLL_ON_MAIN_THREAD: + TRACE_EVENT_INSTANT0("input", "Handle On Main", TRACE_EVENT_SCOPE_THREAD); result = DID_NOT_HANDLE; break; case cc::InputHandler::SCROLL_IGNORED: + TRACE_EVENT_INSTANT0("input", "Ignore Scroll", TRACE_EVENT_SCOPE_THREAD); scroll_sequence_ignored_ = true; result = DROP_EVENT; break; @@ -762,12 +763,14 @@ gfx::Vector2dF scroll_delta(-gesture_event.data.scroll_update.delta_x, -gesture_event.data.scroll_update.delta_y); - TRACE_EVENT_INSTANT2("input", "InputHandlerProxy::HandleGestureScrollUpdate", - TRACE_EVENT_SCOPE_THREAD, "dx", scroll_delta.x(), "dy", - scroll_delta.y()); + TRACE_EVENT2("input", "InputHandlerProxy::HandleGestureScrollUpdate", "dx", + scroll_delta.x(), "dy", scroll_delta.y()); - if (scroll_sequence_ignored_) + if (scroll_sequence_ignored_) { + TRACE_EVENT_INSTANT0("input", "Scroll Sequence Ignored", + TRACE_EVENT_SCOPE_THREAD); return DROP_EVENT; + } if (!gesture_scroll_on_impl_thread_ && !gesture_pinch_on_impl_thread_) return DID_NOT_HANDLE; @@ -788,10 +791,14 @@ case cc::InputHandler::SCROLL_ON_IMPL_THREAD: return DID_HANDLE; case cc::InputHandler::SCROLL_IGNORED: + TRACE_EVENT_INSTANT0("input", "Scroll Ignored", + TRACE_EVENT_SCOPE_THREAD); return DROP_EVENT; case cc::InputHandler::SCROLL_ON_MAIN_THREAD: case cc::InputHandler::SCROLL_UNKNOWN: if (input_handler_->ScrollingShouldSwitchtoMainThread()) { + TRACE_EVENT_INSTANT0("input", "Move Scroll To Main Thread", + TRACE_EVENT_SCOPE_THREAD); gesture_scroll_on_impl_thread_ = false; client_->GenerateScrollBeginAndSendToMainThread(gesture_event); } @@ -832,6 +839,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollEnd( const WebGestureEvent& gesture_event) { + TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollEnd"); #ifndef NDEBUG DCHECK(expect_scroll_update_end_); expect_scroll_update_end_ = false;
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index c7254cc..6119aeb 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -492,20 +492,26 @@ event) { // If there is no focused window, then create a new one opened on the // mounted FSP volume. - this.findFocusedWindow_().then(function(key) { - if (key === null && - event.eventType === 'mount' && - (event.status === 'success' || - event.status === 'error_path_already_mounted') && - event.volumeMetadata.mountContext === 'user' && - event.volumeMetadata.volumeType === - VolumeManagerCommon.VolumeType.PROVIDED && - event.volumeMetadata.source === VolumeManagerCommon.Source.FILE) { - this.navigateToVolumeWhenReady_(event.volumeMetadata.volumeId); - } - }.bind(this)).catch(function(error) { - console.error(error.stack || error); - }); + this.findFocusedWindow_() + .then(function(key) { + let statusOK = event.status === 'success' || + event.status === 'error_path_already_mounted'; + let volumeTypeOK = + event.volumeMetadata.source === VolumeManagerCommon.Source.FILE || + VolumeManagerCommon.getProvidedFileSystemIdFromVolumeId( + event.volumeId) === + VolumeManagerCommon.ProvidedFileSystem.CROSTINI; + if (key === null && event.eventType === 'mount' && statusOK && + event.volumeMetadata.mountContext === 'user' && + event.volumeMetadata.volumeType === + VolumeManagerCommon.VolumeType.PROVIDED && + volumeTypeOK) { + this.navigateToVolumeWhenReady_(event.volumeMetadata.volumeId); + } + }.bind(this)) + .catch(function(error) { + console.error(error.stack || error); + }); }; /**
diff --git a/ui/file_manager/file_manager/common/js/volume_manager_common.js b/ui/file_manager/file_manager/common/js/volume_manager_common.js index ad8df50..1a0c487 100644 --- a/ui/file_manager/file_manager/common/js/volume_manager_common.js +++ b/ui/file_manager/file_manager/common/js/volume_manager_common.js
@@ -102,6 +102,9 @@ // 'Add new services' menu item. ADD_NEW_SERVICES_MENU: 'add_new_services_menu', + + // Fake root for SFTP Mount such as Linux Files. + SFTP_MOUNT: 'sftp_mount', }; Object.freeze(VolumeManagerCommon.RootType); @@ -131,6 +134,7 @@ VolumeManagerCommon.RootType.RECENT, VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT, VolumeManagerCommon.RootType.ADD_NEW_SERVICES_MENU, + VolumeManagerCommon.RootType.SFTP_MOUNT, ]; console.assert( Object.keys(VolumeManagerCommon.RootType).length === @@ -321,6 +325,26 @@ volumeId.split(':', 2)[1]); }; + +/** + * List of known FSP-provided fileSystemId values. + * + * @enum {string} + * @const + */ +VolumeManagerCommon.ProvidedFileSystem = { + CROSTINI: 'crostini', +}; + +/** + * Obtains fileSystemId from volumeId of FSP-provided mount. + * @param {string} volumeId Volume ID. + * @return {string|undefined} + */ +VolumeManagerCommon.getProvidedFileSystemIdFromVolumeId = function(volumeId) { + return volumeId ? volumeId.split(':', 3)[2] : undefined; +}; + /** * Fake entries for virtual folders which hold Google Drive offline files, * Google Drive "Shared with me" files, and mixed Recent files.
diff --git a/ui/file_manager/file_manager/foreground/css/file_types.css b/ui/file_manager/file_manager/foreground/css/file_types.css index 28ddd0d..fe568fe 100644 --- a/ui/file_manager/file_manager/foreground/css/file_types.css +++ b/ui/file_manager/file_manager/foreground/css/file_types.css
@@ -234,7 +234,8 @@ url(../images/volumes/2x/service_drive_active.png) 2x); } -[volume-type-icon='team_drives_grand_root'],[volume-type-icon='team_drive'] { +[volume-type-icon='team_drives_grand_root'], +[volume-type-icon='team_drive'] { background-image: -webkit-image-set( url(../images/volumes/team_drive.png) 1x, url(../images/volumes/2x/team_drive.png) 2x); @@ -416,3 +417,20 @@ url(../images/volumes/recent_active.png) 1x, url(../images/volumes/2x/recent_active.png) 2x); } + +[sftp-mount-icon='linux-files'], +[volume-subtype='crostini'] { + /* Need !important to override inline style applied to provided volumes. */ + background-image: -webkit-image-set( + url(../images/volumes/linux_files.png) 1x, + url(../images/volumes/2x/linux_files.png) 2x) !important; +} + +.tree-row[selected] [sftp-mount-icon='linux-files'], +.tree-row[selected] [volume-subtype='crostini'] { + /* Need !important to override inline style applied to provided volumes. */ + background-image: -webkit-image-set( + url(../images/volumes/linux_files_active.png) 1x, + url(../images/volumes/2x/linux_files_active.png) 2x) !important; +} +
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/2x/linux_files.png b/ui/file_manager/file_manager/foreground/images/volumes/2x/linux_files.png new file mode 100644 index 0000000..020c786 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/volumes/2x/linux_files.png Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/2x/linux_files_active.png b/ui/file_manager/file_manager/foreground/images/volumes/2x/linux_files_active.png new file mode 100644 index 0000000..ed90b384 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/volumes/2x/linux_files_active.png Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/linux_files.png b/ui/file_manager/file_manager/foreground/images/volumes/linux_files.png new file mode 100644 index 0000000..c4a76e8 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/volumes/linux_files.png Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/linux_files_active.png b/ui/file_manager/file_manager/foreground/images/volumes/linux_files_active.png new file mode 100644 index 0000000..cf67c13 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/volumes/linux_files_active.png Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model.js b/ui/file_manager/file_manager/foreground/js/actions_model.js index 54e0cb3..064560e 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model.js +++ b/ui/file_manager/file_manager/foreground/js/actions_model.js
@@ -71,13 +71,20 @@ * @param {!Array<!Entry>} entries * @param {!ActionModelUI} ui * @param {!VolumeManagerWrapper} volumeManager - * @return {DriveShareAction} + * @return {DriveShareAction|DriveManageAction} */ DriveShareAction.create = function(entries, volumeManager, ui) { if (entries.length !== 1) return null; - return new DriveShareAction(entries[0], volumeManager, ui); + // The share URL for Team Drives currently does not support embedding. For + // Team Drives entries, instead point the user to the 'Manage' action. + var entry = entries[0]; + if (util.isTeamDriveEntry(entry)) { + return new DriveManageAction(entry, volumeManager, ui); + } + + return new DriveShareAction(entry, volumeManager, ui); }; /**
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js index 8ef31746..a058ec0 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
@@ -304,7 +304,8 @@ // "share" action is enabled for Team Drive directories. var shareAction = actions[ActionsModel.CommonActionId.SHARE]; assertTrue(!!shareAction); - assertTrue(shareAction.canExecute()); + // TODO(sashab): Re-enable when 'Manage' works for directories. + assertFalse(shareAction.canExecute()); // "manage in drive" action is disabled for Team Drive directories. var manageAction =
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model.js b/ui/file_manager/file_manager/foreground/js/directory_model.js index 0d4eb71..86629d0 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model.js
@@ -1164,13 +1164,15 @@ }.bind(this)); } - // If a new file backed provided volume is mounted, then redirect to it in - // the focused window. Note, that this is a temporary solution for - // crbug.com/427776. - if (window.isFocused() && - event.added.length === 1 && + // If a new file backed provided volume, or crostini is mounted, + // then redirect to it in the focused window. + // Note, that this is a temporary solution for https://crbug.com/427776. + if (window.isFocused() && event.added.length === 1 && event.added[0].volumeType === VolumeManagerCommon.VolumeType.PROVIDED && - event.added[0].source === VolumeManagerCommon.Source.FILE) { + (event.added[0].source === VolumeManagerCommon.Source.FILE || + VolumeManagerCommon.getProvidedFileSystemIdFromVolumeId( + event.added[0].volumeId) === + VolumeManagerCommon.ProvidedFileSystem.CROSTINI)) { event.added[0].resolveDisplayRoot().then(function(displayRoot) { // Resolving a display root on FSP volumes is instant, despite the // asynchronous call.
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model.js index d03836b9..6ebf09f 100644 --- a/ui/file_manager/file_manager/foreground/js/navigation_list_model.js +++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
@@ -10,6 +10,7 @@ VOLUME: 'volume', MENU: 'menu', RECENT: 'recent', + SFTP_MOUNT: 'sftp_mount', }; /** @@ -131,6 +132,38 @@ }; /** + * Item of NavigationListModel for an SFTP Mount as used by Linux files. + * + * @param {string} label Label on the item. + * @param {!FakeEntry} entry Fake entry for the SFTP Mount root folder. + * @param {string} icon CSS icon. + * @constructor + * @extends {NavigationModelItem} + * @struct + */ +function NavigationModelSFTPMountItem(label, entry, icon) { + NavigationModelItem.call(this, label, NavigationModelItemType.SFTP_MOUNT); + this.entry_ = entry; + this.icon_ = icon; +} + +NavigationModelSFTPMountItem.prototype = /** @struct */ { + __proto__: NavigationModelItem.prototype, + get entry() { + return this.entry_; + }, + get icon() { + return this.icon_; + }, + /** + * Start crostini container and mount it. + */ + mount: function() { + chrome.fileManagerPrivate.mountCrostiniContainer(); + }, +}; + +/** * A navigation list model. This model combines multiple models. * @param {!VolumeManagerWrapper} volumeManager VolumeManagerWrapper instance. * @param {(!cr.ui.ArrayDataModel|!FolderShortcutsDataModel)} shortcutListModel @@ -163,12 +196,19 @@ this.recentModelItem_ = recentModelItem; /** + * Root folder for crostini Linux Files. + * This field will be set asynchronously after calling + * chrome.fileManagerPrivate.isCrostiniEnabled. + * @private {NavigationModelSFTPMountItem} + */ + this.linuxFilesItem_ = null; + + /** * @private {NavigationModelMenuItem} * @const */ this.addNewServicesItem_ = addNewServicesItem; - /** * All root navigation items in display order. * @private {!Array<!NavigationModelItem>} @@ -210,7 +250,25 @@ this.shortcutList_.push(entryToModelItem(shortcutEntry)); } - // Reorder volumes, shortcuts, and optional items. + // Check if crostini is enabled to create linuxFilesItem_. + chrome.fileManagerPrivate.isCrostiniEnabled((enabled) => { + if (!enabled) + return; + + this.linuxFilesItem_ = new NavigationModelSFTPMountItem( + str('LINUX_FILES_ROOT_LABEL'), { + isDirectory: true, + rootType: VolumeManagerCommon.RootType.SFTP_MOUNT, + toURL: function() { + return 'fake-entry://linux-files'; + }, + }, + 'linux-files'); + // Reorder items to ensure Linux Files is shown. + this.reorderNavigationItems_(); + }); + + // Reorder volumes, shortcuts, and optional items for initial display. this.reorderNavigationItems_(); // Generates a combined 'permuted' event from an event of either volumeList or @@ -333,14 +391,30 @@ * 1. Volumes. * 2. If Downloads exists, then immediately after Downloads should be: * 2a. Recent if it exists. + * 2b. Linux Files if it exists and is not mounted. + * When mounted, it will be located in Volumes at this position. * 3. Shortcuts. * 4. Add new services if it exists. * @private */ NavigationListModel.prototype.reorderNavigationItems_ = function() { + // Check if Linux files already mounted. + let linuxFilesMounted = false; + for (let i = 0; i < this.volumeList_.length; i++) { + if (VolumeManagerCommon.getProvidedFileSystemIdFromVolumeId( + this.volumeList_[i].volumeInfo.volumeId) === + VolumeManagerCommon.ProvidedFileSystem.CROSTINI) { + linuxFilesMounted = true; + break; + } + } + // Items as per required order. this.navigationItems_ = this.volumeList_.slice(); var downloadsVolumeIndex = this.findDownloadsVolumeIndex_(); + if (this.linuxFilesItem_ && !linuxFilesMounted && downloadsVolumeIndex >= 0) + this.navigationItems_.splice( + downloadsVolumeIndex + 1, 0, this.linuxFilesItem_); if (this.recentModelItem_ && downloadsVolumeIndex >= 0) this.navigationItems_.splice( downloadsVolumeIndex + 1, 0, this.recentModelItem_);
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js index de5cd52..9ec752ce 100644 --- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -11,7 +11,8 @@ // Set up string assets. loadTimeData.data = { DRIVE_DIRECTORY_LABEL: 'My Drive', - DOWNLOADS_DIRECTORY_LABEL: 'Downloads' + DOWNLOADS_DIRECTORY_LABEL: 'Downloads', + LINUX_FILES_ROOT_LABEL: 'Linux Files', }; function setUp() { @@ -19,6 +20,15 @@ // Override VolumeInfo.prototype.resolveDisplayRoot. VolumeInfoImpl.prototype.resolveDisplayRoot = function() {}; + // Mock chrome.fileManagerPrivate.isCrostiniEnabled. + // TODO(crbug.com/834103): Add integration test for Crostini. + chrome.fileManagerPrivate = { + crostiniEnabled: false, + isCrostiniEnabled: function(callback) { + callback(this.crostiniEnabled); + }, + }; + drive = new MockFileSystem('drive'); hoge = new MockFileSystem('removable:hoge'); } @@ -33,22 +43,24 @@ } }; var recentItem = new NavigationModelRecentItem('recent-label', fakeEntry); + chrome.fileManagerPrivate.crostiniEnabled = true; var addNewServicesItem = new NavigationModelMenuItem( 'menu-button-label', '#add-new-services', 'menu-button-icon'); var model = new NavigationListModel( volumeManager, shortcutListModel, recentItem, addNewServicesItem); - assertEquals(5, model.length); + assertEquals(6, model.length); assertEquals('drive', model.item(0).volumeInfo.volumeId); assertEquals('downloads', model.item(1).volumeInfo.volumeId); assertEquals('fake-entry://recent', model.item(2).entry.toURL()); - assertEquals('/root/shortcut', model.item(3).entry.fullPath); - assertEquals('menu-button-label', model.item(4).label); - assertEquals('#add-new-services', model.item(4).menu); - assertEquals('menu-button-icon', model.item(4).icon); + assertEquals('fake-entry://linux-files', model.item(3).entry.toURL()); + assertEquals('/root/shortcut', model.item(4).entry.fullPath); + assertEquals('menu-button-label', model.item(5).label); + assertEquals('#add-new-services', model.item(5).menu); + assertEquals('menu-button-icon', model.item(5).icon); } -function testNoRecent() { +function testNoRecentOrLinuxFiles() { var volumeManager = new MockVolumeManagerWrapper(); var shortcutListModel = new MockFolderShortcutDataModel( [new MockFileEntry(drive, '/root/shortcut')]);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index 1d1a00b6..d660c78 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -700,6 +700,13 @@ 'volume-subtype', VolumeManagerCommon.getMediaViewRootTypeFromVolumeId( volumeInfo.volumeId)); + } else if ( + volumeInfo.volumeType === VolumeManagerCommon.VolumeType.PROVIDED) { + icon.setAttribute( + 'volume-subtype', + VolumeManagerCommon.getProvidedFileSystemIdFromVolumeId( + volumeInfo.volumeId) || + ''); } else { icon.setAttribute('volume-subtype', volumeInfo.deviceType || ''); } @@ -1184,6 +1191,54 @@ this.parentTree_.directoryModel.activateDirectoryEntry(this.entry); }; +//////////////////////////////////////////////////////////////////////////////// +// SFTPMountItem + +/** + * A TreeItem which represents a directory to be mounted using SFTP. + * + * @param {!NavigationModelSFTPMountItem} modelItem + * @param {!DirectoryTree} tree Current tree, which contains this item. + * @extends {cr.ui.TreeItem} + * @constructor + */ +function SFTPMountItem(modelItem, tree) { + var item = new cr.ui.TreeItem(); + item.__proto__ = SFTPMountItem.prototype; + + item.parentTree_ = tree; + item.modelItem_ = modelItem; + item.innerHTML = TREE_ITEM_INNER_HTML; + item.label = modelItem.label; + + var icon = queryRequiredElement('.icon', item); + icon.classList.add('item-icon'); + icon.setAttribute('sftp-mount-icon', item.modelItem_.icon); + + return item; +} + +SFTPMountItem.prototype = { + __proto__: cr.ui.TreeItem.prototype, + get entry() { + return null; + }, + get modelItem() { + return this.modelItem_; + }, + get labelElement() { + return this.firstElementChild.querySelector('.label'); + } +}; + +/** + * @override + */ +SFTPMountItem.prototype.handleClick = function(e) { + this.selected = true; + this.modelItem_.mount(); +}; + //////////////////////////////////////////////////////////////////////////////// // DirectoryTree @@ -1373,6 +1428,9 @@ case NavigationModelItemType.RECENT: this.addAt(new RecentItem(modelItem, this), itemIndex); break; + case NavigationModelItemType.SFTP_MOUNT: + this.addAt(new SFTPMountItem(modelItem, this), itemIndex); + break; } } itemIndex++;
diff --git a/ui/file_manager/file_manager/test/js/strings.js b/ui/file_manager/file_manager/test/js/strings.js index db3f6e59..76acb26 100644 --- a/ui/file_manager/file_manager/test/js/strings.js +++ b/ui/file_manager/file_manager/test/js/strings.js
@@ -53,6 +53,7 @@ 'utm_campaign=gsg', IMAGE_FILE_TYPE: '$1 image', INSTALL_NEW_EXTENSION_LABEL: 'Install new from the webstore', + LINUX_FILES_ROOT_LABEL: 'Linux Files', MANY_ENTRIES_SELECTED: '$1 items selected', MANY_FILES_SELECTED: '$1 files selected', METADATA_BOX_ALBUM_TITLE: 'Album', @@ -68,6 +69,8 @@ OPEN_LABEL: 'Open', PLAIN_TEXT_FILE_TYPE: 'Plain text', PREPARING_LABEL: 'Preparing', + SEE_MENU_FOR_ACTIONS: 'More options available on the action bar. ' + + 'Press Alt + A to focus the action bar.', SIZE_COLUMN_LABEL: 'Size', SPACE_AVAILABLE: '$1 available', STATUS_COLUMN_LABEL: 'Status',
diff --git a/ui/file_manager/gallery/gallery.html b/ui/file_manager/gallery/gallery.html index 44ee9c54..9f85d50 100644 --- a/ui/file_manager/gallery/gallery.html +++ b/ui/file_manager/gallery/gallery.html
@@ -15,8 +15,8 @@ <script src="chrome://resources/js/polymer_config.js"></script> <script src="chrome://resources/js/util.js"></script> + <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> - <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html"> @@ -28,16 +28,18 @@ <script src="js/gallery_scripts.js"></script> <style is="custom-style"> - paper-checkbox { - --paper-checkbox-checked-color: white; - --paper-checkbox-checked-ink-color: white; - --paper-checkbox-checkmark-color: black; - --paper-checkbox-ink-size: 38px; - --paper-checkbox-label-color: white; - --paper-checkbox-label-spacing: 6px; - --paper-checkbox-size: 14px; - --paper-checkbox-unchecked-color: white; - --paper-checkbox-unchecked-ink-color: white; + cr-checkbox { + --cr-checkbox-checked-box-color: white; + --cr-checkbox-label-container: { + -webkit-padding-start: 6px; + color: white; + }; + --cr-checkbox-mark-color: black; + --cr-checkbox-ripple-checked-color: white; + --cr-checkbox-ripple-size: 38px; + --cr-checkbox-ripple-unchecked-color: white; + --cr-checkbox-size: 14px; + --cr-checkbox-unchecked-box-color: white; } paper-input-container { --paper-input-container-color: rgba(255, 255, 255, 0.2); @@ -156,9 +158,9 @@ </div> <div class="edit-mode-toolbar"> <div class="options"> - <paper-checkbox class="overwrite-original" + <cr-checkbox class="overwrite-original" i18n-content="GALLERY_OVERWRITE_ORIGINAL"> - </paper-checkbox> + </cr-checkbox> <div class="saved" i18n-content="GALLERY_SAVED" hidden></div> </div> <div class="edit-bar-spacer"></div>
diff --git a/ui/file_manager/gallery/js/BUILD.gn b/ui/file_manager/gallery/js/BUILD.gn index 03bffec..23fa7a7 100644 --- a/ui/file_manager/gallery/js/BUILD.gn +++ b/ui/file_manager/gallery/js/BUILD.gn
@@ -139,7 +139,6 @@ "image_editor:image_util", "image_editor:image_view", "image_editor:viewport", - "//third_party/polymer/v1_0/components-chromium/paper-checkbox:paper-checkbox-extracted", "//third_party/polymer/v1_0/components-chromium/paper-progress:paper-progress-extracted", ] externs_list = [
diff --git a/ui/file_manager/gallery/js/slide_mode.js b/ui/file_manager/gallery/js/slide_mode.js index 36c93b8..4fdb28d 100644 --- a/ui/file_manager/gallery/js/slide_mode.js +++ b/ui/file_manager/gallery/js/slide_mode.js
@@ -259,10 +259,10 @@ this.savedLabel_ = queryRequiredElement('.saved', this.options_); /** - * @private {!PaperCheckboxElement} + * @private {!Element} * @const */ - this.overwriteOriginalCheckbox_ = /** @type {!PaperCheckboxElement} */ + this.overwriteOriginalCheckbox_ = /** @type {!Element} */ (queryRequiredElement('.overwrite-original', this.options_)); this.overwriteOriginalCheckbox_.addEventListener('change', this.onOverwriteOriginalCheckboxChanged_.bind(this));
diff --git a/ui/file_manager/integration_tests/audio_player/click_control_buttons.js b/ui/file_manager/integration_tests/audio_player/click_control_buttons.js index d733754..8582c7e 100644 --- a/ui/file_manager/integration_tests/audio_player/click_control_buttons.js +++ b/ui/file_manager/integration_tests/audio_player/click_control_buttons.js
@@ -5,7 +5,8 @@ 'use strict'; /** - * Confirms that the play button toggles play state and it's labels. + * Confirms that clicking the play button changes the audio player state and + * updates the play button's label. * @return {Promise} Promise to be fulfilled with on success. */ testcase.togglePlayState = function() { @@ -14,29 +15,43 @@ return openAudio.then(function(args) { appId = args[0]; }).then(function() { - // Audio player should start playing automatically. + // Audio player should start playing automatically, return remoteCallAudioPlayer.waitForElement( appId, 'audio-player[playing]'); }).then(function() { - // While playing, the play/pause button should have 'Pause' label. + // .. and the play button label should be 'Pause'. return remoteCallAudioPlayer.waitForElement( appId, ['#play[aria-label="Pause"]']); }).then(function() { - // Clicking the pause button should change the playback state to pause. + // Clicking on the play button should return remoteCallAudioPlayer.callRemoteTestUtil( 'fakeMouseClick', appId, ['#play']); }).then(function() { + // ... change the audio playback state to pause, return remoteCallAudioPlayer.waitForElement( appId, 'audio-player:not([playing])'); }).then(function() { - // ... and the play/pause button should have 'Play' label. + // ... and the play button label should be 'Play'. return remoteCallAudioPlayer.waitForElement( appId, ['#play[aria-label="Play"]']); + }).then(function() { + // Clicking on the play button again should + return remoteCallAudioPlayer.callRemoteTestUtil( + 'fakeMouseClick', appId, ['#play']); + }).then(function() { + // ... change the audio playback state to playing, + return remoteCallAudioPlayer.waitForElement( + appId, 'audio-player[playing]'); + }).then(function() { + // ... and the play button label should be 'Pause'. + return remoteCallAudioPlayer.waitForElement( + appId, ['#play[aria-label="Pause"]']); }); }; /** - * Confirms that the default volume is 50 and volume button mutes/unmutes audio. + * Confirms that the AudioPlayer default volume is 50 and that clicking the + * volume button mutes / unmutes the volume label. * @return {Promise} Promise to be fulfilled with on success. */ testcase.changeVolumeLevel = function() { @@ -45,11 +60,11 @@ return openAudio.then(function(args) { appId = args[0]; }).then(function() { - // The default volume level should be 50. + // The Audio Player default volume level should be 50. return remoteCallAudioPlayer.waitForElement( appId, ['control-panel[volume="50"]']); }).then(function() { - // Clicking volume button should mute the player. + // Clicking the volume button should mute the player. return remoteCallAudioPlayer.callRemoteTestUtil( 'fakeMouseClick', appId, ['#volumeButton']); }).then(function() { @@ -60,7 +75,7 @@ appId, ['#volumeButton[aria-label="Unmute"]']) ]); }).then(function() { - // Clicking volume button again should restore volume. + // Clicking it again should unmute and restore the volume. return remoteCallAudioPlayer.callRemoteTestUtil( 'fakeMouseClick', appId, ['#volumeButton']); }).then(function() {
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index b59886f..2837607 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -408,6 +408,9 @@ "skia_color_space_util.cc", "skia_color_space_util.h", ] + deps = [ + "//third_party/skia/third_party/skcms", + ] public_deps = [ "//base", "//skia", @@ -419,9 +422,7 @@ ] } if (use_x11) { - deps = [ - "//ui/gfx/x", - ] + deps += [ "//ui/gfx/x" ] configs += [ "//build/config/linux:x11" ] } defines = [ "COLOR_SPACE_IMPLEMENTATION" ]
diff --git a/ui/gfx/color_palette.h b/ui/gfx/color_palette.h index 4a7e3db..13fcf4c 100644 --- a/ui/gfx/color_palette.h +++ b/ui/gfx/color_palette.h
@@ -14,7 +14,7 @@ constexpr SkColor kPlaceholderColor = SK_ColorRED; // The number refers to the shade of darkness. Each color in the MD -// palette ranges from 50-900. +// palette ranges from 050-900. constexpr SkColor kGoogleBlue300 = SkColorSetRGB(0x8A, 0xB4, 0xF8); constexpr SkColor kGoogleBlue500 = SkColorSetRGB(0x42, 0x85, 0xF4); constexpr SkColor kGoogleBlue600 = SkColorSetRGB(0x1A, 0x73, 0xE8); @@ -34,7 +34,7 @@ constexpr SkColor kGoogleYellow300 = SkColorSetRGB(0xFD, 0xD6, 0x63); constexpr SkColor kGoogleYellow700 = SkColorSetRGB(0xF2, 0x99, 0x00); constexpr SkColor kGoogleYellow900 = SkColorSetRGB(0xE3, 0x74, 0x00); -constexpr SkColor kGoogleGrey50 = SkColorSetRGB(0xF8, 0xF9, 0xFA); +constexpr SkColor kGoogleGrey050 = SkColorSetRGB(0xF8, 0xF9, 0xFA); constexpr SkColor kGoogleGrey100 = SkColorSetRGB(0xF1, 0xF3, 0xF4); constexpr SkColor kGoogleGrey200 = SkColorSetRGB(0xE8, 0xEA, 0xED); constexpr SkColor kGoogleGrey300 = SkColorSetRGB(0xDA, 0xDC, 0xE0);
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc index a35cbd94..ab0668c 100644 --- a/ui/gfx/color_space.cc +++ b/ui/gfx/color_space.cc
@@ -44,6 +44,9 @@ } // namespace +// static +int ColorSpace::kInvalidId = -1; + ColorSpace::ColorSpace() {} ColorSpace::ColorSpace(PrimaryID primaries,
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h index 64bd12b..14dc5c73 100644 --- a/ui/gfx/color_space.h +++ b/ui/gfx/color_space.h
@@ -158,6 +158,7 @@ // Generates a process global unique ID that can be used to key a color space. static int GetNextId(); + static int kInvalidId; bool operator==(const ColorSpace& other) const; bool operator!=(const ColorSpace& other) const;
diff --git a/ui/gfx/color_space_unittest.cc b/ui/gfx/color_space_unittest.cc index c4a95578..fc59877 100644 --- a/ui/gfx/color_space_unittest.cc +++ b/ui/gfx/color_space_unittest.cc
@@ -81,165 +81,6 @@ } } -typedef std::tuple<ColorSpace::TransferID, size_t> TableTestData; - -class ColorSpaceTableTest : public testing::TestWithParam<TableTestData> {}; - -TEST_P(ColorSpaceTableTest, ApproximateTransferFn) { - ColorSpace::TransferID transfer_id = std::get<0>(GetParam()); - const size_t table_size = std::get<1>(GetParam()); - - gfx::ColorSpace color_space(ColorSpace::PrimaryID::BT709, transfer_id); - SkColorSpaceTransferFn tr_fn; - SkColorSpaceTransferFn tr_fn_inv; - bool result = color_space.GetTransferFunction(&tr_fn); - CHECK(result); - color_space.GetInverseTransferFunction(&tr_fn_inv); - - std::vector<float> x; - std::vector<float> t; - for (float v = 0; v <= 1.f; v += 1.f / table_size) { - x.push_back(v); - t.push_back(SkTransferFnEval(tr_fn, v)); - } - - SkColorSpaceTransferFn fn_approx; - bool converged = - SkApproximateTransferFn(x.data(), t.data(), x.size(), &fn_approx); - EXPECT_TRUE(converged); - - for (size_t i = 0; i < x.size(); ++i) { - float fn_approx_of_x = SkTransferFnEval(fn_approx, x[i]); - EXPECT_NEAR(t[i], fn_approx_of_x, 3.f / 256.f); - if (std::abs(t[i] - fn_approx_of_x) > 3.f / 256.f) - break; - } -} - -ColorSpace::TransferID all_transfers[] = { - ColorSpace::TransferID::GAMMA22, ColorSpace::TransferID::GAMMA24, - ColorSpace::TransferID::GAMMA28, ColorSpace::TransferID::BT709, - ColorSpace::TransferID::SMPTE240M, ColorSpace::TransferID::IEC61966_2_1, - ColorSpace::TransferID::LINEAR}; - -size_t all_table_sizes[] = {512, 256, 128, 64, 16, 11, 8, 7, 6, 5, 4}; - -INSTANTIATE_TEST_CASE_P(A, - ColorSpaceTableTest, - testing::Combine(testing::ValuesIn(all_transfers), - testing::ValuesIn(all_table_sizes))); - -TEST(ColorSpace, ApproximateTransferFnClamped) { - // These data represent a transfer function that is clamped at the high - // end of its domain. It comes from the color profile attached to - // https://crbug.com/750459 - float t[] = { - 0.000000f, 0.000305f, 0.000610f, 0.000916f, 0.001221f, 0.001511f, - 0.001816f, 0.002121f, 0.002426f, 0.002731f, 0.003037f, 0.003601f, - 0.003937f, 0.004303f, 0.004685f, 0.005081f, 0.005509f, 0.005951f, - 0.006409f, 0.006882f, 0.007385f, 0.007904f, 0.008438f, 0.009003f, - 0.009583f, 0.010193f, 0.010819f, 0.011460f, 0.012131f, 0.012818f, - 0.013535f, 0.014267f, 0.015030f, 0.015808f, 0.016617f, 0.017456f, - 0.018296f, 0.019181f, 0.020081f, 0.021012f, 0.021958f, 0.022934f, - 0.023926f, 0.024949f, 0.026001f, 0.027070f, 0.028168f, 0.029297f, - 0.030442f, 0.031617f, 0.032822f, 0.034058f, 0.035309f, 0.036591f, - 0.037903f, 0.039231f, 0.040604f, 0.041993f, 0.043412f, 0.044846f, - 0.046326f, 0.047822f, 0.049348f, 0.050904f, 0.052491f, 0.054108f, - 0.055756f, 0.057420f, 0.059113f, 0.060853f, 0.062608f, 0.064393f, - 0.066209f, 0.068055f, 0.069932f, 0.071839f, 0.073762f, 0.075731f, - 0.077729f, 0.079759f, 0.081804f, 0.083894f, 0.086015f, 0.088167f, - 0.090333f, 0.092546f, 0.094789f, 0.097063f, 0.099367f, 0.101701f, - 0.104067f, 0.106477f, 0.108904f, 0.111360f, 0.113863f, 0.116381f, - 0.118944f, 0.121538f, 0.124163f, 0.126818f, 0.129519f, 0.132235f, - 0.134997f, 0.137789f, 0.140612f, 0.143465f, 0.146365f, 0.149279f, - 0.152239f, 0.155230f, 0.158267f, 0.161318f, 0.164416f, 0.167544f, - 0.170718f, 0.173907f, 0.177142f, 0.180407f, 0.183719f, 0.187045f, - 0.190433f, 0.193835f, 0.197284f, 0.200763f, 0.204273f, 0.207813f, - 0.211398f, 0.215030f, 0.218692f, 0.222385f, 0.226108f, 0.229877f, - 0.233677f, 0.237522f, 0.241382f, 0.245304f, 0.249256f, 0.253239f, - 0.257252f, 0.261311f, 0.265415f, 0.269551f, 0.273716f, 0.277928f, - 0.282170f, 0.286458f, 0.290776f, 0.295140f, 0.299535f, 0.303975f, - 0.308446f, 0.312947f, 0.317494f, 0.322087f, 0.326711f, 0.331380f, - 0.336080f, 0.340826f, 0.345602f, 0.350423f, 0.355291f, 0.360174f, - 0.365118f, 0.370092f, 0.375113f, 0.380163f, 0.385260f, 0.390387f, - 0.395560f, 0.400778f, 0.406027f, 0.411322f, 0.416663f, 0.422034f, - 0.427451f, 0.432898f, 0.438392f, 0.443931f, 0.449500f, 0.455116f, - 0.460777f, 0.466468f, 0.472221f, 0.477989f, 0.483818f, 0.489677f, - 0.495583f, 0.501518f, 0.507500f, 0.513527f, 0.519600f, 0.525719f, - 0.531868f, 0.538064f, 0.544289f, 0.550576f, 0.556893f, 0.563256f, - 0.569650f, 0.576104f, 0.582589f, 0.589120f, 0.595697f, 0.602304f, - 0.608972f, 0.615671f, 0.622415f, 0.629206f, 0.636027f, 0.642908f, - 0.649821f, 0.656779f, 0.663783f, 0.670832f, 0.677913f, 0.685054f, - 0.692226f, 0.699443f, 0.706706f, 0.714015f, 0.721370f, 0.728771f, - 0.736202f, 0.743694f, 0.751217f, 0.758785f, 0.766400f, 0.774060f, - 0.781765f, 0.789517f, 0.797314f, 0.805158f, 0.813031f, 0.820966f, - 0.828946f, 0.836957f, 0.845029f, 0.853132f, 0.861280f, 0.869490f, - 0.877729f, 0.886015f, 0.894362f, 0.902739f, 0.911162f, 0.919631f, - 0.928161f, 0.936721f, 0.945327f, 0.953994f, 0.962692f, 0.971435f, - 0.980240f, 0.989075f, 0.997955f, 1.000000f, - }; - std::vector<float> x; - for (size_t v = 0; v < 256; ++v) - x.push_back(v / 255.f); - - SkColorSpaceTransferFn fn_approx; - bool converged = SkApproximateTransferFn(x.data(), t, x.size(), &fn_approx); - EXPECT_TRUE(converged); - - // The approximation should be nearly exact. - float expected_error = 1.f / 4096.f; - for (size_t i = 0; i < x.size(); ++i) { - float fn_approx_of_x = SkTransferFnEval(fn_approx, x[i]); - EXPECT_NEAR(t[i], fn_approx_of_x, expected_error); - if (std::abs(t[i] - fn_approx_of_x) > expected_error) - break; - } -} - -TEST(ColorSpace, ApproximateTransferFnBadMatch) { - const float kStep = 1.f / 512.f; - ColorSpace::TransferID transfer_ids[3] = { - ColorSpace::TransferID::IEC61966_2_1, ColorSpace::TransferID::GAMMA22, - ColorSpace::TransferID::BT709, - }; - gfx::ColorSpace color_spaces[3]; - - // The first iteration will have a perfect match. The second will be very - // close. The third will converge, but with an error of ~7/256. - for (size_t transfers_to_use = 1; transfers_to_use <= 3; ++transfers_to_use) { - std::vector<float> x; - std::vector<float> t; - for (size_t c = 0; c < transfers_to_use; ++c) { - color_spaces[c] = - gfx::ColorSpace(ColorSpace::PrimaryID::BT709, transfer_ids[c]); - SkColorSpaceTransferFn tr_fn; - bool result = color_spaces[c].GetTransferFunction(&tr_fn); - CHECK(result); - - for (float v = 0; v <= 1.f; v += kStep) { - x.push_back(v); - t.push_back(SkTransferFnEval(tr_fn, v)); - } - } - - SkColorSpaceTransferFn fn_approx; - bool converged = - SkApproximateTransferFn(x.data(), t.data(), x.size(), &fn_approx); - EXPECT_TRUE(converged); - - float expected_error = 1.5f / 256.f; - if (transfers_to_use == 3) - expected_error = 8.f / 256.f; - - for (size_t i = 0; i < x.size(); ++i) { - float fn_approx_of_x = SkTransferFnEval(fn_approx, x[i]); - EXPECT_NEAR(t[i], fn_approx_of_x, expected_error); - if (std::abs(t[i] - fn_approx_of_x) > expected_error) - break; - } - } -} - TEST(ColorSpace, RasterAndBlend) { ColorSpace display_color_space;
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc index c4c31f83..59407f4e 100644 --- a/ui/gfx/color_transform_unittest.cc +++ b/ui/gfx/color_transform_unittest.cc
@@ -265,21 +265,21 @@ ColorTransform::TriStim expected_transformed_value( 0.34090986847877502f, 0.42633286118507385f, 0.3408740758895874f); - // One step should be needed, namely, the SkColorSpaceXform. + // Two steps should be needed, transfer fn and matrix. std::unique_ptr<ColorTransform> icc_to_xyzd50( ColorTransform::NewColorTransform( icc_space, xyzd50, ColorTransform::Intent::INTENT_ABSOLUTE)); - EXPECT_EQ(icc_to_xyzd50->NumberOfStepsForTesting(), 1u); + EXPECT_EQ(icc_to_xyzd50->NumberOfStepsForTesting(), 2u); icc_to_xyzd50->Transform(&transformed_value, 1); EXPECT_NEAR(transformed_value.x(), expected_transformed_value.x(), kEpsilon); EXPECT_NEAR(transformed_value.y(), expected_transformed_value.y(), kEpsilon); EXPECT_NEAR(transformed_value.z(), expected_transformed_value.z(), kEpsilon); - // One step should be needed, namely, the SkColorSpaceXform. + // Two steps should be needed, matrix and transfer fn. std::unique_ptr<ColorTransform> xyzd50_to_icc( ColorTransform::NewColorTransform( xyzd50, icc_space, ColorTransform::Intent::INTENT_ABSOLUTE)); - EXPECT_EQ(xyzd50_to_icc->NumberOfStepsForTesting(), 1u); + EXPECT_EQ(xyzd50_to_icc->NumberOfStepsForTesting(), 2u); xyzd50_to_icc->Transform(&transformed_value, 1); EXPECT_NEAR(input_value.x(), transformed_value.x(), kEpsilon); EXPECT_NEAR(input_value.y(), transformed_value.y(), kEpsilon);
diff --git a/ui/gfx/icc_profile.cc b/ui/gfx/icc_profile.cc index 55b7a6d..a5f60e5 100644 --- a/ui/gfx/icc_profile.cc +++ b/ui/gfx/icc_profile.cc
@@ -13,7 +13,7 @@ #include "base/metrics/histogram_macros.h" #include "base/synchronization/lock.h" #include "third_party/skia/include/core/SkColorSpaceXform.h" -#include "third_party/skia/include/core/SkICC.h" +#include "third_party/skia/third_party/skcms/skcms.h" #include "ui/gfx/skia_color_space_util.h" namespace gfx { @@ -75,73 +75,36 @@ if (data_.empty()) return kICCNoProfile; - // Parse the profile and attempt to create a SkColorSpaceXform out of it. - sk_sp<SkColorSpace> sk_srgb_color_space = SkColorSpace::MakeSRGB(); - sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size()); - if (!sk_icc) { - DLOG(ERROR) << "Failed to parse ICC profile to SkICC."; + // Parse the profile. + skcms_ICCProfile profile; + if (!skcms_Parse(data_.data(), data_.size(), &profile)) { + DLOG(ERROR) << "Failed to parse ICC profile."; return kICCFailedToParse; } - sk_color_space_ = SkColorSpace::MakeICC(data_.data(), data_.size()); - if (!sk_color_space_) { - DLOG(ERROR) << "Failed to parse ICC profile to SkColorSpace."; - return kICCFailedToExtractSkColorSpace; - } - std::unique_ptr<SkColorSpaceXform> sk_color_space_xform = - SkColorSpaceXform::New(sk_srgb_color_space.get(), sk_color_space_.get()); - if (!sk_color_space_xform) { - DLOG(ERROR) << "Parsed ICC profile but can't create SkColorSpaceXform."; - return kICCFailedToCreateXform; + + // Coerce it into a rasterization destination (if possible). If the profile + // can't be approximated accurately, skcms will not allow transforming to it, + // and this will fail. + if (!skcms_MakeUsableAsDestinationWithSingleCurve(&profile)) { + DLOG(ERROR) << "Parsed ICC profile but can't make usable as destination."; + return kICCFailedToMakeUsable; } - // Because this SkColorSpace can be used to construct a transform, we can use - // it to create a LUT based color transform, at the very least. If we fail to - // get any better approximation, we'll use sRGB as our approximation. - ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_); - ColorSpace::CreateSRGB().GetTransferFunction(&transfer_fn_); + // Create an SkColorSpace from the profile. This should always succeed after + // calling MakeUsableAsDestinationWithSingleCurve. + sk_color_space_ = SkColorSpace::Make(&profile); + DCHECK(sk_color_space_); - // If our SkColorSpace representation is sRGB then return that. - if (sk_color_space_->isSRGB()) - return kICCExtractedSRGBColorSpace; + // Extract the primary matrix and transfer function + to_XYZD50_.set3x3RowMajorf(&profile.toXYZD50.vals[0][0]); + memcpy(&transfer_fn_, &profile.trc[0].parametric, sizeof(transfer_fn_)); - // A primary matrix is required for our parametric representations. Use it if - // it exists. - SkMatrix44 to_XYZD50_matrix; - if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) { - DLOG(ERROR) << "Failed to extract ICC profile primary matrix."; - return kICCFailedToExtractMatrix; - } - to_XYZD50_ = to_XYZD50_matrix; - - // Try to directly extract a numerical transfer function. Use it if it - // exists. - SkColorSpaceTransferFn exact_tr_fn; - if (sk_icc->isNumericalTransferFn(&exact_tr_fn)) { - transfer_fn_ = exact_tr_fn; - return kICCExtractedMatrixAndAnalyticTrFn; - } - - // Attempt to fit a parametric transfer function to the table data in the - // profile. - SkColorSpaceTransferFn approx_tr_fn; - if (!SkApproximateTransferFn(sk_icc, &transfer_fn_error_, &approx_tr_fn)) { - DLOG(ERROR) << "Failed approximate transfer function."; - return kICCFailedToConvergeToApproximateTrFn; - } - - // If this converged, but has too high error, use the sRGB transfer function - // from above. - const float kMaxError = 2.f / 256.f; - if (transfer_fn_error_ >= kMaxError) { - DLOG(ERROR) << "Failed to accurately approximate transfer function, error: " - << 256.f * transfer_fn_error_ << "/256"; - return kICCFailedToApproximateTrFnAccurately; - }; - - // If the error is sufficiently low, declare that the approximation is - // accurate. - transfer_fn_ = approx_tr_fn; - return kICCExtractedMatrixAndApproximatedTrFn; + // We assume that if we accurately approximated the profile, then the + // single-curve version (which may have higher error) is also okay. If we + // want to maintain the distinction between accurate and inaccurate profiles, + // we could check to see if the single-curve version is/ approximately equal + // to the original (or to the multi-channel approximation). + return kICCExtractedMatrixAndTrFn; } ICCProfile::ICCProfile() = default; @@ -293,25 +256,14 @@ // Parse the ICC profile analyze_result_ = Initialize(); switch (analyze_result_) { - case kICCExtractedSRGBColorSpace: - case kICCExtractedMatrixAndAnalyticTrFn: - case kICCExtractedMatrixAndApproximatedTrFn: + case kICCExtractedMatrixAndTrFn: // Successfully and accurately extracted color space. is_valid_ = true; is_parametric_ = true; break; - case kICCFailedToConvergeToApproximateTrFn: - case kICCFailedToApproximateTrFnAccurately: - // Successfully but extracted a color space, but it isn't accurate enough. - is_valid_ = true; - is_parametric_ = false; - break; - case kICCFailedToExtractRawTrFn: - case kICCFailedToExtractMatrix: case kICCFailedToParse: - case kICCFailedToExtractSkColorSpace: - case kICCFailedToCreateXform: case kICCNoProfile: + case kICCFailedToMakeUsable: // Can't even use this color space as a LUT. is_valid_ = false; is_parametric_ = false; @@ -352,23 +304,7 @@ histogrammed_display_ids_.insert(display_id); UMA_HISTOGRAM_ENUMERATION("Blink.ColorSpace.Destination.ICCResult", - analyze_result_, kICCProfileAnalyzeLast); - - // Add histograms for numerical approximation. - bool nonlinear_fit_converged = - analyze_result_ == kICCExtractedMatrixAndApproximatedTrFn || - analyze_result_ == kICCFailedToApproximateTrFnAccurately; - bool nonlinear_fit_did_not_converge = - analyze_result_ == kICCFailedToConvergeToApproximateTrFn; - if (nonlinear_fit_converged || nonlinear_fit_did_not_converge) { - UMA_HISTOGRAM_BOOLEAN("Blink.ColorSpace.Destination.NonlinearFitConverged", - nonlinear_fit_converged); - } - if (nonlinear_fit_converged) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Blink.ColorSpace.Destination.NonlinearFitError", - static_cast<int>(transfer_fn_error_ * 255), 0, 127, 16); - } + analyze_result_); } } // namespace gfx
diff --git a/ui/gfx/icc_profile.h b/ui/gfx/icc_profile.h index 198781d..825d813 100644 --- a/ui/gfx/icc_profile.h +++ b/ui/gfx/icc_profile.h
@@ -77,18 +77,11 @@ // This must match ICCProfileAnalyzeResult enum in histograms.xml. enum AnalyzeResult { - kICCExtractedMatrixAndAnalyticTrFn = 0, - kICCExtractedMatrixAndApproximatedTrFn = 1, - kICCFailedToConvergeToApproximateTrFn = 2, - kICCFailedToExtractRawTrFn = 3, - kICCFailedToExtractMatrix = 4, kICCFailedToParse = 5, - kICCFailedToExtractSkColorSpace = 6, - kICCFailedToCreateXform = 7, - kICCFailedToApproximateTrFnAccurately = 8, - kICCExtractedSRGBColorSpace = 9, kICCNoProfile = 10, - kICCProfileAnalyzeLast = kICCNoProfile, + kICCFailedToMakeUsable = 11, + kICCExtractedMatrixAndTrFn = 12, + kMaxValue = kICCExtractedMatrixAndTrFn, }; const std::vector<char> data_; @@ -118,11 +111,6 @@ SkMatrix44 to_XYZD50_; SkColorSpaceTransferFn transfer_fn_; - // The L-infinity error of the parametric color space fit. This is undefined - // unless |analyze_result_| is kICCFailedToApproximateTrFnAccurately or - // kICCExtractedMatrixAndApproximatedTrFn. - float transfer_fn_error_ = 0; - // The set of display ids which have have caused this ICC profile to be // recorded in UMA histograms. Only record an ICC profile once per display // id (since the same profile will be re-read repeatedly, e.g, when displays
diff --git a/ui/gfx/icc_profile_unittest.cc b/ui/gfx/icc_profile_unittest.cc index 7e9b3272..6e3cc9d8 100644 --- a/ui/gfx/icc_profile_unittest.cc +++ b/ui/gfx/icc_profile_unittest.cc
@@ -67,30 +67,20 @@ } TEST(ICCProfile, ParametricVersusExactInaccurate) { - // This ICC profile has three transfer functions that differ enough that the - // parametric color space is considered inaccurate. + // This ICC profile has three transfer functions that differ significantly, + // but ICCProfiles are always either invalid or considered accurate (and in + // this case, each curve is approximated, so the profile is "accurate"). + // See comments in ICCProfile::Internals::Analyze. ICCProfile multi_tr_fn = ICCProfileForTestingNoAnalyticTrFn(); - EXPECT_FALSE(multi_tr_fn.GetColorSpace().IsParametricAccurate()); + EXPECT_TRUE(multi_tr_fn.GetColorSpace().IsParametricAccurate()); - // Fails to get parametric color space because the space is not parametric. ICCProfile profile; - profile = ICCProfile::FromParametricColorSpace(multi_tr_fn.GetColorSpace()); - EXPECT_FALSE(profile.IsValid()); - - // The Mac cache does not find the parametric approximation, because the cache - // only has the original. - profile = ICCProfile::FromCacheMac( - multi_tr_fn.GetColorSpace().GetParametricApproximation()); - EXPECT_FALSE(profile.IsValid()); - - // The Mac cache does find the original. profile = ICCProfile::FromCacheMac(multi_tr_fn.GetColorSpace()); EXPECT_TRUE(profile.IsValid()); EXPECT_EQ(profile, multi_tr_fn); // We are capable of generating a parametric approximation. - profile = ICCProfile::FromParametricColorSpace( - multi_tr_fn.GetColorSpace().GetParametricApproximation()); + profile = ICCProfile::FromParametricColorSpace(multi_tr_fn.GetColorSpace()); EXPECT_TRUE(profile.IsValid()); EXPECT_NE(profile, multi_tr_fn); } @@ -127,13 +117,12 @@ } TEST(ICCProfile, ParametricVersusExactA2B) { - // This ICC profile has only an A2B representation. We cannot create an - // SkColorSpaceXform to A2B only ICC profiles, so this should be marked - // as invalid. + // This ICC profile has only an A2B representation. We cannot transform to + // A2B only ICC profiles, so this should be marked as invalid. ICCProfile a2b = ICCProfileForTestingA2BOnly(); EXPECT_FALSE(a2b.GetColorSpace().IsValid()); - // Even though it is invalid, it should not be equal to the empty constructor. + // Even though it is invalid, it should not be equal to the empty constructor EXPECT_NE(a2b, gfx::ICCProfile()); }
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc index bf6111f..056d0525 100644 --- a/ui/gfx/mac/io_surface.cc +++ b/ui/gfx/mac/io_surface.cc
@@ -183,13 +183,9 @@ return nullptr; } - // For unknown reasons, triggering this lock on OS X 10.9, on certain GPUs, - // causes PDFs to render incorrectly. Hopefully this check can be removed once - // pdfium switches to a Skia backend on Mac. - // https://crbug.com/594343. // IOSurface clearing causes significant performance regression on about half // of all devices running Yosemite. https://crbug.com/606850#c22. - if (base::mac::IsOS10_9() || base::mac::IsOS10_10()) + if (base::mac::IsOS10_10()) should_clear = false; if (should_clear) {
diff --git a/ui/gfx/platform_font_mac_unittest.mm b/ui/gfx/platform_font_mac_unittest.mm index a935e945..f031568 100644 --- a/ui/gfx/platform_font_mac_unittest.mm +++ b/ui/gfx/platform_font_mac_unittest.mm
@@ -151,16 +151,6 @@ } ns_font = [NSFont systemFontOfSize:13]; - if (base::mac::IsOS10_9()) { - // On 10.9 the system font doesn't provide finer-grained weights. It's - // either bold or it isn't. - for (int row = 6; row <= 14; ++row) { - SCOPED_TRACE(testing::Message() << "Row: " << row); - ns_font = [manager convertWeight:up ofFont:ns_font]; - EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); - } - return; - } if (base::mac::IsOS10_11()) { // On 10.11 the API jumps to BOLD, but has heavier weights as well.
diff --git a/ui/gfx/skia_color_space_util.cc b/ui/gfx/skia_color_space_util.cc index b840f7e6..8f7b6f1d 100644 --- a/ui/gfx/skia_color_space_util.cc +++ b/ui/gfx/skia_color_space_util.cc
@@ -12,287 +12,6 @@ namespace gfx { -namespace { - -// Evaluate the gradient of the nonlinear component of fn -void SkTransferFnEvalGradientNonlinear(const SkColorSpaceTransferFn& fn, - float x, - float* d_fn_d_fA_at_x, - float* d_fn_d_fB_at_x, - float* d_fn_d_fE_at_x, - float* d_fn_d_fG_at_x) { - float base = fn.fA * x + fn.fB; - if (base > 0.f) { - *d_fn_d_fA_at_x = fn.fG * x * std::pow(base, fn.fG - 1.f); - *d_fn_d_fB_at_x = fn.fG * std::pow(base, fn.fG - 1.f); - *d_fn_d_fE_at_x = 1.f; - *d_fn_d_fG_at_x = std::pow(base, fn.fG) * std::log(base); - } else { - *d_fn_d_fA_at_x = 0.f; - *d_fn_d_fB_at_x = 0.f; - *d_fn_d_fE_at_x = 0.f; - *d_fn_d_fG_at_x = 0.f; - } -} - -// Take one Gauss-Newton step updating fA, fB, fE, and fG, given fD. -bool SkTransferFnGaussNewtonStepNonlinear(SkColorSpaceTransferFn* fn, - float* error_Linfty_after, - const float* x, - const float* t, - size_t n) { - // Let ne_lhs be the left hand side of the normal equations, and let ne_rhs - // be the right hand side. Zero the diagonal of |ne_lhs| and all of |ne_rhs|. - SkMatrix44 ne_lhs; - SkVector4 ne_rhs; - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - ne_lhs.set(row, col, 0); - } - ne_rhs.fData[row] = 0; - } - - // Add the contributions from each sample to the normal equations. - for (size_t i = 0; i < n; ++i) { - // Ignore points in the linear segment. - if (x[i] < fn->fD) - continue; - - // Let J be the gradient of fn with respect to parameters A, B, E, and G, - // evaulated at this point. - float J[4]; - SkTransferFnEvalGradientNonlinear(*fn, x[i], &J[0], &J[1], &J[2], &J[3]); - // Let r be the residual at this point; - float r = t[i] - SkTransferFnEval(*fn, x[i]); - - // Update the normal equations left hand side with the outer product of J - // with itself. - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - ne_lhs.set(row, col, ne_lhs.get(row, col) + J[row] * J[col]); - } - - // Update the normal equations right hand side the product of J with the - // residual - ne_rhs.fData[row] += J[row] * r; - } - } - - // Note that if fG = 1, then the normal equations will be singular (because, - // when fG = 1, because fB and fE are equivalent parameters). To avoid - // problems, fix fE (row/column 3) in these circumstances. - float kEpsilonForG = 1.f / 1024.f; - if (std::abs(fn->fG - 1) < kEpsilonForG) { - for (int row = 0; row < 4; ++row) { - float value = (row == 2) ? 1.f : 0.f; - ne_lhs.set(row, 2, value); - ne_lhs.set(2, row, value); - } - ne_rhs.fData[2] = 0.f; - } - - // Solve the normal equations. - SkMatrix44 ne_lhs_inv; - if (!ne_lhs.invert(&ne_lhs_inv)) - return false; - SkVector4 step = ne_lhs_inv * ne_rhs; - - // Update the transfer function. - fn->fA += step.fData[0]; - fn->fB += step.fData[1]; - fn->fE += step.fData[2]; - fn->fG += step.fData[3]; - - // fA should always be positive. - fn->fA = std::max(fn->fA, 0.f); - - // Ensure that fn be defined at fD. - if (fn->fA * fn->fD + fn->fB < 0.f) - fn->fB = -fn->fA * fn->fD; - - // Compute the Linfinity error. - *error_Linfty_after = 0; - for (size_t i = 0; i < n; ++i) { - if (x[i] >= fn->fD) { - float error = std::abs(t[i] - SkTransferFnEval(*fn, x[i])); - *error_Linfty_after = std::max(error, *error_Linfty_after); - } - } - - return true; -} - -// Solve for fA, fB, fE, and fG, given fD. The initial value of |fn| is the -// point from which iteration starts. -bool SkTransferFnSolveNonlinear(SkColorSpaceTransferFn* fn, - const float* x, - const float* t, - size_t n) { - // Take a maximum of 8 Gauss-Newton steps. - const size_t kNumSteps = 8; - - // The L-infinity error after each step. - float step_error[kNumSteps] = {0}; - size_t step = 0; - for (;; ++step) { - // If the normal equations are singular, we can't continue. - if (!SkTransferFnGaussNewtonStepNonlinear(fn, &step_error[step], x, t, n)) - return false; - - // If the error is inf or nan, we are clearly not converging. - if (std::isnan(step_error[step]) || std::isinf(step_error[step])) - return false; - - // Stop if our error is tiny. - float kEarlyOutTinyErrorThreshold = (1.f / 16.f) / 256.f; - if (step_error[step] < kEarlyOutTinyErrorThreshold) - break; - - // Stop if our error is not changing, or changing in the wrong direction. - if (step > 1) { - // If our error is is huge for two iterations, we're probably not in the - // region of convergence. - if (step_error[step] > 1.f && step_error[step - 1] > 1.f) - return false; - - // If our error didn't change by ~1%, assume we've converged as much as we - // are going to. - const float kEarlyOutByPercentChangeThreshold = 32.f / 256.f; - const float kMinimumPercentChange = 1.f / 128.f; - float percent_change = - std::abs(step_error[step] - step_error[step - 1]) / step_error[step]; - if (percent_change < kMinimumPercentChange && - step_error[step] < kEarlyOutByPercentChangeThreshold) { - break; - } - } - if (step == kNumSteps - 1) - break; - } - - // Declare failure if our error is obviously too high. - float kDidNotConvergeThreshold = 64.f / 256.f; - if (step_error[step] > kDidNotConvergeThreshold) - return false; - - // We've converged to a reasonable solution. If some of the parameters are - // extremely close to 0 or 1, set them to 0 or 1. - const float kRoundEpsilon = 1.f / 1024.f; - if (std::abs(fn->fA - 1.f) < kRoundEpsilon) - fn->fA = 1.f; - if (std::abs(fn->fB) < kRoundEpsilon) - fn->fB = 0; - if (std::abs(fn->fE) < kRoundEpsilon) - fn->fE = 0; - if (std::abs(fn->fG - 1.f) < kRoundEpsilon) - fn->fG = 1.f; - return true; -} - -bool SkApproximateTransferFnInternal(const float* x, - const float* t, - size_t n, - SkColorSpaceTransferFn* fn) { - // First, guess at a value of fD. Assume that the nonlinear segment applies - // to all x >= 0.15. This is generally a safe assumption (fD is usually less - // than 0.1). - const float kLinearSegmentMaximum = 0.15f; - fn->fD = kLinearSegmentMaximum; - - // Do a nonlinear regression on the nonlinear segment. Use a number of guesses - // for the initial value of fG, because not all values will converge. - bool nonlinear_fit_converged = false; - { - const size_t kNumInitialGammas = 4; - float initial_gammas[kNumInitialGammas] = {2.2f, 1.f, 3.f, 0.5f}; - for (size_t i = 0; i < kNumInitialGammas; ++i) { - fn->fG = initial_gammas[i]; - fn->fA = 1; - fn->fB = 0; - fn->fC = 1; - fn->fE = 0; - fn->fF = 0; - if (SkTransferFnSolveNonlinear(fn, x, t, n)) { - nonlinear_fit_converged = true; - break; - } - } - } - if (!nonlinear_fit_converged) - return false; - - // Now walk back fD from our initial guess to the point where our nonlinear - // fit no longer fits (or all the way to 0 if it fits). - { - // Find the L-infinity error of this nonlinear fit (using our old fD value). - float max_error_in_nonlinear_fit = 0; - for (size_t i = 0; i < n; ++i) { - if (x[i] < fn->fD) - continue; - float error_at_xi = std::abs(t[i] - SkTransferFnEval(*fn, x[i])); - max_error_in_nonlinear_fit = - std::max(max_error_in_nonlinear_fit, error_at_xi); - } - - // Now find the maximum x value where this nonlinear fit is no longer - // accurate, no longer defined, or no longer nonnegative. - fn->fD = 0.f; - float max_x_where_nonlinear_does_not_fit = -1.f; - for (size_t i = 0; i < n; ++i) { - if (x[i] >= kLinearSegmentMaximum) - continue; - - // The nonlinear segment is only undefined when fA * x + fB is - // nonnegative. - float fn_at_xi = -1; - if (fn->fA * x[i] + fn->fB >= 0) - fn_at_xi = SkTransferFnEvalUnclamped(*fn, x[i]); - - // If the value is negative (or undefined), say that the fit was bad. - bool nonlinear_fits_xi = true; - if (fn_at_xi < 0) - nonlinear_fits_xi = false; - - // Compute the error, and define "no longer accurate" as "has more than - // 10% more error than the maximum error in the fit segment". - if (nonlinear_fits_xi) { - float error_at_xi = std::abs(t[i] - fn_at_xi); - if (error_at_xi > 1.1f * max_error_in_nonlinear_fit) - nonlinear_fits_xi = false; - } - - if (!nonlinear_fits_xi) { - max_x_where_nonlinear_does_not_fit = - std::max(max_x_where_nonlinear_does_not_fit, x[i]); - } - } - - // Now let fD be the highest sample of x that is above the threshold where - // the nonlinear segment does not fit. - fn->fD = 1.f; - for (size_t i = 0; i < n; ++i) { - if (x[i] > max_x_where_nonlinear_does_not_fit) - fn->fD = std::min(fn->fD, x[i]); - } - } - - // Compute the linear segment, now that we have our definitive fD. - if (fn->fD <= 0) { - // If this has no linear segment, don't try to solve for one. - fn->fC = 1; - fn->fF = 0; - } else { - // Set the linear portion such that it go through the origin and be - // continuous with the nonlinear segment. - float fn_at_fD = SkTransferFnEval(*fn, fn->fD); - fn->fC = fn_at_fD / fn->fD; - fn->fF = 0; - } - return true; -} - -} // namespace - float SkTransferFnEvalUnclamped(const SkColorSpaceTransferFn& fn, float x) { if (x < fn.fD) return fn.fC * x + fn.fF; @@ -345,62 +64,6 @@ return true; } -bool SkApproximateTransferFn(const float* x, - const float* t, - size_t n, - SkColorSpaceTransferFn* fn) { - if (SkApproximateTransferFnInternal(x, t, n, fn)) - return true; - fn->fA = 1; - fn->fB = 0; - fn->fC = 1; - fn->fD = 0; - fn->fE = 0; - fn->fF = 0; - fn->fG = 1; - return false; -} - -bool SkApproximateTransferFn(sk_sp<SkICC> sk_icc, - float* max_error, - SkColorSpaceTransferFn* fn) { - SkICC::Tables tables; - bool got_tables = sk_icc->rawTransferFnData(&tables); - if (!got_tables) - return false; - - // Merge all channels' tables into a single array. - SkICC::Channel* channels[3] = {&tables.fGreen, &tables.fRed, &tables.fBlue}; - std::vector<float> x; - std::vector<float> t; - for (size_t c = 0; c < 3; ++c) { - SkICC::Channel* channel = channels[c]; - const float* data = reinterpret_cast<const float*>( - tables.fStorage->bytes() + channel->fOffset); - for (int i = 0; i < channel->fCount; ++i) { - float xi = i / (channel->fCount - 1.f); - float ti = data[i]; - x.push_back(xi); - t.push_back(ti); - } - } - - // Approximate the transfer function. - bool converged = - SkApproximateTransferFnInternal(x.data(), t.data(), x.size(), fn); - if (!converged) - return false; - - // Compute the error among all channels. - *max_error = 0; - for (size_t i = 0; i < x.size(); ++i) { - float fn_of_xi = gfx::SkTransferFnEval(*fn, x[i]); - float error_at_xi = std::abs(t[i] - fn_of_xi); - *max_error = std::max(*max_error, error_at_xi); - } - return true; -} - bool SkMatrixIsApproximatelyIdentity(const SkMatrix44& m) { const float kEpsilon = 1.f / 256.f; for (int i = 0; i < 4; ++i) {
diff --git a/ui/gfx/skia_color_space_util.h b/ui/gfx/skia_color_space_util.h index f15f8267..bec9a2f 100644 --- a/ui/gfx/skia_color_space_util.h +++ b/ui/gfx/skia_color_space_util.h
@@ -31,21 +31,6 @@ bool COLOR_SPACE_EXPORT SkTransferFnIsApproximatelyIdentity(const SkColorSpaceTransferFn& fn); -// Approximates the |n| points in |x| and |t| by the transfer function |fn|. -// Returns true if the approximation converged. -bool COLOR_SPACE_EXPORT SkApproximateTransferFn(const float* x, - const float* t, - size_t n, - SkColorSpaceTransferFn* fn); - -// Approximates |sk_icc| by the transfer function |fn|. Returns in |max_error| -// the maximum pointwise of all color channels' transfer functions with |fn|. -// Returns false if no approximation was possible, or no approximation -// converged. -bool COLOR_SPACE_EXPORT SkApproximateTransferFn(sk_sp<SkICC> sk_icc, - float* max_error, - SkColorSpaceTransferFn* fn); - bool COLOR_SPACE_EXPORT SkMatrixIsApproximatelyIdentity(const SkMatrix44& m); } // namespace gfx
diff --git a/ui/gl/gl_image_dxgi.cc b/ui/gl/gl_image_dxgi.cc index 612dde30..f35f264 100644 --- a/ui/gl/gl_image_dxgi.cc +++ b/ui/gl/gl_image_dxgi.cc
@@ -237,13 +237,10 @@ HRESULT hr = d3d11_device_->CreateTexture2D( &desc, nullptr, decoder_copy_texture_.GetAddressOf()); - // TODO(sunnyps): Remove after fixing https://crbug.com/794735 - base::debug::Alias(&hr); - HRESULT reason_hr = S_OK; - base::debug::Alias(&reason_hr); - if (hr == DXGI_ERROR_DEVICE_REMOVED) - reason_hr = d3d11_device_->GetDeviceRemovedReason(); - CHECK(SUCCEEDED(hr)); + if (FAILED(hr)) { + DLOG(ERROR) << "CreateTexture2D failed: " << std::hex << hr; + return false; + } EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); EGLAttrib frame_attributes[] = { @@ -253,20 +250,27 @@ EGLBoolean result = eglStreamPostD3DTextureANGLE( egl_display, stream_, static_cast<void*>(decoder_copy_texture_.Get()), frame_attributes); - if (!result) + if (!result) { + DLOG(ERROR) << "eglStreamPostD3DTextureANGLE failed"; return false; + } result = eglStreamConsumerAcquireKHR(egl_display, stream_); - if (!result) + if (!result) { + DLOG(ERROR) << "eglStreamConsumerAcquireKHR failed"; return false; + } d3d11_device_.CopyTo(video_device_.GetAddressOf()); Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; d3d11_device_->GetImmediateContext(context.GetAddressOf()); context.CopyTo(video_context_.GetAddressOf()); +#if DCHECK_IS_ON() Microsoft::WRL::ComPtr<ID3D10Multithread> multithread; d3d11_device_.CopyTo(multithread.GetAddressOf()); - CHECK(multithread->GetMultithreadProtected()); + DCHECK(multithread->GetMultithreadProtected()); +#endif // DCHECK_IS_ON() + return true; } @@ -277,7 +281,7 @@ Microsoft::WRL::ComPtr<ID3D11Device> processor_device; video_processor->GetDevice(processor_device.GetAddressOf()); - CHECK_EQ(d3d11_device_.Get(), processor_device.Get()); + DCHECK_EQ(d3d11_device_.Get(), processor_device.Get()); d3d11_processor_ = video_processor; enumerator_ = enumerator; @@ -303,10 +307,10 @@ if (copied_) return true; - CHECK(video_device_); + DCHECK(video_device_); Microsoft::WRL::ComPtr<ID3D11Device> texture_device; texture_->GetDevice(texture_device.GetAddressOf()); - CHECK_EQ(d3d11_device_.Get(), texture_device.Get()); + DCHECK_EQ(d3d11_device_.Get(), texture_device.Get()); D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_view_desc = {0}; input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h index 87f4cba..a9fa046 100644 --- a/ui/gl/test/gl_image_test_template.h +++ b/ui/gl/test/gl_image_test_template.h
@@ -145,11 +145,6 @@ return; #if defined(OS_MACOSX) - // This functionality is disabled on Mavericks because it breaks PDF - // rendering. https://crbug.com/594343. - if (base::mac::IsOS10_9()) - return; - // This functionality is disabled on Yosemite because it is suspected of // causing performance regressions on old hardware. https://crbug.com/606850. if (base::mac::IsOS10_10())
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc index 33d7e8a..a016b777 100644 --- a/ui/native_theme/common_theme.cc +++ b/ui/native_theme/common_theme.cc
@@ -89,6 +89,10 @@ static const SkColor kBlueButtonTextColor = SK_ColorWHITE; static const SkColor kBlueButtonShadowColor = SkColorSetRGB(0x53, 0x8C, 0xEA); // MenuItem: + static const SkColor kTouchableMenuItemLabelColor = + SkColorSetRGB(0x20, 0x21, 0x24); + static const SkColor kActionableSubmenuVerticalSeparatorColor = + SkColorSetARGB(0x24, 0x20, 0x21, 0x24); static const SkColor kMenuBackgroundColor = SK_ColorWHITE; static const SkColor kMenuHighlightBackgroundColor = SkColorSetA(SK_ColorBLACK, 0x14); @@ -187,6 +191,10 @@ return kDisabledTextColor; // MenuItem + case NativeTheme::kColorId_TouchableMenuItemLabelColor: + return kTouchableMenuItemLabelColor; + case NativeTheme::kColorId_ActionableSubmenuVerticalSeparatorColor: + return kActionableSubmenuVerticalSeparatorColor; case NativeTheme::kColorId_SelectedMenuItemForegroundColor: return kSelectedMenuItemForegroundColor; case NativeTheme::kColorId_MenuBorderColor:
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h index d926149c..c459020 100644 --- a/ui/native_theme/native_theme.h +++ b/ui/native_theme/native_theme.h
@@ -311,6 +311,8 @@ kColorId_ProminentButtonColor, kColorId_TextOnProminentButtonColor, // MenuItem + kColorId_TouchableMenuItemLabelColor, + kColorId_ActionableSubmenuVerticalSeparatorColor, kColorId_EnabledMenuItemForegroundColor, kColorId_DisabledMenuItemForegroundColor, kColorId_SelectedMenuItemForegroundColor,
diff --git a/ui/native_theme/native_theme_dark_aura.cc b/ui/native_theme/native_theme_dark_aura.cc index 655b487..998c2454 100644 --- a/ui/native_theme/native_theme_dark_aura.cc +++ b/ui/native_theme/native_theme_dark_aura.cc
@@ -112,6 +112,8 @@ case kColorId_DisabledMenuItemForegroundColor: case kColorId_SelectedMenuItemForegroundColor: case kColorId_FocusedMenuItemBackgroundColor: + case kColorId_TouchableMenuItemLabelColor: + case kColorId_ActionableSubmenuVerticalSeparatorColor: case kColorId_MenuItemMinorTextColor: case kColorId_MenuSeparatorColor: case kColorId_MenuBackgroundColor:
diff --git a/ui/ozone/platform/drm/host/drm_device_connector.cc b/ui/ozone/platform/drm/host/drm_device_connector.cc index 6bfc3cb..eb9fec9 100644 --- a/ui/ozone/platform/drm/host/drm_device_connector.cc +++ b/ui/ozone/platform/drm/host/drm_device_connector.cc
@@ -42,9 +42,9 @@ ws_runner_(base::ThreadTaskRunnerHandle::IsSet() ? base::ThreadTaskRunnerHandle::Get() : nullptr) { - // Invariant: we only have a runner at startup if executing in mus mode. - DCHECK((ws_runner_ && features::IsMusEnabled()) || - (!ws_runner_ && !features::IsMusEnabled())); + // Invariant: we only have a runner at startup if executing in mash mode. + DCHECK((ws_runner_ && features::IsMashEnabled()) || + (!ws_runner_ && !features::IsMashEnabled())); } DrmDeviceConnector::~DrmDeviceConnector() {}
diff --git a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc index 09632b1..c06c013d 100644 --- a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc +++ b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
@@ -95,7 +95,7 @@ if (ui_runner_) { weak_ptr_ = weak_ptr_factory_.GetWeakPtr(); } else { - DCHECK(!features::IsMusEnabled()); + DCHECK(!features::IsMashEnabled()); } }
diff --git a/ui/ozone/platform/wayland/wayland_window.cc b/ui/ozone/platform/wayland/wayland_window.cc index 6ebe4075..25b285c 100644 --- a/ui/ozone/platform/wayland/wayland_window.cc +++ b/ui/ozone/platform/wayland/wayland_window.cc
@@ -194,8 +194,6 @@ void WaylandWindow::Minimize() { DCHECK(xdg_surface_); - - DCHECK(xdg_surface_); xdg_surface_->SetMinimized(); connection_->ScheduleFlush();
diff --git a/ui/views/controls/menu/menu_config.cc b/ui/views/controls/menu/menu_config.cc index a0f7af8..1a22946d 100644 --- a/ui/views/controls/menu/menu_config.cc +++ b/ui/views/controls/menu/menu_config.cc
@@ -29,7 +29,7 @@ icon_to_label_padding(10), touchable_icon_to_label_padding(22), touchable_icon_size(20), - touchable_icon_color(SkColorSetA(SK_ColorBLACK, 0xDE)), + touchable_icon_color(SkColorSetRGB(0x5F, 0x63, 0x60)), check_width(kMenuCheckSize), check_height(kMenuCheckSize), arrow_width(kSubmenuArrowSize), @@ -39,9 +39,14 @@ separator_spacing_height(3), separator_thickness(1), show_mnemonics(false), + use_mnemonics(true), scroll_arrow_height(3), label_to_minor_text_padding(10), item_min_height(0), + actionable_submenu_arrow_to_edge_padding(14), + actionable_submenu_width(37), + actionable_submenu_vertical_separator_height(18), + actionable_submenu_vertical_separator_width(1), show_accelerators(true), always_use_icon_to_label_padding(false), align_arrow_and_shortcut(false),
diff --git a/ui/views/controls/menu/menu_config.h b/ui/views/controls/menu/menu_config.h index 4f4d83c0..22a7d9eb 100644 --- a/ui/views/controls/menu/menu_config.h +++ b/ui/views/controls/menu/menu_config.h
@@ -109,6 +109,9 @@ // Are mnemonics shown? bool show_mnemonics; + // Are mnemonics used to activate items? + bool use_mnemonics; + // Height of the scroll arrow. int scroll_arrow_height; @@ -119,6 +122,18 @@ // Minimum height of menu item. int item_min_height; + // Edge padding for an actionable submenu arrow. + int actionable_submenu_arrow_to_edge_padding; + + // Width of the submenu in an actionable submenu. + int actionable_submenu_width; + + // The height of the vertical separator used in an actionable submenu. + int actionable_submenu_vertical_separator_height; + + // The width of the vertical separator used in an actionable submenu. + int actionable_submenu_vertical_separator_width; + // Whether the keyboard accelerators are visible. bool show_accelerators;
diff --git a/ui/views/controls/menu/menu_config_mac.mm b/ui/views/controls/menu/menu_config_mac.mm index 16757bb..d308d1e0 100644 --- a/ui/views/controls/menu/menu_config_mac.mm +++ b/ui/views/controls/menu/menu_config_mac.mm
@@ -48,6 +48,7 @@ font_list = gfx::FontList(gfx::Font([NSFont menuFontOfSize:0.0])); check_selected_combobox_item = true; arrow_key_selection_wraps = false; + use_mnemonics = false; if (ui::MaterialDesignController::IsSecondaryUiMaterial()) InitMaterialMenuConfig(this); }
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index a59f1f2..5ee38baa4 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -694,7 +694,7 @@ // for selected folder menu items. If it's only a left click, show the // contents of the folder. if (!part.is_scroll() && part.menu && - !(part.menu->HasSubmenu() && + !(part.should_submenu_show && part.menu->HasSubmenu() && (event.flags() & ui::EF_LEFT_MOUSE_BUTTON))) { if (active_mouse_view_tracker_->view()) { SendMouseReleaseToActiveView(source, event); @@ -819,7 +819,7 @@ } } else if (event->type() == ui::ET_GESTURE_TAP) { if (!part.is_scroll() && part.menu && - !(part.menu->HasSubmenu())) { + !(part.should_submenu_show && part.menu->HasSubmenu())) { if (part.menu->GetDelegate()->IsTriggerableEvent( part.menu, *event)) { item_selected_by_touch_ = true; @@ -1165,7 +1165,14 @@ size_t current_size = current_path.size(); size_t new_size = new_path.size(); - bool pending_item_changed = pending_state_.item != menu_item; + // ACTIONABLE_SUBMENUs can change without changing the pending item, this + // occurs when selection moves from the COMMAND area to the SUBMENU area of + // the ACTIONABLE_SUBMENU. + const bool pending_item_changed = + pending_state_.item != menu_item || + pending_state_.submenu_open != + !!(selection_types & SELECTION_OPEN_SUBMENU); + if (pending_item_changed && pending_state_.item) SetHotTrackedButton(nullptr); @@ -1174,7 +1181,8 @@ current_path.empty() ? NULL : current_path.front()->GetDelegate(); for (size_t i = paths_differ_at; i < current_size; ++i) { if (current_delegate && - current_path[i]->GetType() == MenuItemView::SUBMENU) { + (current_path[i]->GetType() == MenuItemView::SUBMENU || + current_path[i]->GetType() == MenuItemView::ACTIONABLE_SUBMENU)) { current_delegate->WillHideMenu(current_path[i]); } current_path[i]->SetSelected(false); @@ -1184,6 +1192,14 @@ for (size_t i = paths_differ_at; i < new_size; ++i) { new_path[i]->ScrollRectToVisible(new_path[i]->GetLocalBounds()); new_path[i]->SetSelected(true); + if (new_path[i]->GetType() == MenuItemView::ACTIONABLE_SUBMENU) { + new_path[i]->SetSelectionOfActionableSubmenu( + (selection_types & SELECTION_OPEN_SUBMENU) != 0); + } + } + if (menu_item && menu_item->GetType() == MenuItemView::ACTIONABLE_SUBMENU) { + menu_item->SetSelectionOfActionableSubmenu( + (selection_types & SELECTION_OPEN_SUBMENU) != 0); } if (menu_item && menu_item->GetDelegate()) @@ -1206,9 +1222,10 @@ StartShowTimer(); // Notify an accessibility focus event on all menu items except for the root. - if (menu_item && - (MenuDepth(menu_item) != 1 || - menu_item->GetType() != MenuItemView::SUBMENU)) { + if (menu_item && (MenuDepth(menu_item) != 1 || + menu_item->GetType() != MenuItemView::SUBMENU || + (menu_item->GetType() == MenuItemView::ACTIONABLE_SUBMENU && + (selection_types & SELECTION_OPEN_SUBMENU) == 0))) { menu_item->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); } } @@ -1255,7 +1272,7 @@ possible_drag_ = true; press_pt_ = event->location(); } - if (part.menu->HasSubmenu()) + if (part.menu->HasSubmenu() && part.should_submenu_show) selection_types |= SELECTION_OPEN_SUBMENU; } SetSelection(part.menu, selection_types); @@ -1693,11 +1710,19 @@ part->menu = GetMenuItemAt(menu, menu_loc.x(), menu_loc.y()); part->type = MenuPart::MENU_ITEM; part->submenu = menu; + part->should_submenu_show = + part->submenu && part->menu && + (part->menu->GetType() == MenuItemView::SUBMENU || + IsLocationOverSubmenuAreaOfActionableSubmenu(part->menu, screen_loc)); if (!part->menu) part->parent = menu->GetMenuItem(); return true; } + // Return false for points on touchable menu shadows, to search parent menus. + if (use_touchable_layout_) + return false; + // While the mouse isn't over a menu item or the scroll buttons of menu, it // is contained by menu and so we return true. If we didn't return true other // menus would be searched, even though they are likely obscured by us. @@ -1729,7 +1754,20 @@ gfx::Point view_loc = screen_loc; View::ConvertPointFromScreen(submenu, &view_loc); gfx::Rect vis_rect = submenu->GetVisibleBounds(); - return vis_rect.Contains(view_loc.x(), view_loc.y()); + return vis_rect.Contains(view_loc); +} + +bool MenuController::IsLocationOverSubmenuAreaOfActionableSubmenu( + MenuItemView* item, + const gfx::Point& screen_loc) const { + if (!item || item->GetType() != MenuItemView::ACTIONABLE_SUBMENU) + return false; + + gfx::Point view_loc = screen_loc; + View::ConvertPointFromScreen(item, &view_loc); + if (base::i18n::IsRTL()) + view_loc.set_x(item->GetMirroredXInView(view_loc.x())); + return item->GetSubmenuAreaOfActionableSubmenu().Contains(view_loc); } void MenuController::CommitPendingSelection() { @@ -2121,7 +2159,6 @@ bool prefer_leading, bool* is_leading) { DCHECK(item); - DCHECK(!item->GetParentMenuItem()); // Assume we can honor prefer_leading. *is_leading = prefer_leading; @@ -2130,103 +2167,153 @@ DCHECK(submenu); gfx::Size pref = submenu->GetScrollViewContainer()->GetPreferredSize(); - const gfx::Rect& owner_bounds = pending_state_.initial_bounds; - - // First the size gets reduced to the possible space. - if (!state_.monitor_bounds.IsEmpty()) { - int max_width = state_.monitor_bounds.width(); - int max_height = state_.monitor_bounds.height(); - // In case of bubbles, the maximum width is limited by the space - // between the display corner and the target area + the tip size. - if (state_.anchor == MENU_ANCHOR_BUBBLE_LEFT) { - max_width = owner_bounds.x() - state_.monitor_bounds.x() + - kBubbleTipSizeLeftRight; - } else if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) { - max_width = state_.monitor_bounds.right() - owner_bounds.right() + - kBubbleTipSizeLeftRight; - } else if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) { - max_height = owner_bounds.y() - state_.monitor_bounds.y() + - kBubbleTipSizeTopBottom; - } else if (state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) { - max_height = state_.monitor_bounds.bottom() - owner_bounds.bottom() + - kBubbleTipSizeTopBottom; - } - // The space for the menu to cover should never get empty. - DCHECK_GE(max_width, kBubbleTipSizeLeftRight); - DCHECK_GE(max_height, kBubbleTipSizeTopBottom); - pref.set_width(std::min(pref.width(), max_width)); - pref.set_height(std::min(pref.height(), max_height)); - } - // Also make sure that the menu does not go too wide. - pref.set_width(std::min(pref.width(), - item->GetDelegate()->GetMaxWidthForMenu(item))); - + int x = 0; + int y = 0; const MenuConfig& menu_config = MenuConfig::instance(); // Shadow insets are built into MenuScrollView's preferred size so it must be // compensated for when determining the bounds of touchable menus. - gfx::Insets shadow_insets = BubbleBorder::GetBorderAndShadowInsets( - menu_config.touchable_menu_shadow_elevation); + const gfx::Insets border_and_shadow_insets = + BubbleBorder::GetBorderAndShadowInsets( + menu_config.touchable_menu_shadow_elevation); - int x, y; - if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE || - state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) { - if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) - y = owner_bounds.y() - pref.height() + kBubbleTipSizeTopBottom; - else - y = owner_bounds.bottom() - kBubbleTipSizeTopBottom; + if (!item->GetParentMenuItem()) { + // This is a top-level menu, position it relative to the anchor bounds. + const gfx::Rect& owner_bounds = pending_state_.initial_bounds; - x = owner_bounds.CenterPoint().x() - pref.width() / 2; - int x_old = x; - if (x < state_.monitor_bounds.x()) { - x = state_.monitor_bounds.x(); - } else if (x + pref.width() > state_.monitor_bounds.right()) { - x = state_.monitor_bounds.right() - pref.width(); + // First the size gets reduced to the possible space. + if (!state_.monitor_bounds.IsEmpty()) { + int max_width = state_.monitor_bounds.width(); + int max_height = state_.monitor_bounds.height(); + // In case of bubbles, the maximum width is limited by the space + // between the display corner and the target area + the tip size. + if (state_.anchor == MENU_ANCHOR_BUBBLE_LEFT) { + max_width = owner_bounds.x() - state_.monitor_bounds.x() + + kBubbleTipSizeLeftRight; + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) { + max_width = state_.monitor_bounds.right() - owner_bounds.right() + + kBubbleTipSizeLeftRight; + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) { + max_height = owner_bounds.y() - state_.monitor_bounds.y() + + kBubbleTipSizeTopBottom; + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) { + max_height = state_.monitor_bounds.bottom() - owner_bounds.bottom() + + kBubbleTipSizeTopBottom; + } + // The menu should always have a non-empty available area. + DCHECK_GE(max_width, kBubbleTipSizeLeftRight); + DCHECK_GE(max_height, kBubbleTipSizeTopBottom); + pref.set_width(std::min(pref.width(), max_width)); + pref.set_height(std::min(pref.height(), max_height)); } - submenu->GetScrollViewContainer()->SetBubbleArrowOffset( - pref.width() / 2 - x + x_old); - } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE) { - // Align the left edges of the menu and anchor, and the bottom of the menu - // with the top of the anchor. - x = owner_bounds.origin().x() - shadow_insets.left(); - y = owner_bounds.origin().y() - pref.height() + shadow_insets.bottom() - - menu_config.touchable_anchor_offset; - // Align the right of the container with the right of the app icon. - if (x + pref.width() > state_.monitor_bounds.width()) - x = owner_bounds.right() - pref.width() + shadow_insets.right(); - // Align the top of the menu with the bottom of the anchor. - if (y < 0) { - y = owner_bounds.bottom() - shadow_insets.top() + + // Respect the delegate's maximum width. + pref.set_width( + std::min(pref.width(), item->GetDelegate()->GetMaxWidthForMenu(item))); + + if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE || + state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) { + if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) + y = owner_bounds.y() - pref.height() + kBubbleTipSizeTopBottom; + else + y = owner_bounds.bottom() - kBubbleTipSizeTopBottom; + + x = owner_bounds.CenterPoint().x() - pref.width() / 2; + int x_old = x; + if (x < state_.monitor_bounds.x()) + x = state_.monitor_bounds.x(); + else if (x + pref.width() > state_.monitor_bounds.right()) + x = state_.monitor_bounds.right() - pref.width(); + submenu->GetScrollViewContainer()->SetBubbleArrowOffset(pref.width() / 2 - + x + x_old); + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE) { + // Align the left edges of the menu and anchor, and the bottom of the menu + // with the top of the anchor. + x = owner_bounds.origin().x() - border_and_shadow_insets.left(); + y = owner_bounds.origin().y() - pref.height() + + border_and_shadow_insets.bottom() - menu_config.touchable_anchor_offset; - } - } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT) { - // Align the right of the menu with the left of the anchor, and the top of - // the menu with the top of the anchor. - x = owner_bounds.origin().x() - pref.width() + shadow_insets.right() - - menu_config.touchable_anchor_offset; - y = owner_bounds.origin().y() - shadow_insets.top(); - // Align the left of the menu with the right of the anchor. - if (x < 0) { - x = owner_bounds.right() + shadow_insets.left() + + // Align the right of the container with the right of the anchor. + if (x + pref.width() > state_.monitor_bounds.width()) { + x = owner_bounds.right() - pref.width() + + border_and_shadow_insets.right(); + } + // Align the top of the menu with the bottom of the anchor. + if (y < 0) { + y = owner_bounds.bottom() - border_and_shadow_insets.top() + + menu_config.touchable_anchor_offset; + } + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT) { + // Align the right of the menu with the left of the anchor, and the top of + // the menu with the top of the anchor. + x = owner_bounds.origin().x() - pref.width() + + border_and_shadow_insets.right() - menu_config.touchable_anchor_offset; + y = owner_bounds.origin().y() - border_and_shadow_insets.top(); + // Align the left of the menu with the right of the anchor. + if (x < 0) { + x = owner_bounds.right() - border_and_shadow_insets.left() + + menu_config.touchable_anchor_offset; + } + // Align the bottom of the menu to the bottom of the anchor. + if (y + pref.height() > state_.monitor_bounds.height()) { + y = owner_bounds.bottom() - pref.height() + + border_and_shadow_insets.bottom(); + } + } else { + if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) + x = owner_bounds.right() - kBubbleTipSizeLeftRight; + else + x = owner_bounds.x() - pref.width() + kBubbleTipSizeLeftRight; + + y = owner_bounds.CenterPoint().y() - pref.height() / 2; + int y_old = y; + if (y < state_.monitor_bounds.y()) + y = state_.monitor_bounds.y(); + else if (y + pref.height() > state_.monitor_bounds.bottom()) + y = state_.monitor_bounds.bottom() - pref.height(); + submenu->GetScrollViewContainer()->SetBubbleArrowOffset( + pref.height() / 2 - y + y_old); } - // Align the bottom of the menu to the bottom of the anchor. - if (y + pref.height() > state_.monitor_bounds.height()) - y = owner_bounds.bottom() - pref.height() + shadow_insets.bottom(); } else { - if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) - x = owner_bounds.right() - kBubbleTipSizeLeftRight; - else - x = owner_bounds.x() - pref.width() + kBubbleTipSizeLeftRight; - - y = owner_bounds.CenterPoint().y() - pref.height() / 2; - int y_old = y; - if (y < state_.monitor_bounds.y()) { - y = state_.monitor_bounds.y(); - } else if (y + pref.height() > state_.monitor_bounds.bottom()) { - y = state_.monitor_bounds.bottom() - pref.height(); + if (!use_touchable_layout_) { + NOTIMPLEMENTED() + << "Nested bubble menus are only implemented for touchable menus."; } - submenu->GetScrollViewContainer()->SetBubbleArrowOffset( - pref.height() / 2 - y + y_old); + + // This is a sub-menu, position it relative to the parent menu. + const gfx::Rect item_bounds = item->GetBoundsInScreen(); + // If the layout is RTL, then a 'leading' menu is positioned to the left of + // the parent menu item and not to the right. + const bool layout_is_rtl = base::i18n::IsRTL(); + const bool create_on_the_right = (prefer_leading && !layout_is_rtl) || + (!prefer_leading && layout_is_rtl); + if (create_on_the_right) { + x = item_bounds.right() - border_and_shadow_insets.left(); + if (state_.monitor_bounds.width() != 0 && + (x + menu_config.touchable_menu_width - + border_and_shadow_insets.right() > + state_.monitor_bounds.right())) { + *is_leading = prefer_leading; + x = item_bounds.x() - menu_config.touchable_menu_width - + border_and_shadow_insets.right(); + } + } else { + x = item_bounds.x() - menu_config.touchable_menu_width - + border_and_shadow_insets.right(); + if (state_.monitor_bounds.width() != 0 && x < state_.monitor_bounds.x()) { + *is_leading = !prefer_leading; + x = item_bounds.x() + menu_config.touchable_menu_width - + border_and_shadow_insets.left(); + } + } + y = item_bounds.y() - border_and_shadow_insets.top() - + menu_config.vertical_touchable_menu_item_padding; + if (y + pref.height() - border_and_shadow_insets.bottom() > + state_.monitor_bounds.bottom()) { + y = state_.monitor_bounds.bottom() - pref.height() + + border_and_shadow_insets.top(); + } + if (y < state_.monitor_bounds.y()) + y = state_.monitor_bounds.y() - border_and_shadow_insets.top(); } return gfx::Rect(x, y, pref.width(), pref.height()); } @@ -2722,7 +2809,8 @@ return; if (part.type == MenuPart::MENU_ITEM && part.menu) { - SetSelection(part.menu, SELECTION_OPEN_SUBMENU); + SetSelection(part.menu, part.should_submenu_show ? SELECTION_OPEN_SUBMENU + : SELECTION_DEFAULT); } else if (!part.is_scroll() && pending_state_.item && pending_state_.item->GetParentMenuItem() && !pending_state_.item->SubmenuIsShowing()) {
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h index b208044..563b4b26 100644 --- a/ui/views/controls/menu/menu_controller.h +++ b/ui/views/controls/menu/menu_controller.h
@@ -294,13 +294,11 @@ SCROLL_DOWN }; - MenuPart() : type(NONE), menu(NULL), parent(NULL), submenu(NULL) {} - // Convenience for testing type == SCROLL_DOWN or type == SCROLL_UP. bool is_scroll() const { return type == SCROLL_DOWN || type == SCROLL_UP; } // Type of part. - Type type; + Type type = NONE; // If type is MENU_ITEM, this is the menu item the mouse is over, otherwise // this is NULL. @@ -308,14 +306,17 @@ // but is over a menu (for example, the mouse is over a separator or // empty menu), this is NULL and parent is the menu the mouse was // clicked on. - MenuItemView* menu; + MenuItemView* menu = nullptr; // If type is MENU_ITEM but the mouse is not over a menu item this is the // parent of the menu item the user clicked on. Otherwise this is NULL. - MenuItemView* parent; + MenuItemView* parent = nullptr; // This is the submenu the mouse is over. - SubmenuView* submenu; + SubmenuView* submenu = nullptr; + + // Whether the controller should apply SELECTION_OPEN_SUBMENU to this item. + bool should_submenu_show = false; }; // Sets the selection to |menu_item|. A value of NULL unselects @@ -419,6 +420,11 @@ bool DoesSubmenuContainLocation(SubmenuView* submenu, const gfx::Point& screen_loc); + // Returns whether the location is over the ACTIONABLE_SUBMENU's submenu area. + bool IsLocationOverSubmenuAreaOfActionableSubmenu( + MenuItemView* item, + const gfx::Point& screen_loc) const; + // Opens/Closes the necessary menus such that state_ matches that of // pending_state_. This is invoked if submenus are not opened immediately, // but after a delay.
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc index 9db91f9..4eb50c9 100644 --- a/ui/views/controls/menu/menu_item_view.cc +++ b/ui/views/controls/menu/menu_item_view.cc
@@ -12,6 +12,7 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/menu_model.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/rect.h" @@ -29,6 +30,7 @@ #include "ui/views/controls/menu/menu_scroll_view_container.h" #include "ui/views/controls/menu/menu_separator.h" #include "ui/views/controls/menu/submenu_view.h" +#include "ui/views/controls/separator.h" #include "ui/views/widget/widget.h" namespace views { @@ -171,6 +173,7 @@ switch (GetType()) { case SUBMENU: + case ACTIONABLE_SUBMENU: node_data->SetHasPopup(ax::mojom::HasPopup::kMenu); break; case CHECKBOX: @@ -267,7 +270,7 @@ item->SetMinorIcon(minor_icon); if (!icon.isNull()) item->SetIcon(icon); - if (type == SUBMENU) + if (type == SUBMENU || type == ACTIONABLE_SUBMENU) item->CreateSubmenu(); if (GetDelegate() && !GetDelegate()->IsCommandVisible(item_id)) item->SetVisible(false); @@ -398,6 +401,19 @@ SchedulePaint(); } +void MenuItemView::SetSelectionOfActionableSubmenu( + bool submenu_area_of_actionable_submenu_selected) { + DCHECK_EQ(ACTIONABLE_SUBMENU, type_); + if (submenu_area_of_actionable_submenu_selected_ == + submenu_area_of_actionable_submenu_selected) { + return; + } + + submenu_area_of_actionable_submenu_selected_ = + submenu_area_of_actionable_submenu_selected; + SchedulePaint(); +} + void MenuItemView::SetTooltip(const base::string16& tooltip, int item_id) { MenuItemView* item = GetMenuItemByID(item_id); DCHECK(item); @@ -458,6 +474,13 @@ return height; } +gfx::Rect MenuItemView::GetSubmenuAreaOfActionableSubmenu() const { + DCHECK_EQ(ACTIONABLE_SUBMENU, type_); + const MenuConfig& config = MenuConfig::instance(); + return gfx::Rect(gfx::Point(vertical_separator_->bounds().right(), 0), + gfx::Size(config.actionable_submenu_width, height())); +} + const MenuItemView::MenuItemDimensions& MenuItemView::GetDimensions() const { if (!is_dimensions_valid()) dimensions_ = CalculateDimensions(); @@ -495,8 +518,10 @@ } base::char16 MenuItemView::GetMnemonic() { - if (!GetRootMenuItem()->has_mnemonics_) + if (!GetRootMenuItem()->has_mnemonics_ || + !MenuConfig::instance().use_mnemonics) { return 0; + } size_t index = 0; do { @@ -580,6 +605,8 @@ continue; if (submenu_arrow_image_view_ == child) continue; + if (vertical_separator_ == child) + continue; int width = child->GetPreferredSize().width(); child->SetBounds(x - width, 0, width, height()); x -= width + kChildXPadding; @@ -611,13 +638,25 @@ } if (submenu_arrow_image_view_) { - int x = width() - config.arrow_width - config.arrow_to_edge_padding; + int x = width() - config.arrow_width - + (type_ == ACTIONABLE_SUBMENU + ? config.actionable_submenu_arrow_to_edge_padding + : config.arrow_to_edge_padding); int y = (height() + GetTopMargin() - GetBottomMargin() - kSubmenuArrowSize) / 2; submenu_arrow_image_view_->SetBounds(x, y, config.arrow_width, kSubmenuArrowSize); } + + if (vertical_separator_) { + const gfx::Size preferred_size = vertical_separator_->GetPreferredSize(); + int x = width() - config.actionable_submenu_width - + config.actionable_submenu_vertical_separator_width; + int y = (height() - preferred_size.height()) / 2; + vertical_separator_->SetBoundsRect( + gfx::Rect(gfx::Point(x, y), preferred_size)); + } } } @@ -705,15 +744,16 @@ MenuItemView::Type type, MenuDelegate* delegate) { delegate_ = delegate; - controller_ = NULL; + controller_ = nullptr; canceled_ = false; parent_menu_item_ = parent; type_ = type; selected_ = false; command_ = command; - submenu_ = NULL; + submenu_ = nullptr; radio_check_image_view_ = nullptr; submenu_arrow_image_view_ = nullptr; + vertical_separator_ = nullptr; show_mnemonics_ = false; // Assign our ID, this allows SubmenuItemView to find MenuItemViews. set_id(kMenuItemViewID); @@ -729,6 +769,20 @@ AddChildView(radio_check_image_view_); } + if (type_ == ACTIONABLE_SUBMENU) { + vertical_separator_ = new Separator(); + vertical_separator_->SetVisible(true); + vertical_separator_->SetFocusBehavior(FocusBehavior::NEVER); + const MenuConfig& config = MenuConfig::instance(); + vertical_separator_->SetColor(GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_ActionableSubmenuVerticalSeparatorColor)); + vertical_separator_->SetPreferredSize( + gfx::Size(config.actionable_submenu_vertical_separator_width, + config.actionable_submenu_vertical_separator_height)); + vertical_separator_->set_can_process_events_within_subtree(false); + AddChildView(vertical_separator_); + } + if (submenu_arrow_image_view_) submenu_arrow_image_view_->SetVisible(HasSubmenu()); @@ -844,6 +898,15 @@ ui::NativeTheme* native_theme = GetNativeTheme(); if (render_selection) { gfx::Rect item_bounds(0, 0, width(), height()); + if (type_ == ACTIONABLE_SUBMENU) { + if (submenu_area_of_actionable_submenu_selected_) { + item_bounds = GetSubmenuAreaOfActionableSubmenu(); + } else { + item_bounds = gfx::Rect(gfx::Size( + width() - MenuConfig::instance().actionable_submenu_width - 1, + height())); + } + } AdjustBoundsForRTLUI(&item_bounds); native_theme->Paint(canvas->sk_canvas(), @@ -962,6 +1025,10 @@ if (!emphasized) color_id = ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor; } + + if (GetMenuController() && GetMenuController()->use_touchable_layout()) + color_id = ui::NativeTheme::kColorId_TouchableMenuItemLabelColor; + return GetNativeTheme()->GetSystemColor(color_id); } @@ -1012,6 +1079,8 @@ continue; if (submenu_arrow_image_view_ == child) continue; + if (vertical_separator_ == child) + continue; if (i) width += kChildXPadding; width += child->GetPreferredSize().width(); @@ -1153,7 +1222,7 @@ // not the number of menu items. return child_count() - (icon_view_ ? 1 : 0) - (radio_check_image_view_ ? 1 : 0) - - (submenu_arrow_image_view_ ? 1 : 0); + (submenu_arrow_image_view_ ? 1 : 0) - (vertical_separator_ ? 1 : 0); } int MenuItemView::GetMaxIconViewWidth() const {
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h index 8037459..6276932 100644 --- a/ui/views/controls/menu/menu_item_view.h +++ b/ui/views/controls/menu/menu_item_view.h
@@ -17,7 +17,6 @@ #include "build/build_config.h" #include "ui/base/models/menu_separator_types.h" #include "ui/gfx/image/image_skia.h" -#include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_controller.h" #include "ui/views/controls/menu/menu_types.h" #include "ui/views/view.h" @@ -45,6 +44,7 @@ class MenuController; class MenuDelegate; +class Separator; class TestMenuItemView; class SubmenuView; @@ -83,15 +83,16 @@ // ID used to identify empty menu items. static const int kEmptyMenuItemViewID; - // Different types of menu items. EMPTY is a special type for empty - // menus that is only used internally. + // Different types of menu items. enum Type { - NORMAL, - SUBMENU, - CHECKBOX, - RADIO, - SEPARATOR, - EMPTY + NORMAL, // Performs an action when selected. + SUBMENU, // Presents a submenu within another menu. + ACTIONABLE_SUBMENU, // A SUBMENU that is also a COMMAND. + CHECKBOX, // Can be selected/checked to toggle a boolean state. + RADIO, // Can be selected/checked among a group of choices. + SEPARATOR, // Shows a horizontal line separator. + EMPTY, // EMPTY is a special type for empty menus that is only used + // internally. }; // Where the menu should be drawn, above or below the bounds (when @@ -257,6 +258,15 @@ // Returns true if the item is selected. bool IsSelected() const { return selected_; } + // Sets whether the submenu area of an ACTIONABLE_SUBMENU is selected. + void SetSelectionOfActionableSubmenu( + bool submenu_area_of_actionable_submenu_selected); + + // Whether the submenu area of an ACTIONABLE_SUBMENU is selected. + bool IsSubmenuAreaOfActionableSubmenuSelected() const { + return submenu_area_of_actionable_submenu_selected_; + } + // Sets the |tooltip| for a menu item view with |item_id| identifier. void SetTooltip(const base::string16& tooltip, int item_id); @@ -288,6 +298,9 @@ // dimensions. int GetHeightForWidth(int width) const override; + // Returns the bounds of the submenu part of the ACTIONABLE_SUBMENU. + gfx::Rect GetSubmenuAreaOfActionableSubmenu() const; + // Return the preferred dimensions of the item in pixel. const MenuItemDimensions& GetDimensions() const; @@ -492,6 +505,9 @@ // Whether we're selected. bool selected_; + // Whether the submenu area of an ACTIONABLE_SUBMENU is selected. + bool submenu_area_of_actionable_submenu_selected_; + // Command id. int command_; @@ -573,6 +589,10 @@ // The forced visual selection state of this item, if any. base::Optional<bool> forced_visual_selection_; + // The vertical separator that separates the actionable and submenu regions of + // an ACTIONABLE_SUBMENU. + Separator* vertical_separator_; + DISALLOW_COPY_AND_ASSIGN(MenuItemView); };
diff --git a/ui/views/controls/menu/menu_item_view_unittest.cc b/ui/views/controls/menu/menu_item_view_unittest.cc index 9170ded6..07273f5d 100644 --- a/ui/views/controls/menu/menu_item_view_unittest.cc +++ b/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -41,6 +41,8 @@ void AddEmptyMenus() { MenuItemView::AddEmptyMenus(); } + void SetHasMnemonics(bool has_mnemonics) { has_mnemonics_ = has_mnemonics; } + private: DISALLOW_COPY_AND_ASSIGN(TestMenuItemView); }; @@ -146,6 +148,24 @@ empty_item->title()); } +TEST(MenuItemViewUnitTest, UseMnemonicOnPlatform) { + TestMenuItemView root_menu; + views::MenuItemView* item1 = + root_menu.AppendMenuItemWithLabel(1, base::ASCIIToUTF16("&Item 1")); + views::MenuItemView* item2 = + root_menu.AppendMenuItemWithLabel(2, base::ASCIIToUTF16("I&tem 2")); + + root_menu.SetHasMnemonics(true); + + if (MenuConfig::instance().use_mnemonics) { + EXPECT_EQ('i', item1->GetMnemonic()); + EXPECT_EQ('t', item2->GetMnemonic()); + } else { + EXPECT_EQ(0, item1->GetMnemonic()); + EXPECT_EQ(0, item2->GetMnemonic()); + } +} + class MenuItemViewPaintUnitTest : public ViewsTestBase { public: MenuItemViewPaintUnitTest() {}
diff --git a/ui/views/controls/menu/menu_model_adapter.cc b/ui/views/controls/menu/menu_model_adapter.cc index e1a2339..e9cfe1c 100644 --- a/ui/views/controls/menu/menu_model_adapter.cc +++ b/ui/views/controls/menu/menu_model_adapter.cc
@@ -80,6 +80,9 @@ case ui::MenuModel::TYPE_SUBMENU: type = MenuItemView::SUBMENU; break; + case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU: + type = MenuItemView::ACTIONABLE_SUBMENU; + break; } if (*type == MenuItemView::SEPARATOR) { @@ -267,9 +270,11 @@ for (int i = 0; i < item_count; ++i) { MenuItemView* item = AppendMenuItem(menu, model, i); - if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) { + if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU || + model->GetTypeAt(i) == ui::MenuModel::TYPE_ACTIONABLE_SUBMENU) { DCHECK(item); - DCHECK_EQ(MenuItemView::SUBMENU, item->GetType()); + DCHECK(item->GetType() == MenuItemView::SUBMENU || + item->GetType() == MenuItemView::ACTIONABLE_SUBMENU); ui::MenuModel* submodel = model->GetSubmenuModelAt(i); DCHECK(submodel); BuildMenuImpl(item, submodel);
diff --git a/ui/views/controls/menu/menu_model_adapter_unittest.cc b/ui/views/controls/menu/menu_model_adapter_unittest.cc index c5df954..df3bb3e 100644 --- a/ui/views/controls/menu/menu_model_adapter_unittest.cc +++ b/ui/views/controls/menu/menu_model_adapter_unittest.cc
@@ -16,8 +16,9 @@ namespace { // Base command id for test menu and its submenu. -const int kRootIdBase = 100; -const int kSubmenuIdBase = 200; +constexpr int kRootIdBase = 100; +constexpr int kSubmenuIdBase = 200; +constexpr int kActionableSubmenuIdBase = 300; class MenuModelBase : public ui::MenuModel { public: @@ -139,26 +140,98 @@ DISALLOW_COPY_AND_ASSIGN(SubmenuModel); }; +class ActionableSubmenuModel : public MenuModelBase { + public: + ActionableSubmenuModel() : MenuModelBase(kActionableSubmenuIdBase) { + items_.push_back(Item(TYPE_COMMAND, "actionable submenu item 0", NULL)); + items_.push_back(Item(TYPE_COMMAND, "actionable submenu item 1", NULL)); + } + ~ActionableSubmenuModel() override = default; + + private: + DISALLOW_COPY_AND_ASSIGN(ActionableSubmenuModel); +}; + class RootModel : public MenuModelBase { public: RootModel() : MenuModelBase(kRootIdBase) { - submenu_model_.reset(new SubmenuModel); + submenu_model_ = std::make_unique<SubmenuModel>(); + actionable_submenu_model_ = std::make_unique<ActionableSubmenuModel>(); items_.push_back(Item(TYPE_COMMAND, "command 0", NULL)); items_.push_back(Item(TYPE_CHECK, "check 1", NULL)); items_.push_back(Item(TYPE_SEPARATOR, "", NULL)); items_.push_back(Item(TYPE_SUBMENU, "submenu 3", submenu_model_.get())); items_.push_back(Item(TYPE_RADIO, "radio 4", NULL)); + items_.push_back(Item(TYPE_ACTIONABLE_SUBMENU, "actionable 5", + actionable_submenu_model_.get())); } ~RootModel() override {} private: std::unique_ptr<MenuModel> submenu_model_; + std::unique_ptr<MenuModel> actionable_submenu_model_; DISALLOW_COPY_AND_ASSIGN(RootModel); }; +void CheckSubmenu(const RootModel& model, + views::MenuItemView* menu, + views::MenuModelAdapter* delegate, + int submenu_id, + int expected_children, + int submenu_model_index, + int id_base) { + views::MenuItemView* submenu = menu->GetMenuItemByID(submenu_id); + views::SubmenuView* subitem_container = submenu->GetSubmenu(); + EXPECT_EQ(expected_children, subitem_container->child_count()); + + for (int i = 0; i < subitem_container->child_count(); ++i) { + MenuModelBase* submodel = static_cast<MenuModelBase*>( + model.GetSubmenuModelAt(submenu_model_index)); + EXPECT_TRUE(submodel); + + const MenuModelBase::Item& model_item = submodel->GetItemDefinition(i); + + const int id = i + id_base; + views::MenuItemView* item = menu->GetMenuItemByID(id); + if (!item) { + EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type); + continue; + } + // Check placement. + EXPECT_EQ(i, submenu->GetSubmenu()->GetIndexOf(item)); + + // Check type. + switch (model_item.type) { + case ui::MenuModel::TYPE_COMMAND: + EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType()); + break; + case ui::MenuModel::TYPE_CHECK: + EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType()); + break; + case ui::MenuModel::TYPE_RADIO: + EXPECT_EQ(views::MenuItemView::RADIO, item->GetType()); + break; + case ui::MenuModel::TYPE_SEPARATOR: + case ui::MenuModel::TYPE_BUTTON_ITEM: + break; + case ui::MenuModel::TYPE_SUBMENU: + EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType()); + break; + case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU: + EXPECT_EQ(views::MenuItemView::ACTIONABLE_SUBMENU, item->GetType()); + break; + } + + // Check activation. + static_cast<views::MenuDelegate*>(delegate)->ExecuteCommand(id); + EXPECT_EQ(i, submodel->last_activation()); + submodel->set_last_activation(-1); + } +} + } // namespace namespace views { @@ -180,7 +253,7 @@ // Check top level menu items. views::SubmenuView* item_container = menu->GetSubmenu(); - EXPECT_EQ(5, item_container->child_count()); + EXPECT_EQ(6, item_container->child_count()); for (int i = 0; i < item_container->child_count(); ++i) { const MenuModelBase::Item& model_item = model.GetItemDefinition(i); @@ -212,6 +285,9 @@ case ui::MenuModel::TYPE_SUBMENU: EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType()); break; + case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU: + EXPECT_EQ(views::MenuItemView::ACTIONABLE_SUBMENU, item->GetType()); + break; } // Check activation. @@ -220,52 +296,15 @@ model.set_last_activation(-1); } - // Check submenu items. - views::MenuItemView* submenu = menu->GetMenuItemByID(103); - views::SubmenuView* subitem_container = submenu->GetSubmenu(); - EXPECT_EQ(2, subitem_container->child_count()); + // Check the submenu. + const int submenu_index = 3; + CheckSubmenu(model, menu, &delegate, kRootIdBase + submenu_index, 2, + submenu_index, kSubmenuIdBase); - for (int i = 0; i < subitem_container->child_count(); ++i) { - MenuModelBase* submodel = static_cast<MenuModelBase*>( - model.GetSubmenuModelAt(3)); - EXPECT_TRUE(submodel); - - const MenuModelBase::Item& model_item = submodel->GetItemDefinition(i); - - const int id = i + kSubmenuIdBase; - MenuItemView* item = menu->GetMenuItemByID(id); - if (!item) { - EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model_item.type); - continue; - } - - // Check placement. - EXPECT_EQ(i, submenu->GetSubmenu()->GetIndexOf(item)); - - // Check type. - switch (model_item.type) { - case ui::MenuModel::TYPE_COMMAND: - EXPECT_EQ(views::MenuItemView::NORMAL, item->GetType()); - break; - case ui::MenuModel::TYPE_CHECK: - EXPECT_EQ(views::MenuItemView::CHECKBOX, item->GetType()); - break; - case ui::MenuModel::TYPE_RADIO: - EXPECT_EQ(views::MenuItemView::RADIO, item->GetType()); - break; - case ui::MenuModel::TYPE_SEPARATOR: - case ui::MenuModel::TYPE_BUTTON_ITEM: - break; - case ui::MenuModel::TYPE_SUBMENU: - EXPECT_EQ(views::MenuItemView::SUBMENU, item->GetType()); - break; - } - - // Check activation. - static_cast<views::MenuDelegate*>(&delegate)->ExecuteCommand(id); - EXPECT_EQ(i, submodel->last_activation()); - submodel->set_last_activation(-1); - } + // Check the actionable submenu. + const int actionable_submenu_index = 5; + CheckSubmenu(model, menu, &delegate, kRootIdBase + actionable_submenu_index, + 2, actionable_submenu_index, kActionableSubmenuIdBase); // Check that selecting the root item is safe. The MenuModel does // not care about the root so MenuModelAdapter should do nothing
diff --git a/ui/views/controls/menu/menu_types.h b/ui/views/controls/menu/menu_types.h index d95ce0b..03a0c72 100644 --- a/ui/views/controls/menu/menu_types.h +++ b/ui/views/controls/menu/menu_types.h
@@ -9,8 +9,7 @@ // Where a popup menu should be anchored to for non-RTL languages. The opposite // position will be used if base::i18n:IsRTL() is true. The BUBBLE flags are -// used when the menu should get enclosed by a bubble. Note that BUBBLE flags -// should only be used with menus which have no children. The Fixed flags are +// used when the menu should get enclosed by a bubble. The Fixed flags are // used for the menus that have a fixed anchor position. enum MenuAnchorPosition { MENU_ANCHOR_TOPLEFT,
diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc index 9b244c9..b69a318 100644 --- a/ui/views/controls/menu/submenu_view.cc +++ b/ui/views/controls/menu/submenu_view.cc
@@ -182,8 +182,9 @@ minimum_preferred_width_ - 2 * insets.width())); if (GetMenuItem()->GetMenuController() && - GetMenuItem()->GetMenuController()->use_touchable_layout()) + GetMenuItem()->GetMenuController()->use_touchable_layout()) { width = std::max(touchable_minimum_width, width); + } // Then, the height for that width. int height = 0;
diff --git a/ui/views/controls/views_text_services_context_menu_mac.mm b/ui/views/controls/views_text_services_context_menu_mac.mm index 0c4cd26..81015952 100644 --- a/ui/views/controls/views_text_services_context_menu_mac.mm +++ b/ui/views/controls/views_text_services_context_menu_mac.mm
@@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "ui/base/cocoa/text_services_context_menu.h" +#include "ui/base/emoji/emoji_panel_helper.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" @@ -43,7 +44,9 @@ l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_LOOK_UP, text)); menu->InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR); } - if (base::FeatureList::IsEnabled(features::kEnableEmojiContextMenu)) { + // TODO(crbug.com/827404): Move this to the cross-platform context menu + // code. + if (ui::IsEmojiPanelSupported()) { menu->InsertItemWithStringIdAt(index++, IDS_CONTENT_CONTEXT_EMOJI, IDS_CONTENT_CONTEXT_EMOJI); menu->InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR); @@ -85,7 +88,7 @@ void ExecuteCommand(int command_id) override { switch (command_id) { case IDS_CONTENT_CONTEXT_EMOJI: - [NSApp orderFrontCharacterPalette:nil]; + ui::ShowEmojiPanel(); break; case IDS_CONTENT_CONTEXT_LOOK_UP:
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc index 270d1f5f..ae12a5a 100644 --- a/ui/views/mus/desktop_window_tree_host_mus.cc +++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -698,7 +698,9 @@ return false; } -void DesktopWindowTreeHostMus::FrameTypeChanged() {} +void DesktopWindowTreeHostMus::FrameTypeChanged() { + native_widget_delegate_->AsWidget()->ThemeChanged(); +} void DesktopWindowTreeHostMus::SetFullscreen(bool fullscreen) { if (IsFullscreen() == fullscreen)
diff --git a/ui/views/style/typography_provider.cc b/ui/views/style/typography_provider.cc index a66e387..e208380 100644 --- a/ui/views/style/typography_provider.cc +++ b/ui/views/style/typography_provider.cc
@@ -37,12 +37,11 @@ gfx::Font::Weight TypographyProvider::MediumWeightForUI() { #if defined(OS_MACOSX) // System fonts are not user-configurable on Mac, so there's a simpler check. - // However, 10.9 and 10.11 do not ship with a MEDIUM weight system font. In - // that case, trying to use MEDIUM there will give a bold font, which will - // look worse with the surrounding NORMAL text than just using NORMAL. - return (base::mac::IsOS10_9() || base::mac::IsOS10_11()) - ? gfx::Font::Weight::NORMAL - : gfx::Font::Weight::MEDIUM; + // However, 10.11 do not ship with a MEDIUM weight system font. In that + // case, trying to use MEDIUM there will give a bold font, which will look + // worse with the surrounding NORMAL text than just using NORMAL. + return base::mac::IsOS10_11() ? gfx::Font::Weight::NORMAL + : gfx::Font::Weight::MEDIUM; #else // NORMAL may already have at least MEDIUM weight. Return NORMAL in that case // since trying to return MEDIUM would actually make the font lighter-weight
diff --git a/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html b/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html index 388faf5d..6483cef 100644 --- a/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html +++ b/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html
@@ -1,23 +1,18 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_checkbox_style_css.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <link rel="import" href="certificate_shared_css.html"> <link rel="import" href="certificates_browser_proxy.html"> <dom-module id="ca-trust-edit-dialog"> <template> - <style include="certificate-shared paper-button-style paper-checkbox-style"> - paper-checkbox { - display: block; - } - - paper-checkbox, + <style include="certificate-shared paper-button-style"> + cr-checkbox, #description { margin: 15px 0; } @@ -32,15 +27,15 @@ <div id="description"> [[i18n('certificateManagerCaTrustEditDialogDescription')]] </div> - <paper-checkbox id="ssl" checked="[[trustInfo_.ssl]]"> + <cr-checkbox id="ssl" checked="[[trustInfo_.ssl]]"> [[i18n('certificateManagerCaTrustEditDialogSsl')]] - </paper-checkbox> - <paper-checkbox id="email" checked="[[trustInfo_.email]]"> + </cr-checkbox> + <cr-checkbox id="email" checked="[[trustInfo_.email]]"> [[i18n('certificateManagerCaTrustEditDialogEmail')]] - </paper-checkbox> - <paper-checkbox id="objSign" checked="[[trustInfo_.objSign]]"> + </cr-checkbox> + <cr-checkbox id="objSign" checked="[[trustInfo_.objSign]]"> [[i18n('certificateManagerCaTrustEditDialogObjSign')]] - </paper-checkbox> + </cr-checkbox> </div> <div slot="button-container"> <paper-spinner-lite id="spinner"></paper-spinner-lite>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html b/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html index 1a2c716e..b9a8be8 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> @@ -9,7 +10,7 @@ <dom-module id="network-apnlist"> <template> - <style include="network-shared md-select"> + <style include="network-shared md-select paper-button-style"> paper-button { margin: 4px 0; }
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_choose_mobile.html b/ui/webui/resources/cr_components/chromeos/network/network_choose_mobile.html index 24afaea..41b6085 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_choose_mobile.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_choose_mobile.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> @@ -9,13 +10,7 @@ <dom-module id="network-choose-mobile"> <template> - <style include="network-shared md-select iron-flex"> - paper-button { - margin: 0; - } - paper-button[disabled] { - background: none; - } + <style include="network-shared md-select iron-flex paper-button-style"> /* Align select with button and scan messages */ select { margin-top: 4px;
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html index 2ed533d..e579ea8 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
@@ -30,9 +30,11 @@ <div class="control-box"> <paper-input-container always-float-label> <label id="label" slot="label">[[label]]</label> - <input is="iron-input" value="{{value::input}}" slot="input" - tabindex="1" disabled="[[disabled]]" aria-label$="[[label]]" - type="[[getInputType_(password, showPassword)]]"> + <iron-input slot="input"> + <input value="{{value::input}}" tabindex="1" disabled="[[disabled]]" + aria-label$="[[label]]" + type="[[getInputType_(password, showPassword)]]"> + </iron-input> </paper-input-container> <div id="iconDiv"> <template is="dom-if" if="[[password]]">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html b/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html index 4caf352..a62966a 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html
@@ -88,9 +88,11 @@ <div class="property-box single-column two-line"> <template is="dom-repeat" items="[[nameservers_]]"> <paper-input-container no-label-float> - <input id="nameserver[[index]]" is="iron-input" value="[[item]]" - disabled="[[!canEdit_(editable, nameserversType_)]]" - on-change="onValueChange_" slot="input"> + <iron-input slot="input"> + <input id="nameserver[[index]]" value="[[item]]" + disabled="[[!canEdit_(editable, nameserversType_)]]" + on-change="onValueChange_"> + </iron-input> </paper-input-container> </template> </div>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_property_list.html b/ui/webui/resources/cr_components/chromeos/network/network_property_list.html index dab56078..e24bb7f 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_property_list.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_property_list.html
@@ -49,10 +49,12 @@ <template is="dom-if" restamp if="[[isEditTypeInput_(item, propertyDict, editFieldTypes)]]"> <paper-input-container no-label-float> - <input id="[[item]]" is="iron-input" slot="input" - type="[[getEditInputType_(item, editFieldTypes)]]" - value="[[getPropertyValue_(item, prefix, propertyDict)]]" - on-change="onValueChange_"> + <iron-input slot="input"> + <input id="[[item]]" + type="[[getEditInputType_(item, editFieldTypes)]]" + value="[[getPropertyValue_(item, prefix, propertyDict)]]" + on-change="onValueChange_"> + </iron-input> </paper-input-container> </template> <!-- TODO(stevenjb): Support other types (number, boolean)? -->
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy.html b/ui/webui/resources/cr_components/chromeos/network/network_proxy.html index 1834e1db..5640402 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_proxy.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy.html
@@ -130,7 +130,9 @@ </network-proxy-exclusions> <div class="layout horizontal"> <paper-input-container no-label-float class="flex"> - <input id="proxyExclusion" is="iron-input" slot="input"> + <iron-input slot="input"> + <input id="proxyExclusion"> + </iron-input> <iron-a11y-keys keys="enter" slot="add-on" on-keys-pressed="onAddProxyExclusionTap_"> </iron-a11y-keys>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html index 940a943..188a8ef 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
@@ -35,14 +35,18 @@ </style> <div id="container"> <div id="label">[[label]]</div> - <paper-input-container id="host" no-label-float> - <input is="iron-input" bind-value="{{value.Host}}" slot="input" - disabled="[[!editable]]" on-change="onValueChange_"> + <paper-input-container id="host" no-label-float disabled$="[[!editable]]"> + <iron-input slot="input"> + <input value="{{value.Host}}" disabled$="[[!editable]]" + on-change="onValueChange_"> + </iron-input> </paper-input-container> <div>[[i18n('networkProxyPort')]]</div> - <paper-input-container id="port" no-label-float> - <input is="iron-input" bind-value="{{value.Port}}" slot="input" - disabled="[[!editable]]" on-change="onValueChange_"> + <paper-input-container id="port" no-label-float disabled$="[[!editable]]"> + <iron-input slot="input"> + <input value="{{value.Port}}" disabled$="[[!editable]]" + on-change="onValueChange_"> + </iron-input> </paper-input-container> </div> </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html b/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html index 7c2deb9..6377caca 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
@@ -1,11 +1,10 @@ <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> -<link rel="import" href="chrome://resources/html/md_select_css.html"> <!-- Common styles for network elements. --> <dom-module id="network-shared"> <template> - <style include="cr-shared-style md-select"> + <style include="cr-shared-style"> :root { /* Margin for the show/hide password icon */ --network-control-margin: 40px; @@ -71,6 +70,10 @@ margin-bottom: 0; margin-top: -9px; } + + iron-input input { + @apply --paper-input-container-shared-input-style; + } </style> </template> </dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html index 0cff8dd8..57cc81e 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> @@ -16,7 +17,7 @@ <dom-module id="network-siminfo"> <template> - <style include="network-shared iron-flex"> + <style include="network-shared iron-flex paper-button-style"> :host { cursor: default } @@ -132,7 +133,8 @@ </div> </div> <div slot="button-container"> - <paper-button on-tap="sendChangePin_" disabled="[[inProgress_]]"> + <paper-button class="action-button" on-tap="sendChangePin_" + disabled="[[inProgress_]]"> [[i18n('networkSimChange')]] </paper-button> </div>
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html index 5e069a548..03b2358 100644 --- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html +++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
@@ -172,7 +172,7 @@ <div id="root" on-contextmenu="onContextMenu_" on-tap="focusInput_"> <div id="pinInputDiv" class="row"> <paper-input id="pinInput" type="password" no-label-float - value="[[value]]" + value="{{value}}" is-input-rtl$="[[isInputRtl_(value)]]" has-content$="[[hasInput_(value)]]" label="[[getInputPlaceholder_(enablePassword)]]"
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js index 8ffadaa..66f79182 100644 --- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js +++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
@@ -71,13 +71,7 @@ * @type {?Element} * @private */ - passwordElement: { - type: Object, - value: function() { - return this.$.pinInput.inputElement; - }, - observer: 'onPasswordElementAttached_', - }, + passwordElement: Object, /** * The intervalID used for the backspace button set/clear interval. @@ -98,15 +92,6 @@ }, /** - * Whether or not to show the default pin input. - * @private - */ - showPinInput_: { - type: Boolean, - value: false, - }, - - /** * The value stored in the keyboard's input element. * @private */ @@ -119,32 +104,12 @@ }, /** - * Called when a password element is attached to the pin keyboard. - * @param {HTMLInputElement} inputElement The PIN keyboard's input element. - * @private - */ - onPasswordElementAttached_: function(inputElement) { - this.showPinInput_ = inputElement == this.$.pinInput.inputElement; - inputElement.addEventListener('input', this.handleInputChanged_.bind(this)); - }, - - /** - * Called when the user uses the keyboard to enter a value into the input - * element. - * @param {Event} event The event object. - * @private - */ - handleInputChanged_: function(event) { - this.value = event.target.value; - }, - - /** * Gets the selection start of the input field. * @type {number} * @private */ get selectionStart_() { - return this.passwordElement.selectionStart; + return this.passwordElement_().selectionStart; }, /** @@ -153,7 +118,7 @@ * @private */ get selectionEnd_() { - return this.passwordElement.selectionEnd; + return this.passwordElement_().selectionEnd; }, /** @@ -162,7 +127,7 @@ * @private */ set selectionStart_(start) { - this.passwordElement.selectionStart = start; + this.passwordElement_().selectionStart = start; }, /** @@ -171,14 +136,14 @@ * @private */ set selectionEnd_(end) { - this.passwordElement.selectionEnd = end; + this.passwordElement_().selectionEnd = end; }, /** * Transfers blur to the input element. */ blur: function() { - this.passwordElement.blur(); + this.passwordElement_().blur(); }, /** @@ -190,7 +155,7 @@ */ focus: function(opt_selectionStart, opt_selectionEnd) { setTimeout(function() { - this.passwordElement.focus(); + this.passwordElement_().focus(); this.selectionStart_ = opt_selectionStart || 0; this.selectionEnd_ = opt_selectionEnd || 0; }.bind(this), 0); @@ -242,10 +207,9 @@ * @param {string} previous */ onPinValueChange_: function(value, previous) { - if (value != previous) { - this.passwordElement.value = this.value; - this.fire('pin-change', {pin: value}); - } + if (this.passwordElement) + this.passwordElement.value = value; + this.fire('pin-change', {pin: value}); }, /** @@ -423,5 +387,15 @@ e.preventDefault(); e.stopPropagation(); }, + + /** + * @return {!HTMLElement} Returns the native input element of |pinInput|. + * @private + */ + passwordElement_: function() { + // |passwordElement| is null by default. It can be set to override the + // input field that will be populated with the keypad. + return this.passwordElement || this.$.pinInput.inputElement.inputElement; + }, }); })();
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html index ef6cca6b2..3d74601 100644 --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html
@@ -43,7 +43,7 @@ } :host ::slotted(.dropdown-item[disabled]) { - opacity: 0.65; + opacity: var(--cr-action-menu-disabled-item-opacity, 0.65); } :host ::slotted(.dropdown-item:not([disabled])) {
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html index be77b46..c1d83b1 100644 --- a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html +++ b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html
@@ -3,7 +3,19 @@ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> +<!-- +List of customizable styles: + --cr-checkbox-border-size + --cr-checkbox-checked-box-color + --cr-checkbox-label-container (CSS mixin) + --cr-checkbox-mark-color + --cr-checkbox-ripple-checked-color + --cr-checkbox-ripple-size + --cr-checkbox-ripple-unchecked-color + --cr-checkbox-size + --cr-checkbox-unchecked-box-color +--> <dom-module id="cr-checkbox"> <template> <style> @@ -14,6 +26,12 @@ display: flex; outline: none; user-select: none; + + --cr-checkbox-size: 16px; + --cr-checkbox-border-size: 2px; + --cr-checkbox-ripple-size: 40px; + --cr-checkbox-ripple-offset: calc(var(--cr-checkbox-size)/2 - + var(--cr-checkbox-ripple-size)/2 - var(--cr-checkbox-border-size)); } :host([disabled]) { @@ -24,48 +42,46 @@ #checkbox { background: none; - border: none; + border: var(--cr-checkbox-border-size) solid + var(--cr-checkbox-unchecked-box-color, var(--google-grey-700)); + border-radius: 2px; + box-sizing: border-box; cursor: pointer; - height: 16px; + display: block; + flex-shrink: 0; + height: var(--cr-checkbox-size); margin: 0; outline: none; padding: 0; position: relative; transform: none; /* Checkboxes shouldn't flip even in RTL. */ - width: 16px; + width: var(--cr-checkbox-size); } #checkmark { - border: 2px solid var(--google-grey-700); - border-radius: 2px; - display: block; - height: 12px; - width: 12px; - } - - #checkmark::after { - border-color: inherit; + border-color: var(--cr-checkbox-mark-color, white); border-style: solid; border-width: 0 2px 2px 0; content: ''; display: block; height: 70%; transform: scale(0) rotate(45deg); - transform-origin: 97% 86%; + transform-origin: 100% 85%; width: 36%; } - :host-context([dir='rtl']) #checkmark::after { + :host-context([dir='rtl']) #checkmark { transform-origin: 50% 14%; } - :host([checked]) #checkmark { - background: var(--google-blue-600); - border-color: var(--google-blue-600); + :host([checked]) #checkbox { + background: var(--cr-checkbox-checked-box-color, + var(--google-blue-600)); + border-color: var(--cr-checkbox-checked-box-color, + var(--google-blue-600)); } - :host([checked]) #checkmark::after { - border-color: white; + :host([checked]) #checkmark { transform: scale(1) rotate(45deg); /* Only animate when showing checkmark. */ transition: transform 140ms ease-out; @@ -73,26 +89,29 @@ paper-ripple { --paper-ripple-opacity: 0.1; - color: var(--google-grey-900); - height: 40px; - left: -12px; + color: var(--cr-checkbox-ripple-unchecked-color, var(--google-grey-900)); + height: var(--cr-checkbox-ripple-size); + left: var(--cr-checkbox-ripple-offset); pointer-events: none; - top: -12px; + top: var(--cr-checkbox-ripple-offset); transition: color linear 80ms; - width: 40px; + width: var(--cr-checkbox-ripple-size); } :host([checked]) paper-ripple { - color: var(--google-blue-600); + color: var(--cr-checkbox-ripple-checked-color, var(--google-blue-600)); } :host-context([dir=rtl]) paper-ripple { left: auto; - right: -12px; + right: var(--cr-checkbox-ripple-offset); } #label-container { -webkit-padding-start: 20px; + white-space: normal; + + @apply --cr-checkbox-label-container; } :host(.no-label) #label-container {
diff --git a/ui/webui/resources/cr_elements/paper_checkbox_style_css.html b/ui/webui/resources/cr_elements/paper_checkbox_style_css.html deleted file mode 100644 index 6aab514..0000000 --- a/ui/webui/resources/cr_elements/paper_checkbox_style_css.html +++ /dev/null
@@ -1,19 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<!-- Common paper-checkbox styling for Material Design WebUI. --> -<dom-module id="paper-checkbox-style"> - <template> - <style> - paper-checkbox { - --paper-checkbox-checked-color: var(--google-blue-500); - --paper-checkbox-ink-size: 40px; - --paper-checkbox-label-color: inherit; - --paper-checkbox-label-spacing: 20px; - --paper-checkbox-size: 16px; - --paper-checkbox-unchecked-color: var(--paper-grey-600); - -webkit-margin-start: 2px; - } - </style> - </template> -</dom-module> -
diff --git a/ui/webui/resources/cr_elements/paper_input_style_css.html b/ui/webui/resources/cr_elements/paper_input_style_css.html index 60009fd7..4ea1c98 100644 --- a/ui/webui/resources/cr_elements/paper_input_style_css.html +++ b/ui/webui/resources/cr_elements/paper_input_style_css.html
@@ -1,7 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<!-- Common paper-checkbox styling for Material Design WebUI. --> +<!-- Common paper-input styling for Material Design WebUI. --> <dom-module id="paper-input-style"> <template> <style>
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp index 21aadf1..c03e4894 100644 --- a/ui/webui/resources/cr_elements_resources.grdp +++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -280,10 +280,6 @@ file="../../webui/resources/cr_elements/paper_button_style_css.html" type="chrome_html" compress="gzip" /> - <structure name="IDR_CR_ELEMENTS_PAPER_CHECKBOX_STYLE_CSS_HTML" - file="../../webui/resources/cr_elements/paper_checkbox_style_css.html" - type="chrome_html" - compress="gzip" /> <structure name="IDR_CR_ELEMENTS_PAPER_INPUT_STYLE_CSS_HTML" file="../../webui/resources/cr_elements/paper_input_style_css.html" type="chrome_html"