diff --git a/DEPS b/DEPS index 247bffe..2fc9664d 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # 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': '64c745349ec8e447722ec903aad31e7380cbcfc9', + 'v8_revision': '549f42837de0b6b0383f3c2522737ced60657a0b', # 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.
diff --git a/ash/login/ui/login_pin_view.cc b/ash/login/ui/login_pin_view.cc index e8f63118c..393c9749 100644 --- a/ash/login/ui/login_pin_view.cc +++ b/ash/login/ui/login_pin_view.cc
@@ -7,6 +7,7 @@ #include "ash/ash_constants.h" #include "ash/resources/vector_icons/vector_icons.h" #include "base/callback.h" +#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
diff --git a/ash/perftests/ash_background_filter_blur_perftest.cc b/ash/perftests/ash_background_filter_blur_perftest.cc index 0fc05d64..ee2c93f 100644 --- a/ash/perftests/ash_background_filter_blur_perftest.cc +++ b/ash/perftests/ash_background_filter_blur_perftest.cc
@@ -4,6 +4,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "base/memory/ptr_util.h" #include "cc/base/lap_timer.h" #include "testing/perf/perf_test.h" #include "ui/aura/window.h"
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 4e8bc32..f6e34741 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -888,12 +888,15 @@ // The callback need to be called at least once even if there is no events // to let the caller know the completion of flush. scoped_refptr<RefCountedString> json_events_str_ptr = new RefCountedString(); + const size_t kReserveCapacity = kTraceEventBufferSizeInBytes * 5 / 4; + json_events_str_ptr->data().reserve(kReserveCapacity); while (const TraceBufferChunk* chunk = logged_events->NextChunk()) { for (size_t j = 0; j < chunk->size(); ++j) { size_t size = json_events_str_ptr->size(); if (size > kTraceEventBufferSizeInBytes) { flush_output_callback.Run(json_events_str_ptr, true); json_events_str_ptr = new RefCountedString(); + json_events_str_ptr->data().reserve(kReserveCapacity); } else if (size) { json_events_str_ptr->data().append(",\n"); }
diff --git a/build/config/jumbo.gni b/build/config/jumbo.gni index a16795a..a3f374e 100644 --- a/build/config/jumbo.gni +++ b/build/config/jumbo.gni
@@ -25,8 +25,9 @@ jumbo_file_merge_limit = 200 } -# Use one of the targets jumbo_target or jumbo_component to generate a -# target which merges sources if possible to compile much faster. +# Use one of the targets jumbo_source_set, jumbo_static_library, +# jumbo_split_static_library or jumbo_component to generate a target +# which merges sources if possible to compile much faster. # # Special values. # @@ -178,13 +179,44 @@ } # See documentation above by "internal_jumbo_target". -template("jumbo_target") { +template("jumbo_source_set") { internal_jumbo_target(target_name) { + target_type = "source_set" forward_variables_from(invoker, "*") } } -set_defaults("jumbo_target") { +set_defaults("jumbo_source_set") { + # This sets the default list of configs when the content_source_set target + # is defined. The default_compiler_configs comes from BUILDCONFIG.gn and + # is the list normally applied to static libraries and source sets. + configs = default_compiler_configs +} + +# See documentation above by "internal_jumbo_target". +template("jumbo_static_library") { + internal_jumbo_target(target_name) { + target_type = "static_library" + forward_variables_from(invoker, "*") + } +} + +set_defaults("jumbo_static_library") { + # This sets the default list of configs when the content_source_set target + # is defined. The default_compiler_configs comes from BUILDCONFIG.gn and + # is the list normally applied to static libraries and source sets. + configs = default_compiler_configs +} + +# See documentation above by "internal_jumbo_target". +template("jumbo_split_static_library") { + internal_jumbo_target(target_name) { + target_type = "split_static_library" + forward_variables_from(invoker, "*") + } +} + +set_defaults("jumbo_split_static_library") { # This sets the default list of configs when the content_source_set target # is defined. The default_compiler_configs comes from BUILDCONFIG.gn and # is the list normally applied to static libraries and source sets. @@ -194,6 +226,7 @@ # See documentation above by "internal_jumbo_target". template("jumbo_component") { internal_jumbo_target(target_name) { + target_type = "component" forward_variables_from(invoker, "*") } }
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni index 9ce2ad9..62b2561 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni
@@ -64,7 +64,12 @@ declare_args() { if (is_clang) { # Clang compiler version. Clang files are placed at version-dependent paths. - clang_version = "5.0.0" + if (llvm_force_head_revision) { + clang_version = "6.0.0" + } else { + # TODO(hans): Trunk was updated; remove after the next roll. + clang_version = "5.0.0" + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java index 29111c90..498cceb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java
@@ -4,157 +4,103 @@ package org.chromium.chrome.browser.banners; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; import android.content.pm.PackageManager; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; -import android.support.annotation.IntDef; -import android.text.TextUtils; -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; -import org.chromium.base.ContextUtils; -import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.ui.base.WindowAndroid; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.concurrent.TimeUnit; /** - * Monitors the app installation process and informs an observer of updates. + * Monitors the PackageManager to see when an app has been installed. */ -public class InstallerDelegate { - /** Observer methods called for the different stages of app installation. */ +public class InstallerDelegate implements Runnable { + /** + * Callback for when the app install has completed. + */ public static interface Observer { /** - * Called when the installation intent completes to inform the observer if installation has - * begun. For instance, the user may have rejected the intent. - * @param delegate The delegate object sending the message. - * @param isInstalling true if the app is currently installing. - */ - public void onInstallIntentCompleted(InstallerDelegate delegate, boolean isInstalling); - - /** * Called when the task has finished. - * @param delegate The delegate object sending the message. + * @param delegate Instance of the class that finished. * @param success Whether or not the package was successfully installed. */ public void onInstallFinished(InstallerDelegate delegate, boolean success); - - /** - * Called when the current application state changes due to an installation. - * @param delegate The delegate object sending the message. - * @param newState The new state id. - */ - public void onApplicationStateChanged( - InstallerDelegate delegate, @ActivityState int newState); } - /** - * Object to wait for the PackageManager to finish installation an app. For convenience, this is - * bound to an instance of InstallerDelegate, and accesses its members and methods. - */ - private class InstallMonitor implements Runnable { - /** Timestamp of when we started monitoring. */ - private long mTimestampStarted; - - public InstallMonitor() {} - - /** Begin monitoring the PackageManager to see if it completes installing the package. */ - public void start() { - mTimestampStarted = SystemClock.elapsedRealtime(); - mIsRunning = true; - mHandler.postDelayed(this, mMsBetweenRuns); - } - - /** Don't call this directly; instead, call {@link #start()}. */ - @Override - public void run() { - boolean isPackageInstalled = isInstalled(mPackageName); - boolean waitedTooLong = - (SystemClock.elapsedRealtime() - mTimestampStarted) > mMsMaximumWaitingTime; - if (isPackageInstalled || !mIsRunning || waitedTooLong) { - mIsRunning = false; - mObserver.onInstallFinished(InstallerDelegate.this, isPackageInstalled); - } else { - mHandler.postDelayed(this, mMsBetweenRuns); - } - } - - /** Prevent rescheduling the Runnable. */ - public void cancel() { - mIsRunning = false; - } - } - - // Installation states. - @Retention(RetentionPolicy.SOURCE) - @IntDef({INSTALL_STATE_NOT_INSTALLED, INSTALL_STATE_INSTALLING, INSTALL_STATE_INSTALLED}) - public @interface InstallState {} - public static final int INSTALL_STATE_NOT_INSTALLED = 0; - public static final int INSTALL_STATE_INSTALLING = 1; - public static final int INSTALL_STATE_INSTALLED = 2; - - private static final String TAG = "cr_InstallerDelegate"; - private static final long DEFAULT_MS_BETWEEN_RUNS = TimeUnit.SECONDS.toMillis(1); - private static final long DEFAULT_MS_MAXIMUM_WAITING_TIME = TimeUnit.MINUTES.toMillis(3); - - /** PackageManager to use in place of the real one. */ - private static PackageManager sPackageManagerForTests; - - /** Monitors an installation in progress. */ - private InstallMonitor mInstallMonitor; + private static final long DEFAULT_MS_BETWEEN_RUNS = 1000; + private static final long DEFAULT_MS_MAXIMUM_WAITING_TIME = 3 * 60 * 1000; /** Message loop to post the Runnable to. */ private final Handler mHandler; - /** Monitors for application state changes. */ - private final ApplicationStatus.ApplicationStateListener mListener; + /** PackageManager that the Runnable is monitoring. */ + private final PackageManager mPackageManager; - /** The name of the package currently being installed. */ - private String mPackageName; + /** Object that is notified when the PackageManager has finished. */ + private final Observer mObserver; - /** Milliseconds to wait between calls to check on the PackageManager during installation. */ - private long mMsBetweenRuns; + /** Name of the package that we need to see the PackageManager has finished installing. */ + private final String mPackageName; - /** Maximum milliseconds to wait before giving up on monitoring during installation. */ - private long mMsMaximumWaitingTime; - - /** The observer to inform of updates during the installation process. */ - private Observer mObserver; - - /** Whether or we are currently monitoring an installation. */ + /** Whether or not the Runnable is currently looping. */ private boolean mIsRunning; - /** Overrides the PackageManager for testing. */ - @VisibleForTesting - static void setPackageManagerForTesting(PackageManager manager) { - sPackageManagerForTests = manager; + /** Number of milliseconds to wait between calls to run(). */ + private long mMsBetweenRuns; + + /** Maximum number of milliseconds to wait before giving up. */ + private long mMsMaximumWaitingTime; + + /** Timestamp of when we first started. */ + private long mTimestampStarted; + + /** + * Constructs the InstallerDelegate. + * @param looper Thread to run the Runnable on. + * @param packageManager Provides access to the list of installed apps. + * @param observer Alerted when the package has been completely installed. + * @param packageName Name of the package for the app to monitor. + */ + public InstallerDelegate( + Looper looper, PackageManager packageManager, Observer observer, String packageName) { + mHandler = new Handler(looper); + mPackageManager = packageManager; + mObserver = observer; + mPackageName = packageName; + mMsBetweenRuns = DEFAULT_MS_BETWEEN_RUNS; + mMsMaximumWaitingTime = DEFAULT_MS_MAXIMUM_WAITING_TIME; } /** - * Set how often the handler will check the PackageManager. - * @param msBetween How long to wait between executions of the Runnable. - * @param msMax How long to wait before giving up. + * Begin monitoring the PackageManager to see if it completes installing the package. */ - @VisibleForTesting - void setTimingForTests(long msBetween, long msMax) { - mMsBetweenRuns = msBetween; - mMsMaximumWaitingTime = msMax; + public void start() { + mTimestampStarted = SystemClock.elapsedRealtime(); + mIsRunning = true; + mHandler.postDelayed(this, mMsBetweenRuns); + } + + /** + * Don't call this directly; instead, call {@link #start()}. + */ + @Override + public void run() { + boolean isInstalled = isInstalled(); + boolean waitedTooLong = + (SystemClock.elapsedRealtime() - mTimestampStarted) > mMsMaximumWaitingTime; + if (isInstalled || !mIsRunning || waitedTooLong) { + mObserver.onInstallFinished(this, isInstalled); + mIsRunning = false; + } else { + mHandler.postDelayed(this, mMsBetweenRuns); + } } /** * Checks if the app has been installed on the system. - * @return true if the PackageManager reports that the app is installed, false otherwise. * @param packageManager PackageManager to use. - * @param packageName Name of the package to check. + * @param packageName Name of the package to check. + * @return True if the PackageManager reports that the app is installed, false otherwise. */ public static boolean isInstalled(PackageManager packageManager, String packageName) { try { @@ -166,153 +112,37 @@ } /** - * Construct an InstallerDelegate to monitor an installation. - * @param looper Thread to run the monitor on. - * @param observer Object to inform of changes in the installation state. - */ - public InstallerDelegate(Looper looper, Observer observer) { - mHandler = new Handler(looper); - mObserver = observer; - mListener = createApplicationStateListener(); - ApplicationStatus.registerApplicationStateListener(mListener); - - mMsBetweenRuns = DEFAULT_MS_BETWEEN_RUNS; - mMsMaximumWaitingTime = DEFAULT_MS_MAXIMUM_WAITING_TIME; - } - - /** * Checks if the app has been installed on the system. - * @return true if the PackageManager reports that the app is installed, false otherwise. - * @param packageName Name of the package to check. + * @return True if the PackageManager reports that the app is installed, false otherwise. */ - public boolean isInstalled(String packageName) { - return isInstalled(getPackageManager(ContextUtils.getApplicationContext()), packageName); + private boolean isInstalled() { + return isInstalled(mPackageManager, mPackageName); } /** - * Stops all current monitoring. + * Prevent rescheduling the Runnable. */ - public void destroy() { - if (mInstallMonitor != null) { - mInstallMonitor.cancel(); - mInstallMonitor = null; - } - ApplicationStatus.unregisterApplicationStateListener(mListener); + public void cancel() { + mIsRunning = false; } /** - * Returns the current installation state of the provided package name - * @return the installation state - not installed, installing, or installed. - * @param packageName Name of the package to check. + * Checks to see if the Runnable will continue scheduling itself. + * @return True if the runnable is still being scheduled. */ - public @InstallState int determineInstallState(String packageName) { - if (mIsRunning || TextUtils.isEmpty(packageName)) { - // The package name being empty means we are installing a WebAPK, where we don't know - // what the package name is until installation is complete. - return INSTALL_STATE_INSTALLING; - } - - if (isInstalled(packageName)) { - return INSTALL_STATE_INSTALLED; - } - - return INSTALL_STATE_NOT_INSTALLED; - } - - /** - * Attempts to open the specified package name in the given content. - * @return true if successfully opened, otherwise false (e.g. not installed/opening failed). - * @param packageName Name of the package to open. - */ - public boolean openApp(String packageName) { - Context context = ContextUtils.getApplicationContext(); - PackageManager packageManager = getPackageManager(context); - if (!isInstalled(packageManager, packageName)) return false; - - Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName); - if (launchIntent != null) { - try { - context.startActivity(launchIntent); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "Failed to open app : %s!", packageName, e); - return false; - } - } - return true; - } - - /** - * Attempts to install or open a native app specified by the given data. - * @return true if the app was opened or installation was started successfully. false otherwise. - * @param tab The current tab. - * @param appData The native app data to try and open or install. - * @param referrer The referrer attached to the URL specifying the native app, if any. - */ - public boolean installOrOpenNativeApp(Tab tab, AppData appData, String referrer) { - if (openApp(appData.packageName())) { - return true; - } else { - // If the installation was started, return false to prevent the infobar disappearing. - // The supplied referrer is the URL of the page requesting the native app banner. It may - // be empty depending on that page's referrer policy. If it is non-empty, attach it to - // the installation intent as Intent.EXTRA_REFERRER. - Intent installIntent = appData.installIntent(); - if (!TextUtils.isEmpty(referrer)) { - installIntent.putExtra(Intent.EXTRA_REFERRER, referrer); - } - return !tab.getWindowAndroid().showIntent( - installIntent, createIntentCallback(appData), null); - } - } - - /** - * Start monitoring an installation. Should be called once per the lifetime of this object. - * @param packageName The name of the package to monitor. - * */ - public void startMonitoring(String packageName) { - mPackageName = packageName; - mInstallMonitor = new InstallMonitor(); - mInstallMonitor.start(); - } - - /** Checks to see if we are currently monitoring an installation. */ @VisibleForTesting boolean isRunning() { return mIsRunning; } - /** Simulates a cancellation for testing purposes. */ + /** + * Set how often the handler will check the PackageManager. + * @param msBetween How long to wait between executions of the Runnable. + * @param msMax How long to wait before giving up. + */ @VisibleForTesting - void cancel() { - mInstallMonitor.cancel(); - } - - private WindowAndroid.IntentCallback createIntentCallback(final AppData appData) { - return new WindowAndroid.IntentCallback() { - @Override - public void onIntentCompleted(WindowAndroid window, int resultCode, Intent data) { - boolean isInstalling = resultCode == Activity.RESULT_OK; - if (isInstalling) { - startMonitoring(appData.packageName()); - } - - mObserver.onInstallIntentCompleted(InstallerDelegate.this, isInstalling); - } - }; - } - - private ApplicationStatus.ApplicationStateListener createApplicationStateListener() { - return new ApplicationStatus.ApplicationStateListener() { - @Override - public void onApplicationStateChange(int newState) { - if (!ApplicationStatus.hasVisibleActivities()) return; - mObserver.onApplicationStateChanged(InstallerDelegate.this, newState); - } - }; - } - - private PackageManager getPackageManager(Context context) { - if (sPackageManagerForTests != null) return sPackageManagerForTests; - return context.getPackageManager(); + void setTimingForTests(long msBetween, long msMax) { + mMsBetweenRuns = msBetween; + mMsMaximumWaitingTime = msMax; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarAndroid.java index 74be983..ea1ee30 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarAndroid.java
@@ -17,13 +17,17 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.banners.AppBannerManager; import org.chromium.chrome.browser.banners.AppData; -import org.chromium.chrome.browser.banners.InstallerDelegate; import org.chromium.chrome.browser.widget.DualControlLayout; /** * Infobar informing the user about an app related to this page. */ public class AppBannerInfoBarAndroid extends ConfirmInfoBar implements View.OnClickListener { + // Installation states. + public static final int INSTALL_STATE_NOT_INSTALLED = 0; + public static final int INSTALL_STATE_INSTALLING = 1; + public static final int INSTALL_STATE_INSTALLED = 2; + // Views composing the infobar. private Button mButton; private InfoBarControlLayout mMessageLayout; @@ -34,7 +38,7 @@ // Data for native app installs. private final AppData mAppData; - private @InstallerDelegate.InstallState int mInstallState; + private int mInstallState; // Data for web app installs. private final String mAppUrl; @@ -48,7 +52,7 @@ mAppTitle = appTitle; mAppData = data; mAppUrl = null; - mInstallState = InstallerDelegate.INSTALL_STATE_NOT_INSTALLED; + mInstallState = INSTALL_STATE_NOT_INSTALLED; } // Banner for web apps. @@ -59,7 +63,7 @@ mAppData = null; mAppUrl = url; mIsWebApk = isWebApk; - mInstallState = InstallerDelegate.INSTALL_STATE_NOT_INSTALLED; + mInstallState = INSTALL_STATE_NOT_INSTALLED; } @Override @@ -121,7 +125,7 @@ @Override public void onButtonClicked(boolean isPrimaryButton) { - if (isPrimaryButton && mInstallState == InstallerDelegate.INSTALL_STATE_INSTALLING) { + if (isPrimaryButton && mInstallState == INSTALL_STATE_INSTALLING) { setControlsEnabled(true); updateButton(); return; @@ -143,7 +147,7 @@ String accessibilityText = null; boolean enabled = true; Context context = getContext(); - if (mInstallState == InstallerDelegate.INSTALL_STATE_NOT_INSTALLED) { + if (mInstallState == INSTALL_STATE_NOT_INSTALLED) { if (mIsWebApk) { // If the installation of the WebAPK fails, the banner will disappear and // a failure toast will be shown. @@ -152,7 +156,7 @@ text = mAppData.installButtonText(); accessibilityText = context.getString( R.string.app_banner_view_native_app_install_accessibility, text); - } else if (mInstallState == InstallerDelegate.INSTALL_STATE_INSTALLING) { + } else if (mInstallState == INSTALL_STATE_INSTALLING) { text = mIsWebApk ? context.getString(R.string.app_banner_installing_webapk) : context.getString(R.string.app_banner_installing); mButton.announceForAccessibility(text);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java index 7ad31c0..7020011 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java
@@ -4,64 +4,159 @@ package org.chromium.chrome.browser.infobar; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; import android.os.Looper; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.ContextUtils; +import org.chromium.base.Log; +import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.banners.AppData; import org.chromium.chrome.browser.banners.InstallerDelegate; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.ui.base.WindowAndroid; /** - * Handles the promotion and installation of an app specified by the current web page. This object - * is created by and owned by the native AppBannerInfoBarDelegateAndroid. + * Handles the promotion and installation of an app specified by the current web page. This Java + * object is created by and owned by the native AppBannerInfoBarDelegateAndroid. */ @JNINamespace("banners") -public class AppBannerInfoBarDelegateAndroid implements InstallerDelegate.Observer { +public class AppBannerInfoBarDelegateAndroid { + private static final String TAG = "cr_AppBannerInfoBar"; + + /** PackageManager to use in place of the real one. */ + private static PackageManager sPackageManagerForTests; + /** Weak pointer to the native AppBannerInfoBarDelegateAndroid. */ private long mNativePointer; - /** Delegate which does the actual monitoring of an in-progress installation. */ - private InstallerDelegate mInstallerDelegate; + /** Monitors an installation in progress. */ + private InstallerDelegate mInstallTask; + + /** Monitors for application state changes. */ + private final ApplicationStatus.ApplicationStateListener mListener; + + /** + * Indicates whether a request to install a WebAPK has started. This flag is set while the + * WebAPK is being installed. + */ + private boolean mIsInstallingWebApk; + + /** The package name of the WebAPK. */ + private String mWebApkPackage; + + /** Overrides the PackageManager for testing. */ + @VisibleForTesting + public static void setPackageManagerForTesting(PackageManager manager) { + sPackageManagerForTests = manager; + } private AppBannerInfoBarDelegateAndroid(long nativePtr) { mNativePointer = nativePtr; - mInstallerDelegate = new InstallerDelegate(Looper.getMainLooper(), this); + mListener = createApplicationStateListener(); + ApplicationStatus.registerApplicationStateListener(mListener); } - @Override - public void onInstallIntentCompleted(InstallerDelegate delegate, boolean isInstalling) { - if (mInstallerDelegate != delegate) return; - nativeOnInstallIntentReturned(mNativePointer, isInstalling); - } - - @Override - public void onInstallFinished(InstallerDelegate delegate, boolean success) { - if (mInstallerDelegate != delegate) return; - nativeOnInstallFinished(mNativePointer, success); - } - - @Override - public void onApplicationStateChanged(InstallerDelegate delegate, int newState) { - if (mInstallerDelegate != delegate) return; - nativeUpdateInstallState(mNativePointer); + private ApplicationStatus.ApplicationStateListener createApplicationStateListener() { + return new ApplicationStatus.ApplicationStateListener() { + @Override + public void onApplicationStateChange(int newState) { + if (!ApplicationStatus.hasVisibleActivities()) return; + nativeUpdateInstallState(mNativePointer); + } + }; } @CalledByNative private void destroy() { - mInstallerDelegate.destroy(); - mInstallerDelegate = null; + if (mInstallTask != null) { + mInstallTask.cancel(); + mInstallTask = null; + } + ApplicationStatus.unregisterApplicationStateListener(mListener); mNativePointer = 0; } @CalledByNative private boolean installOrOpenNativeApp(Tab tab, AppData appData, String referrer) { - return mInstallerDelegate.installOrOpenNativeApp(tab, appData, referrer); + Context context = ContextUtils.getApplicationContext(); + String packageName = appData.packageName(); + PackageManager packageManager = getPackageManager(context); + + if (InstallerDelegate.isInstalled(packageManager, packageName)) { + // Open the app. + openApp(context, packageName); + return true; + } else { + // Try installing the app. If the installation was kicked off, return false to prevent + // the infobar from disappearing. + // The supplied referrer is the URL of the page requesting the native app banner. It + // may be empty depending on that page's referrer policy. If it is non-empty, attach it + // to the installation intent as Intent.EXTRA_REFERRER. + Intent installIntent = appData.installIntent(); + if (referrer.length() > 0) installIntent.putExtra(Intent.EXTRA_REFERRER, referrer); + return !tab.getWindowAndroid().showIntent( + installIntent, createIntentCallback(appData), null); + } + } + + void openApp(Context context, String packageName) { + Intent launchIntent = getPackageManager(context).getLaunchIntentForPackage(packageName); + if (launchIntent != null) { + try { + context.startActivity(launchIntent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "Failed to open app : %s!", packageName, e); + return; + } + } + } + + private WindowAndroid.IntentCallback createIntentCallback(final AppData appData) { + return new WindowAndroid.IntentCallback() { + @Override + public void onIntentCompleted(WindowAndroid window, int resultCode, Intent data) { + boolean isInstalling = resultCode == Activity.RESULT_OK; + if (isInstalling) { + // Start monitoring the install. + PackageManager pm = + getPackageManager(ContextUtils.getApplicationContext()); + mInstallTask = new InstallerDelegate( + Looper.getMainLooper(), pm, createInstallerDelegateObserver(), + appData.packageName()); + mInstallTask.start(); + } + + nativeOnInstallIntentReturned(mNativePointer, isInstalling); + } + }; + } + + private InstallerDelegate.Observer createInstallerDelegateObserver() { + return new InstallerDelegate.Observer() { + @Override + public void onInstallFinished(InstallerDelegate task, boolean success) { + if (mInstallTask != task) return; + mInstallTask = null; + nativeOnInstallFinished(mNativePointer, success); + } + }; } @CalledByNative - private void openApp(String packageName) { - mInstallerDelegate.openApp(packageName); + private void openWebApk() { + Context context = ContextUtils.getApplicationContext(); + PackageManager packageManager = getPackageManager(context); + + if (InstallerDelegate.isInstalled(packageManager, mWebApkPackage)) { + openApp(context, mWebApkPackage); + } } @CalledByNative @@ -70,8 +165,33 @@ } @CalledByNative - private int determineInstallState(String packageName) { - return mInstallerDelegate.determineInstallState(packageName); + private int determineInstallState(AppData data) { + if (mInstallTask != null || mIsInstallingWebApk) { + return AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLING; + } + + PackageManager pm = getPackageManager(ContextUtils.getApplicationContext()); + String packageName = (data != null) ? data.packageName() : mWebApkPackage; + boolean isInstalled = InstallerDelegate.isInstalled(pm, packageName); + return isInstalled ? AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLED + : AppBannerInfoBarAndroid.INSTALL_STATE_NOT_INSTALLED; + } + + @CalledByNative + /** Set the flag of whether the installation process has been started for the WebAPK. */ + private void setWebApkInstallingState(boolean isInstalling) { + mIsInstallingWebApk = isInstalling; + } + + @CalledByNative + /** Sets the WebAPK package name. */ + private void setWebApkPackageName(String webApkPackage) { + mWebApkPackage = webApkPackage; + } + + private PackageManager getPackageManager(Context context) { + if (sPackageManagerForTests != null) return sPackageManagerForTests; + return context.getPackageManager(); } @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsLauncher.java index d9e5463..4f2304e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsLauncher.java
@@ -31,11 +31,6 @@ // Task tags for fetching snippets. public static final String TASK_TAG_WIFI = "FetchSnippetsWifi"; public static final String TASK_TAG_FALLBACK = "FetchSnippetsFallback"; - // TODO(treib): Remove this after M55. - private static final String OBSOLETE_TASK_TAG_WIFI_CHARGING = "FetchSnippetsWifiCharging"; - - // TODO(treib): Remove this after M55. - private static final String OBSOLETE_TASK_TAG_RESCHEDULE = "RescheduleSnippets"; // The amount of "flex" to add around the fetching periods, as a ratio of the period. private static final double FLEX_FACTOR = 0.1; @@ -144,12 +139,10 @@ // Google Play Services may not be up to date, if the application was not installed through // the Play Store. In this case, scheduling the task will fail silently. try { - mScheduler.cancelTask(OBSOLETE_TASK_TAG_WIFI_CHARGING, ChromeBackgroundService.class); scheduleOrCancelFetchTask( TASK_TAG_WIFI, periodWifiSeconds, Task.NETWORK_STATE_UNMETERED); scheduleOrCancelFetchTask( TASK_TAG_FALLBACK, periodFallbackSeconds, Task.NETWORK_STATE_CONNECTED); - mScheduler.cancelTask(OBSOLETE_TASK_TAG_RESCHEDULE, ChromeBackgroundService.class); } catch (IllegalArgumentException e) { // Disable GCM for the remainder of this session. mGCMEnabled = false;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 7c25890..9e3c250 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -37,6 +37,7 @@ import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.engagement.SiteEngagementService; import org.chromium.chrome.browser.infobar.AppBannerInfoBarAndroid; +import org.chromium.chrome.browser.infobar.AppBannerInfoBarDelegateAndroid; import org.chromium.chrome.browser.infobar.InfoBar; import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationListener; @@ -198,7 +199,7 @@ public void setUp() throws Exception { mPackageManager = new TestPackageManager(); AppBannerManager.setIsSupported(true); - InstallerDelegate.setPackageManagerForTesting(mPackageManager); + AppBannerInfoBarDelegateAndroid.setPackageManagerForTesting(mPackageManager); ShortcutHelper.setDelegateForTests(new ShortcutHelper.Delegate() { @Override public void addShortcutToHomescreen(String title, Bitmap icon, Intent shortcutIntent) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java index 300fe75d..e64a9c3b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java
@@ -57,11 +57,6 @@ private boolean mInstallStarted; @Override - public void onInstallIntentCompleted(InstallerDelegate delegate, boolean isInstalling) { - Assert.assertTrue(isInstalling); - } - - @Override public void onInstallFinished(InstallerDelegate delegate, boolean success) { mResultDelegate = delegate; mResultSuccess = success; @@ -69,19 +64,16 @@ Assert.assertTrue(mInstallStarted); } - @Override - public void onApplicationStateChanged(InstallerDelegate delegate, int newState) {} - @Before public void setUp() throws Exception { mPackageManager = new TestPackageManager(); - InstallerDelegate.setPackageManagerForTesting(mPackageManager); // Create a thread for the InstallerDelegate to run on. We need this thread because the // InstallerDelegate's handler fails to be processed otherwise. mThread = new HandlerThread("InstallerDelegateTest thread"); mThread.start(); - mTestDelegate = new InstallerDelegate(mThread.getLooper(), this); + mTestDelegate = new InstallerDelegate( + mThread.getLooper(), mPackageManager, this, MOCK_PACKAGE_NAME); // Clear out the results from last time. mResultDelegate = null; @@ -95,7 +87,7 @@ } private void startMonitoring() { - mTestDelegate.startMonitoring(MOCK_PACKAGE_NAME); + mTestDelegate.start(); mInstallStarted = true; }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 701fbde..fddbb79 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3920,8 +3920,8 @@ "//components/exo/wayland", ] sources += [ - "exo_parts.cc", - "exo_parts.h", + "chrome_browser_main_extra_parts_exo.cc", + "chrome_browser_main_extra_parts_exo.h", ] }
diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc index d68dca1..6234b7d 100644 --- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc +++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc
@@ -82,10 +82,10 @@ const base::string16& app_title, const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, const SkBitmap& icon, - const std::string& native_app_package_name, + const std::string& native_app_package, const std::string& referrer) { auto infobar_delegate = base::WrapUnique(new AppBannerInfoBarDelegateAndroid( - app_title, native_app_data, icon, native_app_package_name, referrer)); + app_title, native_app_data, icon, native_app_package, referrer)); return InfoBarService::FromWebContents(web_contents) ->AddInfoBar(base::MakeUnique<AppBannerInfoBarAndroid>( std::move(infobar_delegate), native_app_data)); @@ -107,8 +107,8 @@ if (TriggeredFromBanner()) TrackDismissEvent(DISMISS_EVENT_DISMISSED); - Java_AppBannerInfoBarDelegateAndroid_destroy( - base::android::AttachCurrentThread(), java_delegate_); + JNIEnv* env = base::android::AttachCurrentThread(); + Java_AppBannerInfoBarDelegateAndroid_destroy(env, java_delegate_); java_delegate_.Reset(); } @@ -118,12 +118,10 @@ if (native_app_data_.is_null() && !is_webapk_) return; - ScopedJavaLocalRef<jstring> jpackage_name( - ConvertUTF8ToJavaString(env, package_name_)); int newState = Java_AppBannerInfoBarDelegateAndroid_determineInstallState( - env, java_delegate_, jpackage_name); - static_cast<AppBannerInfoBarAndroid*>(infobar())->OnInstallStateChanged( - newState); + env, java_delegate_, native_app_data_); + static_cast<AppBannerInfoBarAndroid*>(infobar()) + ->OnInstallStateChanged(newState); } void AppBannerInfoBarDelegateAndroid::OnInstallIntentReturned( @@ -131,13 +129,14 @@ const JavaParamRef<jobject>& obj, jboolean jis_installing) { DCHECK(infobar()); - DCHECK(!package_name_.empty()); content::WebContents* web_contents = InfoBarService::WebContentsFromInfoBar(infobar()); if (jis_installing) { AppBannerSettingsHelper::RecordBannerEvent( - web_contents, web_contents->GetURL(), package_name_, + web_contents, + web_contents->GetURL(), + native_app_package_, AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN, AppBannerManager::GetCurrentTime()); @@ -185,6 +184,19 @@ return AcceptWebApp(web_contents); } +void AppBannerInfoBarDelegateAndroid::UpdateStateForInstalledWebAPK( + const std::string& webapk_package_name) { + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef<jstring> java_webapk_package_name = + base::android::ConvertUTF8ToJavaString(env, webapk_package_name); + Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( + env, java_delegate_, false); + Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName( + env, java_delegate_, java_webapk_package_name); + UpdateInstallState(env, nullptr); + install_state_ = INSTALLED; +} + AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( base::WeakPtr<AppBannerManager> weak_manager, std::unique_ptr<ShortcutInfo> shortcut_info, @@ -209,24 +221,23 @@ const base::string16& app_title, const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, const SkBitmap& icon, - const std::string& native_app_package_name, + const std::string& native_app_package, const std::string& referrer) : app_title_(app_title), native_app_data_(native_app_data), primary_icon_(icon), - package_name_(native_app_package_name), + native_app_package_(native_app_package), referrer_(referrer), has_user_interaction_(false), - is_webapk_(false), weak_ptr_factory_(this) { DCHECK(!native_app_data_.is_null()); - DCHECK(!package_name_.empty()); CreateJavaDelegate(); } void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() { java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create( - base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this))); + base::android::AttachCurrentThread(), + reinterpret_cast<intptr_t>(this))); } bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp( @@ -274,11 +285,7 @@ // If the WebAPK is installed and the "Open" button is clicked, open the // WebAPK. Do not send a BannerAccepted message. if (install_state_ == INSTALLED) { - DCHECK(!package_name_.empty()); - ScopedJavaLocalRef<jstring> jpackage_name( - ConvertUTF8ToJavaString(env, package_name_)); - Java_AppBannerInfoBarDelegateAndroid_openApp(env, java_delegate_, - jpackage_name); + Java_AppBannerInfoBarDelegateAndroid_openWebApk(env, java_delegate_); webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN); return true; } @@ -303,6 +310,8 @@ AppBannerManager::GetCurrentTime()); } + Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( + env, java_delegate_, true); UpdateInstallState(env, nullptr); WebApkInstallService::FinishCallback callback = base::Bind(&AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished, @@ -343,10 +352,7 @@ OnWebApkInstallFailed(result); return; } - - install_state_ = INSTALLED; - package_name_ = webapk_package_name; - UpdateInstallState(base::android::AttachCurrentThread(), nullptr); + UpdateStateForInstalledWebAPK(webapk_package_name); } void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFailed( @@ -409,10 +415,9 @@ AppBannerSettingsHelper::WEB); } } else { - DCHECK(!package_name_.empty()); TrackUserResponse(USER_RESPONSE_NATIVE_APP_DISMISSED); AppBannerSettingsHelper::RecordBannerDismissEvent( - web_contents, package_name_, AppBannerSettingsHelper::NATIVE); + web_contents, native_app_package_, AppBannerSettingsHelper::NATIVE); } } @@ -430,14 +435,15 @@ return false; // Try to show the details for the native app. + JNIEnv* env = base::android::AttachCurrentThread(); + content::WebContents* web_contents = InfoBarService::WebContentsFromInfoBar(infobar()); TabAndroid* tab = TabAndroid::FromWebContents(web_contents); DCHECK(tab); Java_AppBannerInfoBarDelegateAndroid_showAppDetails( - base::android::AttachCurrentThread(), java_delegate_, - tab->GetJavaObject(), native_app_data_); + env, java_delegate_, tab->GetJavaObject(), native_app_data_); TrackDismissEvent(DISMISS_EVENT_BANNER_CLICK); return true;
diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h index e7dd249..b62e5e3 100644 --- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h +++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h
@@ -52,7 +52,7 @@ const base::string16& app_title, const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, const SkBitmap& icon, - const std::string& native_app_package_name, + const std::string& native_app_package, const std::string& referrer); ~AppBannerInfoBarDelegateAndroid() override; @@ -75,6 +75,9 @@ // ConfirmInfoBarDelegate: bool Accept() override; + // Update the AppBannerInfoBarAndroid with installed WebAPK's information. + void UpdateStateForInstalledWebAPK(const std::string& webapk_package_name); + private: // The states of a WebAPK installation, where the infobar is displayed during // the entire installation process. This state is used to correctly record @@ -99,7 +102,7 @@ const base::string16& app_title, const base::android::ScopedJavaGlobalRef<jobject>& native_app_data, const SkBitmap& icon, - const std::string& native_app_package_name, + const std::string& native_app_package, const std::string& referrer); void CreateJavaDelegate(); @@ -149,7 +152,7 @@ const SkBitmap primary_icon_; const SkBitmap badge_icon_; - std::string package_name_; + std::string native_app_package_; std::string referrer_; bool has_user_interaction_;
diff --git a/chrome/browser/exo_parts.cc b/chrome/browser/chrome_browser_main_extra_parts_exo.cc similarity index 87% rename from chrome/browser/exo_parts.cc rename to chrome/browser/chrome_browser_main_extra_parts_exo.cc index 6e6f5d7..4927bbd 100644 --- a/chrome/browser/exo_parts.cc +++ b/chrome/browser/chrome_browser_main_extra_parts_exo.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/exo_parts.h" +#include "chrome/browser/chrome_browser_main_extra_parts_exo.h" #include "base/memory/ptr_util.h" @@ -12,7 +12,6 @@ #include "base/command_line.h" #include "base/macros.h" -#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/common/chrome_switches.h" @@ -57,7 +56,7 @@ } // namespace -class ExoParts::WaylandWatcher { +class ChromeBrowserMainExtraPartsExo::WaylandWatcher { public: explicit WaylandWatcher(exo::wayland::Server* server) : wayland_poll_(new GPollFD), @@ -88,7 +87,8 @@ DISALLOW_COPY_AND_ASSIGN(WaylandWatcher); }; #else -class ExoParts::WaylandWatcher : public base::MessagePumpLibevent::Watcher { +class ChromeBrowserMainExtraPartsExo::WaylandWatcher + : public base::MessagePumpLibevent::Watcher { public: explicit WaylandWatcher(exo::wayland::Server* server) : controller_(FROM_HERE), server_(server) { @@ -113,24 +113,15 @@ }; #endif -// static -std::unique_ptr<ExoParts> ExoParts::CreateIfNecessary() { +ChromeBrowserMainExtraPartsExo::ChromeBrowserMainExtraPartsExo() {} + +ChromeBrowserMainExtraPartsExo::~ChromeBrowserMainExtraPartsExo() {} + +void ChromeBrowserMainExtraPartsExo::PreProfileInit() { if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableWaylandServer)) { - return nullptr; - } + switches::kEnableWaylandServer)) + return; - return base::WrapUnique(new ExoParts()); -} - -ExoParts::~ExoParts() { - wayland_watcher_.reset(); - wayland_server_.reset(); - exo::WMHelper::SetInstance(nullptr); - wm_helper_.reset(); -} - -ExoParts::ExoParts() { arc_notification_surface_manager_ = base::MakeUnique<arc::ArcNotificationSurfaceManagerImpl>(); if (ash_util::IsRunningInMash()) @@ -145,3 +136,12 @@ if (wayland_server_) wayland_watcher_ = base::MakeUnique<WaylandWatcher>(wayland_server_.get()); } + +void ChromeBrowserMainExtraPartsExo::PostMainMessageLoopRun() { + wayland_watcher_.reset(); + wayland_server_.reset(); + if (wm_helper_) { + exo::WMHelper::SetInstance(nullptr); + wm_helper_.reset(); + } +}
diff --git a/chrome/browser/chrome_browser_main_extra_parts_exo.h b/chrome/browser/chrome_browser_main_extra_parts_exo.h new file mode 100644 index 0000000..0113c771 --- /dev/null +++ b/chrome/browser/chrome_browser_main_extra_parts_exo.h
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROME_BROWSER_MAIN_EXTRA_PARTS_EXO_H_ +#define CHROME_BROWSER_CHROME_BROWSER_MAIN_EXTRA_PARTS_EXO_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/chrome_browser_main_extra_parts.h" + +namespace exo { +class Display; +class WMHelper; +namespace wayland { +class Server; +} +} + +namespace arc { +class ArcNotificationSurfaceManagerImpl; +} + +class ChromeBrowserMainExtraPartsExo : public ChromeBrowserMainExtraParts { + public: + ChromeBrowserMainExtraPartsExo(); + ~ChromeBrowserMainExtraPartsExo() override; + + // Overridden from ChromeBrowserMainExtraParts: + void PreProfileInit() override; + void PostMainMessageLoopRun() override; + + private: + std::unique_ptr<arc::ArcNotificationSurfaceManagerImpl> + arc_notification_surface_manager_; + std::unique_ptr<exo::WMHelper> wm_helper_; + std::unique_ptr<exo::Display> display_; + std::unique_ptr<exo::wayland::Server> wayland_server_; + class WaylandWatcher; + std::unique_ptr<WaylandWatcher> wayland_watcher_; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsExo); +}; + +#endif // CHROME_BROWSER_CHROME_BROWSER_MAIN_EXTRA_PARTS_EXO_H_
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index d1be8fc..9e45446 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -387,6 +387,10 @@ #include "components/printing/service/public/interfaces/pdf_compositor.mojom.h" #endif +#if BUILDFLAG(ENABLE_WAYLAND_SERVER) +#include "chrome/browser/chrome_browser_main_extra_parts_exo.h" +#endif + #if BUILDFLAG(ENABLE_MOJO_MEDIA) #include "chrome/browser/media/output_protection_impl.h" #if BUILDFLAG(ENABLE_MOJO_CDM) && defined(OS_ANDROID) @@ -904,6 +908,10 @@ main_parts->AddParts(new ChromeBrowserMainExtraPartsX11()); #endif +#if BUILDFLAG(ENABLE_WAYLAND_SERVER) + main_parts->AddParts(new ChromeBrowserMainExtraPartsExo()); +#endif + chrome::AddMetricsExtraParts(main_parts); return main_parts;
diff --git a/chrome/browser/exo_parts.h b/chrome/browser/exo_parts.h deleted file mode 100644 index 5c34364..0000000 --- a/chrome/browser/exo_parts.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_EXO_PARTS_H_ -#define CHROME_BROWSER_EXO_PARTS_H_ - -#include <memory> - -#include "base/macros.h" - -namespace exo { -class Display; -class WMHelper; -namespace wayland { -class Server; -} -} // namespace exo - -namespace arc { -class ArcNotificationSurfaceManagerImpl; -} - -class ExoParts { - public: - // Creates ExoParts. Returns null if exo should not be created. - static std::unique_ptr<ExoParts> CreateIfNecessary(); - - ~ExoParts(); - - private: - ExoParts(); - - std::unique_ptr<arc::ArcNotificationSurfaceManagerImpl> - arc_notification_surface_manager_; - std::unique_ptr<exo::WMHelper> wm_helper_; - std::unique_ptr<exo::Display> display_; - std::unique_ptr<exo::wayland::Server> wayland_server_; - class WaylandWatcher; - std::unique_ptr<WaylandWatcher> wayland_watcher_; - - DISALLOW_COPY_AND_ASSIGN(ExoParts); -}; - -#endif // CHROME_BROWSER_EXO_PARTS_H_
diff --git a/chrome/browser/media/media_engagement_contents_observer.cc b/chrome/browser/media/media_engagement_contents_observer.cc index 13180110..150ed8e8 100644 --- a/chrome/browser/media/media_engagement_contents_observer.cc +++ b/chrome/browser/media/media_engagement_contents_observer.cc
@@ -9,12 +9,18 @@ #include "chrome/browser/media/media_engagement_service.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" +#include "services/metrics/public/cpp/ukm_entry_builder.h" +#include "services/metrics/public/cpp/ukm_recorder.h" namespace { constexpr base::TimeDelta kSignificantMediaPlaybackTime = base::TimeDelta::FromSeconds(7); +int ConvertScoreToPercentage(double score) { + return round(score * 100); +} + } // namespace. // This is the minimum size (in px) of each dimension that a media @@ -25,6 +31,21 @@ const char* MediaEngagementContentsObserver::kHistogramScoreAtPlaybackName = "Media.Engagement.ScoreAtPlayback"; +const char* MediaEngagementContentsObserver::kUkmEntryName = + "Media.Engagement.SessionFinished"; + +const char* MediaEngagementContentsObserver::kUkmMetricPlaybacksTotalName = + "Playbacks.Total"; + +const char* MediaEngagementContentsObserver::kUkmMetricVisitsTotalName = + "Visits.Total"; + +const char* MediaEngagementContentsObserver::kUkmMetricEngagementScoreName = + "Engagement.Score"; + +const char* MediaEngagementContentsObserver::kUkmMetricPlaybacksDeltaName = + "Playbacks.Delta"; + MediaEngagementContentsObserver::MediaEngagementContentsObserver( content::WebContents* web_contents, MediaEngagementService* service) @@ -36,6 +57,7 @@ void MediaEngagementContentsObserver::WebContentsDestroyed() { playback_timer_->Stop(); + RecordUkmMetrics(); ClearPlayerStates(); service_->contents_observers_.erase(this); delete this; @@ -48,6 +70,35 @@ significant_players_.clear(); } +void MediaEngagementContentsObserver::RecordUkmMetrics() { + ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); + if (!ukm_recorder) + return; + + GURL url = committed_origin_.GetURL(); + if (!service_->ShouldRecordEngagement(url)) + return; + + ukm::SourceId source_id = ukm_recorder->GetNewSourceID(); + ukm_recorder->UpdateSourceURL(source_id, url); + + std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_recorder->GetEntryBuilder( + source_id, MediaEngagementContentsObserver::kUkmEntryName); + + MediaEngagementScore score = service_->CreateEngagementScore(url); + builder->AddMetric( + MediaEngagementContentsObserver::kUkmMetricPlaybacksTotalName, + score.media_playbacks()); + builder->AddMetric(MediaEngagementContentsObserver::kUkmMetricVisitsTotalName, + score.visits()); + builder->AddMetric( + MediaEngagementContentsObserver::kUkmMetricEngagementScoreName, + ConvertScoreToPercentage(score.GetTotalScore())); + builder->AddMetric( + MediaEngagementContentsObserver::kUkmMetricPlaybacksDeltaName, + significant_playback_recorded_); +} + void MediaEngagementContentsObserver::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!navigation_handle->IsInMainFrame() || @@ -63,12 +114,10 @@ if (committed_origin_.IsSameOriginWith(new_origin)) return; + RecordUkmMetrics(); + committed_origin_ = new_origin; significant_playback_recorded_ = false; - - if (committed_origin_.unique()) - return; - service_->RecordVisit(committed_origin_.GetURL()); } @@ -182,10 +231,6 @@ #endif significant_playback_recorded_ = true; - - if (committed_origin_.unique()) - return; - service_->RecordPlayback(committed_origin_.GetURL()); }
diff --git a/chrome/browser/media/media_engagement_contents_observer.h b/chrome/browser/media/media_engagement_contents_observer.h index 5d9d04d..c2bd5da22 100644 --- a/chrome/browser/media/media_engagement_contents_observer.h +++ b/chrome/browser/media/media_engagement_contents_observer.h
@@ -81,6 +81,15 @@ void MaybeRemoveSignificantPlayer(const MediaPlayerId& id); bool IsSignificantPlayer(const MediaPlayerId& id); + // Record the score and change in score to UKM. + void RecordUkmMetrics(); + + static const char* kUkmEntryName; + static const char* kUkmMetricPlaybacksTotalName; + static const char* kUkmMetricVisitsTotalName; + static const char* kUkmMetricEngagementScoreName; + static const char* kUkmMetricPlaybacksDeltaName; + bool is_visible_ = false; bool significant_playback_recorded_ = false;
diff --git a/chrome/browser/media/media_engagement_contents_observer_unittest.cc b/chrome/browser/media/media_engagement_contents_observer_unittest.cc index dabe98a..d9355a2 100644 --- a/chrome/browser/media/media_engagement_contents_observer_unittest.cc +++ b/chrome/browser/media/media_engagement_contents_observer_unittest.cc
@@ -13,6 +13,8 @@ #include "chrome/browser/media/media_engagement_service_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" +#include "components/ukm/test_ukm_recorder.h" +#include "components/ukm/ukm_source.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "content/public/test/web_contents_tester.h" @@ -154,6 +156,49 @@ ->SetWasRecentlyAudible(false); } + void ExpectUkmEntry(GURL url, + int playbacks_total, + int visits_total, + int score, + int playbacks_delta) { + std::vector<std::pair<const char*, int64_t>> metrics = { + {MediaEngagementContentsObserver::kUkmMetricPlaybacksTotalName, + playbacks_total}, + {MediaEngagementContentsObserver::kUkmMetricVisitsTotalName, + visits_total}, + {MediaEngagementContentsObserver::kUkmMetricEngagementScoreName, score}, + {MediaEngagementContentsObserver::kUkmMetricPlaybacksDeltaName, + playbacks_delta}, + }; + + const ukm::UkmSource* source = + test_ukm_recorder_.GetSourceForUrl(url.spec().c_str()); + EXPECT_EQ(url, source->url()); + EXPECT_EQ(1, test_ukm_recorder_.CountEntries( + *source, MediaEngagementContentsObserver::kUkmEntryName)); + test_ukm_recorder_.ExpectMetric( + *source, MediaEngagementContentsObserver::kUkmEntryName, + MediaEngagementContentsObserver::kUkmMetricVisitsTotalName, + visits_total); + test_ukm_recorder_.ExpectMetric( + *source, MediaEngagementContentsObserver::kUkmEntryName, + MediaEngagementContentsObserver::kUkmMetricPlaybacksTotalName, + playbacks_total); + test_ukm_recorder_.ExpectMetric( + *source, MediaEngagementContentsObserver::kUkmEntryName, + MediaEngagementContentsObserver::kUkmMetricEngagementScoreName, score); + test_ukm_recorder_.ExpectMetric( + *source, MediaEngagementContentsObserver::kUkmEntryName, + MediaEngagementContentsObserver::kUkmMetricPlaybacksDeltaName, + playbacks_delta); + test_ukm_recorder_.ExpectEntry( + *source, MediaEngagementContentsObserver::kUkmEntryName, metrics); + } + + void ExpectNoUkmEntry() { EXPECT_FALSE(test_ukm_recorder_.sources_count()); } + + void SimulateDestroy() { contents_observer_->WebContentsDestroyed(); } + void SimulateSignificantPlayer(int id) { SimulatePlaybackStarted(id); SimulateIsVisible(); @@ -171,6 +216,8 @@ base::test::ScopedFeatureList scoped_feature_list_; base::MockTimer* playback_timer_; + + ukm::TestUkmRecorder test_ukm_recorder_; }; // TODO(mlamouri): test that visits are not recorded multiple times when a @@ -435,3 +482,71 @@ tester.ExpectTotalCount( MediaEngagementContentsObserver::kHistogramScoreAtPlaybackName, 0); } + +TEST_F(MediaEngagementContentsObserverTest, RecordUkmMetricsOnDestroy) { + GURL url("https://www.google.com"); + SetScores(url, 6, 5); + Navigate(url); + + EXPECT_FALSE(WasSignificantPlaybackRecorded()); + SimulateSignificantPlayer(0); + SimulateSignificantPlaybackTime(); + ExpectScores(url, 6.0 / 7.0, 7, 6); + EXPECT_TRUE(WasSignificantPlaybackRecorded()); + + SimulateDestroy(); + ExpectUkmEntry(url, 6, 7, 86, 1); +} + +TEST_F(MediaEngagementContentsObserverTest, + RecordUkmMetricsOnDestroy_NoPlaybacks) { + GURL url("https://www.google.com"); + SetScores(url, 6, 5); + Navigate(url); + + EXPECT_FALSE(WasSignificantPlaybackRecorded()); + ExpectScores(url, 5.0 / 7.0, 7, 5); + + SimulateDestroy(); + ExpectUkmEntry(url, 5, 7, 71, 0); +} + +TEST_F(MediaEngagementContentsObserverTest, RecordUkmMetricsOnNavigate) { + GURL url("https://www.google.com"); + SetScores(url, 6, 5); + Navigate(url); + + EXPECT_FALSE(WasSignificantPlaybackRecorded()); + SimulateSignificantPlayer(0); + SimulateSignificantPlaybackTime(); + ExpectScores(url, 6.0 / 7.0, 7, 6); + EXPECT_TRUE(WasSignificantPlaybackRecorded()); + + Navigate(GURL("https://www.example.org")); + ExpectUkmEntry(url, 6, 7, 86, 1); +} + +TEST_F(MediaEngagementContentsObserverTest, + RecordUkmMetricsOnNavigate_NoPlaybacks) { + GURL url("https://www.google.com"); + SetScores(url, 6, 5); + Navigate(url); + + EXPECT_FALSE(WasSignificantPlaybackRecorded()); + ExpectScores(url, 5.0 / 7.0, 7, 5); + + Navigate(GURL("https://www.example.org")); + ExpectUkmEntry(url, 5, 7, 71, 0); +} + +TEST_F(MediaEngagementContentsObserverTest, DoNotRecordMetricsOnInternalUrl) { + Navigate(GURL("chrome://about")); + + EXPECT_FALSE(WasSignificantPlaybackRecorded()); + SimulateSignificantPlayer(0); + SimulateSignificantPlaybackTime(); + EXPECT_TRUE(WasSignificantPlaybackRecorded()); + + SimulateDestroy(); + ExpectNoUkmEntry(); +}
diff --git a/chrome/browser/predictors/loading_predictor.cc b/chrome/browser/predictors/loading_predictor.cc index 3507650..d945e8d 100644 --- a/chrome/browser/predictors/loading_predictor.cc +++ b/chrome/browser/predictors/loading_predictor.cc
@@ -29,18 +29,14 @@ stats_collector_.get(), config)), observer_(nullptr), - weak_factory_(this) { - preconnect_manager_ = base::MakeUnique<PreconnectManager>( - GetWeakPtr(), profile_->GetRequestContext()); -} + weak_factory_(this) {} LoadingPredictor::~LoadingPredictor() { - // Ensure that Shutdown() was called. - DCHECK(preconnect_manager_ == nullptr); + DCHECK(shutdown_); } void LoadingPredictor::PrepareForPageLoad(const GURL& url, HintOrigin origin) { - if (active_hints_.find(url) != active_hints_.end()) + if (shutdown_ || active_hints_.find(url) != active_hints_.end()) return; bool has_prefetch_prediction = false; @@ -78,10 +74,16 @@ } void LoadingPredictor::CancelPageLoadHint(const GURL& url) { + if (shutdown_) + return; + CancelActiveHint(active_hints_.find(url)); } void LoadingPredictor::StartInitialization() { + if (shutdown_) + return; + resource_prefetch_predictor_->StartInitialization(); } @@ -94,6 +96,7 @@ } void LoadingPredictor::Shutdown() { + DCHECK(!shutdown_); resource_prefetch_predictor_->Shutdown(); std::vector<std::unique_ptr<ResourcePrefetcher>> prefetchers; @@ -106,10 +109,13 @@ base::BindOnce([](std::vector<std::unique_ptr<ResourcePrefetcher>>, std::unique_ptr<PreconnectManager>) {}, std::move(prefetchers), std::move(preconnect_manager_))); + shutdown_ = true; } void LoadingPredictor::OnMainFrameRequest(const URLRequestSummary& summary) { DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); + if (shutdown_) + return; const NavigationID& navigation_id = summary.navigation_id; CleanupAbandonedHintsAndNavigations(navigation_id); @@ -119,6 +125,8 @@ void LoadingPredictor::OnMainFrameRedirect(const URLRequestSummary& summary) { DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); + if (shutdown_) + return; auto it = active_navigations_.find(summary.navigation_id); if (it != active_navigations_.end()) { @@ -133,6 +141,8 @@ void LoadingPredictor::OnMainFrameResponse(const URLRequestSummary& summary) { DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); + if (shutdown_) + return; const NavigationID& navigation_id = summary.navigation_id; auto it = active_navigations_.find(navigation_id); @@ -245,12 +255,13 @@ ResourcePrefetcher* prefetcher, std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::string host = prefetcher->main_frame_url().host(); - auto it = prefetches_.find(host); - // Can happen after Shutdown() has been called, since it purges |prefetches_|. - if (it == prefetches_.end()) + if (shutdown_) return; + std::string host = prefetcher->main_frame_url().host(); + auto it = prefetches_.find(host); + + DCHECK(it != prefetches_.end()); DCHECK(it->second.first.get() == prefetcher); stats_collector_->RecordPrefetcherStats(std::move(stats)); @@ -271,9 +282,10 @@ const std::vector<GURL>& preconnect_origins, const std::vector<GURL>& preresolve_hosts, HintOrigin origin) { - // In case Shutdown() has been already called. - if (!preconnect_manager_) - return; + if (!preconnect_manager_) { + preconnect_manager_ = base::MakeUnique<PreconnectManager>( + GetWeakPtr(), profile_->GetRequestContext()); + } content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, @@ -283,7 +295,6 @@ } void LoadingPredictor::MaybeRemovePreconnect(const GURL& url) { - // In case Shutdown() has been already called. if (!preconnect_manager_) return; @@ -295,6 +306,9 @@ void LoadingPredictor::PreconnectFinished(const GURL& url) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (shutdown_) + return; + NOTIMPLEMENTED(); }
diff --git a/chrome/browser/predictors/loading_predictor.h b/chrome/browser/predictors/loading_predictor.h index 113f1c4..c47e8f8e 100644 --- a/chrome/browser/predictors/loading_predictor.h +++ b/chrome/browser/predictors/loading_predictor.h
@@ -131,6 +131,7 @@ std::map<std::string, std::pair<std::unique_ptr<ResourcePrefetcher>, bool>> prefetches_; TestLoadingObserver* observer_; + bool shutdown_ = false; friend class LoadingPredictorTest; FRIEND_TEST_ALL_PREFIXES(LoadingPredictorTest,
diff --git a/chrome/browser/predictors/preconnect_manager.cc b/chrome/browser/predictors/preconnect_manager.cc index e6987e3..1dfb037 100644 --- a/chrome/browser/predictors/preconnect_manager.cc +++ b/chrome/browser/predictors/preconnect_manager.cc
@@ -40,6 +40,7 @@ inflight_preresolves_count_(0), weak_factory_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(context_getter_); } PreconnectManager::~PreconnectManager() {
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc index 104ffbf..84dbea72 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -44,10 +44,6 @@ #include "ui/keyboard/keyboard_controller.h" #include "ui/views/mus/mus_client.h" -#if BUILDFLAG(ENABLE_WAYLAND_SERVER) -#include "chrome/browser/exo_parts.h" -#endif - ChromeBrowserMainExtraPartsAsh::ChromeBrowserMainExtraPartsAsh() {} ChromeBrowserMainExtraPartsAsh::~ChromeBrowserMainExtraPartsAsh() {} @@ -121,19 +117,9 @@ keyboard::InitializeKeyboard(); ui::SelectFileDialog::SetFactory(new SelectFileDialogExtensionFactory); - -#if BUILDFLAG(ENABLE_WAYLAND_SERVER) - exo_parts_ = ExoParts::CreateIfNecessary(); -#endif } void ChromeBrowserMainExtraPartsAsh::PostProfileInit() { -#if BUILDFLAG(ENABLE_WAYLAND_SERVER) - // ExoParts uses state from ash, delete it before ash so that exo can - // uninstall correctly. - exo_parts_.reset(); -#endif - if (ash_util::IsRunningInMash()) { DCHECK(!ash::Shell::HasInstance()); DCHECK(!ChromeLauncherController::instance());
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h index 790cbc1b..8b297d5b 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
@@ -9,7 +9,6 @@ #include "base/macros.h" #include "chrome/browser/chrome_browser_main_extra_parts.h" -#include "chrome/common/features.h" namespace ash { class ShelfModel; @@ -38,10 +37,6 @@ class VolumeController; class VpnListForwarder; -#if BUILDFLAG(ENABLE_WAYLAND_SERVER) -class ExoParts; -#endif - // Browser initialization for Ash. Only runs on Chrome OS. // TODO(jamescook): Fold this into ChromeBrowserMainPartsChromeOS. class ChromeBrowserMainExtraPartsAsh : public ChromeBrowserMainExtraParts { @@ -80,10 +75,6 @@ std::unique_ptr<ui::UserActivityDetector> user_activity_detector_; std::unique_ptr<aura::UserActivityForwarder> user_activity_forwarder_; -#if BUILDFLAG(ENABLE_WAYLAND_SERVER) - std::unique_ptr<ExoParts> exo_parts_; -#endif - DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsAsh); };
diff --git a/chrome/browser/ui/views/tabs/new_tab_promo.cc b/chrome/browser/ui/views/tabs/new_tab_promo.cc index 4e5bf62ee..b3b8f6f 100644 --- a/chrome/browser/ui/views/tabs/new_tab_promo.cc +++ b/chrome/browser/ui/views/tabs/new_tab_promo.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/tabs/new_tab_promo.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc index 5e40627db..ea053368 100644 --- a/chromeos/audio/cras_audio_handler.cc +++ b/chromeos/audio/cras_audio_handler.cc
@@ -306,6 +306,15 @@ return true; } +const AudioDevice* CrasAudioHandler::GetDeviceByType(AudioDeviceType type) { + for (const auto& item : audio_devices_) { + const AudioDevice& device = item.second; + if (device.type == type) + return &device; + } + return nullptr; +} + void CrasAudioHandler::SetKeyboardMicActive(bool active) { const AudioDevice* keyboard_mic = GetKeyboardMic(); if (!keyboard_mic) @@ -1531,15 +1540,6 @@ return nullptr; } -const AudioDevice* CrasAudioHandler::GetDeviceByType(AudioDeviceType type) { - for (const auto& item : audio_devices_) { - const AudioDevice& device = item.second; - if (device.type == type) - return &device; - } - return nullptr; -} - bool CrasAudioHandler::HasDualInternalMic() const { bool has_front_mic = false; bool has_rear_mic = false;
diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h index b4e3b9fe..9f06bae5 100644 --- a/chromeos/audio/cras_audio_handler.h +++ b/chromeos/audio/cras_audio_handler.h
@@ -164,6 +164,11 @@ bool GetPrimaryActiveOutputDevice(AudioDevice* device) const; + // Returns the device matched with |type|. Assuming there is only one device + // matched the |type|, if there is more than one matched devices, it will + // return the first one found. + const AudioDevice* GetDeviceByType(AudioDeviceType type); + // Whether there is alternative input/output audio device. bool has_alternative_input() const; bool has_alternative_output() const; @@ -461,11 +466,6 @@ // Returns the microphone for the camera with |camera_facing|. const AudioDevice* GetMicForCamera(media::VideoFacingMode camera_facing); - // Returns the device matched with |type|. Assuming there is only one device - // matched the |type|, if there is more than one matched devices, it will - // return the first one found. - const AudioDevice* GetDeviceByType(AudioDeviceType type); - bool IsCameraOn() const; // Returns true if there are any external devices.
diff --git a/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc b/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc index f20cb554..b176aca 100644 --- a/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc +++ b/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
@@ -11,6 +11,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" +#include "base/test/mock_callback.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/image_fetcher/core/image_decoder.h" @@ -25,9 +26,11 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_unittest_util.h" using testing::_; using testing::Eq; +using testing::Property; namespace ntp_snippets { @@ -37,12 +40,19 @@ const char kImageURL[] = "http://image.test/test.png"; const char kSnippetID[] = "http://localhost"; -class MockImageDecoder : public image_fetcher::ImageDecoder { +// Always decodes a valid image for all non-empty input. +class FakeImageDecoder : public image_fetcher::ImageDecoder { public: - MOCK_METHOD3(DecodeImage, - void(const std::string& image_data, - const gfx::Size& desired_image_frame_size, - const image_fetcher::ImageDecodedCallback& callback)); + void DecodeImage( + const std::string& image_data, + const gfx::Size& desired_image_frame_size, + const image_fetcher::ImageDecodedCallback& callback) override { + gfx::Image image; + if (!image_data.empty()) { + image = gfx::test::CreateImage(); + } + callback.Run(image); + } }; } // namespace @@ -61,8 +71,8 @@ request_context_getter_ = scoped_refptr<net::TestURLRequestContextGetter>( new net::TestURLRequestContextGetter(mock_task_runner_.get())); - auto decoder = base::MakeUnique<MockImageDecoder>(); - mock_image_decoder_ = decoder.get(); + auto decoder = base::MakeUnique<FakeImageDecoder>(); + fake_image_decoder_ = decoder.get(); cached_image_fetcher_ = base::MakeUnique<ntp_snippets::CachedImageFetcher>( base::MakeUnique<image_fetcher::ImageFetcherImpl>( std::move(decoder), request_context_getter_.get()), @@ -71,32 +81,27 @@ EXPECT_TRUE(database_->IsInitialized()); } - void FetchImage() { + void FetchImage(const ImageFetchedCallback& callback) { ContentSuggestion::ID content_suggestion_id( Category::FromKnownCategory(KnownCategories::ARTICLES), kSnippetID); - cached_image_fetcher_->FetchSuggestionImage( - content_suggestion_id, GURL(kImageURL), - base::Bind(&CachedImageFetcherTest::OnImageFetched, - base::Unretained(this))); + cached_image_fetcher_->FetchSuggestionImage(content_suggestion_id, + GURL(kImageURL), callback); } - // TODO(gaschler): add a test where decoder runs this callback - void OnImageFetched(const gfx::Image&) {} - void RunUntilIdle() { mock_task_runner_->RunUntilIdle(); } RemoteSuggestionsDatabase* database() { return database_.get(); } + FakeImageDecoder* fake_image_decoder() { return fake_image_decoder_; } net::FakeURLFetcherFactory* fake_url_fetcher_factory() { return &fake_url_fetcher_factory_; } - MockImageDecoder* mock_image_decoder() { return mock_image_decoder_; } private: std::unique_ptr<CachedImageFetcher> cached_image_fetcher_; std::unique_ptr<RemoteSuggestionsDatabase> database_; base::ScopedTempDir database_dir_; + FakeImageDecoder* fake_image_decoder_; net::FakeURLFetcherFactory fake_url_fetcher_factory_; - MockImageDecoder* mock_image_decoder_; scoped_refptr<base::TestSimpleTaskRunner> mock_task_runner_; base::ThreadTaskRunnerHandle mock_task_runner_handle_; TestingPrefServiceSimple pref_service_; @@ -112,8 +117,10 @@ // Do not provide any URL responses and expect that the image is fetched (from // cache). - EXPECT_CALL(*mock_image_decoder(), DecodeImage(kImageData, _, _)); - FetchImage(); + base::MockCallback<ImageFetchedCallback> mock_image_fetched_callback; + EXPECT_CALL(mock_image_fetched_callback, + Run(Property(&gfx::Image::IsEmpty, Eq(false)))); + FetchImage(mock_image_fetched_callback.Get()); RunUntilIdle(); } @@ -122,8 +129,10 @@ fake_url_fetcher_factory()->SetFakeResponse(GURL(kImageURL), kImageData, net::HTTP_OK, net::URLRequestStatus::SUCCESS); - EXPECT_CALL(*mock_image_decoder(), DecodeImage(kImageData, _, _)); - FetchImage(); + base::MockCallback<ImageFetchedCallback> mock_image_fetched_callback; + EXPECT_CALL(mock_image_fetched_callback, + Run(Property(&gfx::Image::IsEmpty, Eq(false)))); + FetchImage(mock_image_fetched_callback.Get()); RunUntilIdle(); } @@ -132,11 +141,12 @@ fake_url_fetcher_factory()->SetFakeResponse(GURL(kImageURL), kErrorResponse, net::HTTP_NOT_FOUND, net::URLRequestStatus::FAILED); - // Expect that decoder is called even if URL cannot be requested, - // then with empty image data. + // Expect an empty image is fetched if the URL cannot be requested. const std::string kEmptyImageData; - EXPECT_CALL(*mock_image_decoder(), DecodeImage(kEmptyImageData, _, _)); - FetchImage(); + base::MockCallback<ImageFetchedCallback> mock_image_fetched_callback; + EXPECT_CALL(mock_image_fetched_callback, + Run(Property(&gfx::Image::IsEmpty, Eq(true)))); + FetchImage(mock_image_fetched_callback.Get()); RunUntilIdle(); }
diff --git a/components/proximity_auth/BUILD.gn b/components/proximity_auth/BUILD.gn index 66a7dc20..77f4291b 100644 --- a/components/proximity_auth/BUILD.gn +++ b/components/proximity_auth/BUILD.gn
@@ -23,6 +23,8 @@ "messenger_observer.h", "metrics.cc", "metrics.h", + "promotion_manager.cc", + "promotion_manager.h", "proximity_auth_client.h", "proximity_auth_pref_manager.cc", "proximity_auth_pref_manager.h", @@ -100,6 +102,7 @@ "bluetooth_connection_unittest.cc", "bluetooth_low_energy_connection_finder_unittest.cc", "messenger_impl_unittest.cc", + "promotion_manager_unittests.cc", "proximity_auth_pref_manager_unittest.cc", "proximity_auth_system_unittest.cc", "proximity_monitor_impl_unittest.cc",
diff --git a/components/proximity_auth/promotion_manager.cc b/components/proximity_auth/promotion_manager.cc new file mode 100644 index 0000000..3c316f7 --- /dev/null +++ b/components/proximity_auth/promotion_manager.cc
@@ -0,0 +1,159 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "components/proximity_auth/promotion_manager.h" + +#include <stdlib.h> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/rand_util.h" +#include "base/task_runner.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "components/cryptauth/cryptauth_client.h" +#include "components/cryptauth/local_device_data_provider.h" +#include "components/proximity_auth/logging/logging.h" +#include "components/proximity_auth/proximity_auth_pref_manager.h" + +namespace proximity_auth { +namespace { + +// The minimun between two consecutive promotion checks. +const int64_t kFreshnessPeriodMs = 24 * 60 * 60 * 1000; + +// The number of seconds to wait for phones to contact CryptAuth +// before calling the FindEligigleUnlockDevices API. +const int64_t kWaitForPhoneOnlineDelaySec = 10; + +// The probably for each operation to actually check with CryptAuth. +const double kCheckEligibilityProbability = 0.2; + +} // namespace + +PromotionManager::PromotionManager( + cryptauth::LocalDeviceDataProvider* provider, + ProximityAuthPrefManager* pref_manager, + std::unique_ptr<cryptauth::CryptAuthClientFactory> client_factory, + std::unique_ptr<base::Clock> clock, + scoped_refptr<base::TaskRunner> task_runner) + : check_eligibility_probability_(kCheckEligibilityProbability), + local_device_data_provider_(provider), + pref_manager_(pref_manager), + client_factory_(std::move(client_factory)), + clock_(std::move(clock)), + task_runner_(task_runner), + weak_ptr_factory_(this) {} + +PromotionManager::~PromotionManager() { + if (ScreenlockBridge::Get()) { + ScreenlockBridge::Get()->RemoveObserver(this); + } +} + +void PromotionManager::Start() { + ScreenlockBridge::Get()->AddObserver(this); +} + +void PromotionManager::OnFocusedUserChanged(const AccountId& account_id) {} + +void PromotionManager::OnScreenDidLock( + ScreenlockBridge::LockHandler::ScreenType screen_type) {} + +void PromotionManager::OnScreenDidUnlock( + ScreenlockBridge::LockHandler::ScreenType screen_type) { + if (!HasFreshnessPeriodElapsed()) { + return; + } + PA_LOG(INFO) << "[Promotion] Fresh period elapsed. Starting the flow."; + if (!RollForPromotionCheck()) { + return; + } + client_ = client_factory_->CreateInstance(); + + std::string public_key; + local_device_data_provider_->GetLocalDeviceData(&public_key, nullptr); + cryptauth::FindEligibleForPromotionRequest request; + request.set_promoter_public_key(public_key); + client_->FindEligibleForPromotion( + request, + base::Bind(&PromotionManager::OnFindEligibleForPromotionSuccess, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PromotionManager::OnFindEligibleForPromotionFailure, + weak_ptr_factory_.GetWeakPtr())); +} + +bool PromotionManager::HasFreshnessPeriodElapsed() { + int64_t now_ms = clock_->Now().ToJavaTime(); + int64_t elapsed_time_since_last_check = + now_ms - pref_manager_->GetLastPromotionCheckTimestampMs(); + if (elapsed_time_since_last_check < kFreshnessPeriodMs) { + return false; + } + pref_manager_->SetLastPromotionCheckTimestampMs(now_ms); + return true; +} + +bool PromotionManager::RollForPromotionCheck() { + bool success = base::RandDouble() < check_eligibility_probability_; + if (!success) { + PA_LOG(INFO) << "[Promotion] Roll uncessful. Stopping the flow."; + } + return success; +} + +void PromotionManager::OnFindEligibleForPromotionFailure( + const std::string& error) { + client_.reset(); + PA_LOG(WARNING) << "[Promotion] FindEligibleForPromotion failed: " << error; +} + +void PromotionManager::OnFindEligibleForPromotionSuccess( + const cryptauth::FindEligibleForPromotionResponse& response) { + client_.reset(); + if (!response.may_show_promo()) { + PA_LOG(INFO) << "[Promotion] Local device not eligible for promo."; + return; + } + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&PromotionManager::FindEligibleUnlockDevices, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromSeconds(kWaitForPhoneOnlineDelaySec)); +} + +void PromotionManager::FindEligibleUnlockDevices() { + client_ = client_factory_->CreateInstance(); + cryptauth::FindEligibleUnlockDevicesRequest request; + request.set_max_last_update_time_delta_millis(kWaitForPhoneOnlineDelaySec * + 1000); + client_->FindEligibleUnlockDevices( + request, + base::Bind(&PromotionManager::OnFindEligibleUnlockDevicesSuccess, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PromotionManager::OnFindEligibleUnlockDevicesFailure, + weak_ptr_factory_.GetWeakPtr())); +} + +void PromotionManager::OnFindEligibleUnlockDevicesFailure( + const std::string& error) { + client_.reset(); + PA_LOG(WARNING) << "[Promotion] FindEligibleUnlockDevices failed: " << error; +} + +void PromotionManager::OnFindEligibleUnlockDevicesSuccess( + const cryptauth::FindEligibleUnlockDevicesResponse& response) { + client_.reset(); + if (response.eligible_devices_size() == 0) { + PA_LOG(INFO) << "[Promotion] No eligible unlock devices found."; + return; + } + ShowPromotion(); +} + +void PromotionManager::ShowPromotion() { + PA_LOG(INFO) << "[Promotion] Showing promotion for the user."; + // TODO(sacomoto): Actually display the promotion message. +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/promotion_manager.h b/components/proximity_auth/promotion_manager.h new file mode 100644 index 0000000..6ec838f --- /dev/null +++ b/components/proximity_auth/promotion_manager.h
@@ -0,0 +1,106 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PROXIMITY_AUTH_PROMOTION_MANAGER_H +#define COMPONENTS_PROXIMITY_AUTH_PROMOTION_MANAGER_H + +#include <memory> + +#include "components/cryptauth/proto/cryptauth_api.pb.h" +#include "components/proximity_auth/screenlock_bridge.h" + +namespace base { +class Clock; +class TaskRunner; +} // namespace base + +namespace cryptauth { +class CryptAuthClient; +class CryptAuthClientFactory; +class LocalDeviceDataProvider; +} // namespace cryptauth + +namespace proximity_auth { + +class ProximityAuthPrefManager; + +// The PromotionManager periodically checks with CryptAuth to determine if the +// user is eligible to be shown a promotion notification (eg. the user must have +// a phone). Once Smart Lock is set up, this promotion will no longer be shown. +class PromotionManager : public ScreenlockBridge::Observer { + public: + PromotionManager( + cryptauth::LocalDeviceDataProvider* local_device_data_provider, + ProximityAuthPrefManager* pref_manager, + std::unique_ptr<cryptauth::CryptAuthClientFactory> client_factory, + std::unique_ptr<base::Clock> clock, + scoped_refptr<base::TaskRunner> task_runner); + ~PromotionManager() override; + + void Start(); + + void set_check_eligibility_probability(double probability) { + check_eligibility_probability_ = probability; + } + + private: + // ScreenlockBridge::Observer + void OnFocusedUserChanged(const AccountId& account_id) override; + void OnScreenDidLock( + ScreenlockBridge::LockHandler::ScreenType screen_type) override; + void OnScreenDidUnlock( + ScreenlockBridge::LockHandler::ScreenType screen_type) override; + + // True if the freshness period since the last check has elapsed. Updates the + // last check timestamp if necessary. + bool HasFreshnessPeriodElapsed(); + + // True if it should continue with the promotion check. + bool RollForPromotionCheck(); + + // FindEligibleForPromotion callbacks. + void OnFindEligibleForPromotionSuccess( + const cryptauth::FindEligibleForPromotionResponse& response); + void OnFindEligibleForPromotionFailure(const std::string& error); + + // FindEligibleUnlockDevices callbacks. + void OnFindEligibleUnlockDevicesSuccess( + const cryptauth::FindEligibleUnlockDevicesResponse& response); + void OnFindEligibleUnlockDevicesFailure(const std::string& error); + + // Send the FindEligigleUnlockDevices query to CryptAuth. + void FindEligibleUnlockDevices(); + + // Show the EasyUnlock promotion. + void ShowPromotion(); + + // The probability for each operation to actually check with CryptAuth. + double check_eligibility_probability_; + + // Provides the local device information, e.g. public key. + cryptauth::LocalDeviceDataProvider* local_device_data_provider_; + + // Used to store the last a promotion check was done. + ProximityAuthPrefManager* pref_manager_; + + // The factory for |client_| instances. + std::unique_ptr<cryptauth::CryptAuthClientFactory> client_factory_; + + // The client used to make request to CryptAuth. + std::unique_ptr<cryptauth::CryptAuthClient> client_; + + // Used to determine the time. + std::unique_ptr<base::Clock> clock_; + + // Used to schedule delayed tasks. + scoped_refptr<base::TaskRunner> task_runner_; + + base::WeakPtrFactory<PromotionManager> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PromotionManager); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_PROMOTION_MANAGER_H
diff --git a/components/proximity_auth/promotion_manager_unittests.cc b/components/proximity_auth/promotion_manager_unittests.cc new file mode 100644 index 0000000..48c3d9ef --- /dev/null +++ b/components/proximity_auth/promotion_manager_unittests.cc
@@ -0,0 +1,240 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/proximity_auth/promotion_manager.h" + +#include <string> + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/weak_ptr.h" +#include "base/test/simple_test_clock.h" +#include "base/test/test_simple_task_runner.h" +#include "components/cryptauth/mock_cryptauth_client.h" +#include "components/cryptauth/mock_local_device_data_provider.h" +#include "components/proximity_auth/fake_lock_handler.h" +#include "components/proximity_auth/proximity_auth_pref_manager.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::DoAll; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::SaveArg; + +namespace proximity_auth { +namespace { +const int64_t kPreviousCheckTimestampMs = 123456789L; +const int64_t kFreshnessPeriodMs = 24 * 60 * 60 * 1000; +const char kPublicKey[] = "public key"; + +// ExternalDeviceInfo fields for the eligible unlock key. +const char kPublicKey1[] = "GOOG"; +const char kDeviceName1[] = "Nexus 5"; +const char kBluetoothAddress1[] = "aa:bb:cc:ee:dd:ff"; +const bool kUnlockKey1 = true; +const bool kUnlockable1 = false; +} // namespace + +// Mock implementation of ProximityAuthPrefManager. +class MockProximityAuthPrefManager : public ProximityAuthPrefManager { + public: + MockProximityAuthPrefManager() : ProximityAuthPrefManager(nullptr) {} + ~MockProximityAuthPrefManager() override {} + + MOCK_METHOD1(SetLastPromotionCheckTimestampMs, void(int64_t)); + MOCK_CONST_METHOD0(GetLastPromotionCheckTimestampMs, int64_t()); + + private: + DISALLOW_COPY_AND_ASSIGN(MockProximityAuthPrefManager); +}; + +class ProximityAuthPromotionManagerTest + : public testing::Test, + public cryptauth::MockCryptAuthClientFactory::Observer { + protected: + ProximityAuthPromotionManagerTest() + : local_device_data_provider_( + new cryptauth::MockLocalDeviceDataProvider()), + clock_(new base::SimpleTestClock()), + expect_eligible_unlock_devices_request_(false), + client_factory_(new cryptauth::MockCryptAuthClientFactory( + cryptauth::MockCryptAuthClientFactory::MockType:: + MAKE_STRICT_MOCKS)), + pref_manager_(new NiceMock<MockProximityAuthPrefManager>()), + task_runner_(new base::TestSimpleTaskRunner), + promotion_manager_( + new PromotionManager(local_device_data_provider_.get(), + pref_manager_.get(), + base::WrapUnique(client_factory_), + base::WrapUnique(clock_), + task_runner_)) { + client_factory_->AddObserver(this); + local_device_data_provider_->SetPublicKey( + base::MakeUnique<std::string>(kPublicKey)); + + unlock_key_.set_public_key(kPublicKey1); + unlock_key_.set_friendly_device_name(kDeviceName1); + unlock_key_.set_bluetooth_address(kBluetoothAddress1); + unlock_key_.set_unlock_key(kUnlockKey1); + unlock_key_.set_unlockable(kUnlockable1); + } + + ~ProximityAuthPromotionManagerTest() override { + client_factory_->RemoveObserver(this); + } + + void SetUp() override { + promotion_manager_->set_check_eligibility_probability(2.0); + promotion_manager_->Start(); + LockScreen(); + } + + // MockCryptAuthClientFactory::Observer: + void OnCryptAuthClientCreated( + cryptauth::MockCryptAuthClient* client) override { + if (expect_eligible_unlock_devices_request_) { + EXPECT_CALL(*client, FindEligibleUnlockDevices(_, _, _)) + .WillOnce( + DoAll(SaveArg<0>(&find_eligible_unlock_devices_request_), + SaveArg<1>(&find_eligible_unlock_devices_success_callback_), + SaveArg<2>(&find_eligible_unlock_devices_error_callback_))); + } else { + EXPECT_CALL(*client, FindEligibleForPromotion(_, _, _)) + .WillOnce( + DoAll(SaveArg<0>(&find_eligible_for_promotion_request_), + SaveArg<1>(&find_eligible_for_promotion_success_callback_), + SaveArg<2>(&find_eligible_for_promotion_error_callback_))); + } + } + + void LockScreen() { ScreenlockBridge::Get()->SetLockHandler(&lock_handler_); } + void UnlockScreen() { ScreenlockBridge::Get()->SetLockHandler(nullptr); } + + void ExpectFreshnessPeriodElapsed() { + EXPECT_CALL(*pref_manager_, GetLastPromotionCheckTimestampMs()) + .WillOnce(Return(kPreviousCheckTimestampMs)); + const int64_t now = kPreviousCheckTimestampMs + kFreshnessPeriodMs + 1; + clock_->SetNow(base::Time::FromJavaTime(now)); + EXPECT_CALL(*pref_manager_, SetLastPromotionCheckTimestampMs(now)); + } + + FakeLockHandler lock_handler_; + std::unique_ptr<cryptauth::MockLocalDeviceDataProvider> + local_device_data_provider_; + base::SimpleTestClock* clock_; + bool expect_eligible_unlock_devices_request_; + cryptauth::MockCryptAuthClientFactory* client_factory_; + std::unique_ptr<MockProximityAuthPrefManager> pref_manager_; + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + cryptauth::ExternalDeviceInfo unlock_key_; + + // The instance being tested. + std::unique_ptr<PromotionManager> promotion_manager_; + + cryptauth::FindEligibleForPromotionResponse + find_eligible_for_promotion_response_; + cryptauth::FindEligibleForPromotionRequest + find_eligible_for_promotion_request_; + cryptauth::CryptAuthClient::FindEligibleForPromotionCallback + find_eligible_for_promotion_success_callback_; + cryptauth::CryptAuthClient::ErrorCallback + find_eligible_for_promotion_error_callback_; + + cryptauth::FindEligibleUnlockDevicesResponse + find_eligible_unlock_devices_response_; + cryptauth::FindEligibleUnlockDevicesRequest + find_eligible_unlock_devices_request_; + cryptauth::CryptAuthClient::FindEligibleUnlockDevicesCallback + find_eligible_unlock_devices_success_callback_; + cryptauth::CryptAuthClient::ErrorCallback + find_eligible_unlock_devices_error_callback_; +}; + +TEST_F(ProximityAuthPromotionManagerTest, ShowPromotion) { + ExpectFreshnessPeriodElapsed(); + UnlockScreen(); + + // Receives the FindEligibleForPromotion response. + find_eligible_for_promotion_response_.set_may_show_promo(true); + find_eligible_for_promotion_success_callback_.Run( + find_eligible_for_promotion_response_); + + // Waits before sending the FindEligibleUnlockDevices request. + expect_eligible_unlock_devices_request_ = true; + task_runner_->RunUntilIdle(); + + // Receives the FindEligibleUnlockDevices response. + find_eligible_unlock_devices_response_.add_eligible_devices()->CopyFrom( + unlock_key_); + find_eligible_unlock_devices_success_callback_.Run( + find_eligible_unlock_devices_response_); +} + +TEST_F(ProximityAuthPromotionManagerTest, + NoPromotion_FreshnessPeriodNotElapsed) { + EXPECT_CALL(*pref_manager_, GetLastPromotionCheckTimestampMs()) + .WillOnce(Return(kPreviousCheckTimestampMs)); + const int64_t now = kPreviousCheckTimestampMs + 1; + clock_->SetNow(base::Time::FromJavaTime(now)); + UnlockScreen(); +} + +TEST_F(ProximityAuthPromotionManagerTest, NoPromotion_NotEligibleForPromotion) { + ExpectFreshnessPeriodElapsed(); + UnlockScreen(); + + // Receives the FindEligibleForPromotion response. + find_eligible_for_promotion_response_.set_may_show_promo(false); + find_eligible_for_promotion_success_callback_.Run( + find_eligible_for_promotion_response_); +} + +TEST_F(ProximityAuthPromotionManagerTest, + NoPromotion_EligibleForPromotionRequestFailed) { + ExpectFreshnessPeriodElapsed(); + UnlockScreen(); + + // Receives the FindEligibleForPromotion response. + find_eligible_for_promotion_error_callback_.Run("some error"); +} + +TEST_F(ProximityAuthPromotionManagerTest, NoPromotion_NoEligibleUnlockDevices) { + ExpectFreshnessPeriodElapsed(); + UnlockScreen(); + + // Receives the FindEligibleForPromotion response. + find_eligible_for_promotion_response_.set_may_show_promo(true); + find_eligible_for_promotion_success_callback_.Run( + find_eligible_for_promotion_response_); + + // Waits before sending the FindEligibleUnlockDevices request. + expect_eligible_unlock_devices_request_ = true; + task_runner_->RunUntilIdle(); + + // Receives the FindEligibleUnlockDevices response. + find_eligible_unlock_devices_success_callback_.Run( + find_eligible_unlock_devices_response_); +} + +TEST_F(ProximityAuthPromotionManagerTest, + NoPromotion_EligibleUnlockDevicesRequestFailed) { + ExpectFreshnessPeriodElapsed(); + UnlockScreen(); + + // Receives the FindEligibleForPromotion response. + find_eligible_for_promotion_response_.set_may_show_promo(true); + find_eligible_for_promotion_success_callback_.Run( + find_eligible_for_promotion_response_); + + // Waits before sending the FindEligibleUnlockDevices request. + expect_eligible_unlock_devices_request_ = true; + task_runner_->RunUntilIdle(); + + // Receives the FindEligibleUnlockDevices response. + find_eligible_unlock_devices_error_callback_.Run("some error"); +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/proximity_auth_pref_manager.cc b/components/proximity_auth/proximity_auth_pref_manager.cc index 12a1c629..198fe5b 100644 --- a/components/proximity_auth/proximity_auth_pref_manager.cc +++ b/components/proximity_auth/proximity_auth_pref_manager.cc
@@ -27,6 +27,8 @@ user_prefs::PrefRegistrySyncable* registry) { registry->RegisterInt64Pref(prefs::kProximityAuthLastPasswordEntryTimestampMs, 0L); + registry->RegisterInt64Pref( + prefs::kProximityAuthLastPromotionCheckTimestampMs, 0L); registry->RegisterDictionaryPref(prefs::kProximityAuthRemoteBleDevices); registry->RegisterIntegerPref( prefs::kEasyUnlockProximityThreshold, 1, @@ -134,6 +136,17 @@ return pref_service_->GetDictionary(prefs::kProximityAuthRemoteBleDevices); } +void ProximityAuthPrefManager::SetLastPromotionCheckTimestampMs( + int64_t timestamp_ms) { + pref_service_->SetInt64(prefs::kProximityAuthLastPasswordEntryTimestampMs, + timestamp_ms); +} + +int64_t ProximityAuthPrefManager::GetLastPromotionCheckTimestampMs() const { + return pref_service_->GetInt64( + prefs::kProximityAuthLastPasswordEntryTimestampMs); +} + void ProximityAuthPrefManager::SetProximityThreshold(ProximityThreshold value) { pref_service_->SetInteger(prefs::kEasyUnlockProximityThreshold, value); }
diff --git a/components/proximity_auth/proximity_auth_pref_manager.h b/components/proximity_auth/proximity_auth_pref_manager.h index 9418ad52..c102a59 100644 --- a/components/proximity_auth/proximity_auth_pref_manager.h +++ b/components/proximity_auth/proximity_auth_pref_manager.h
@@ -68,6 +68,9 @@ virtual void SetLastPasswordEntryTimestampMs(int64_t timestamp_ms); virtual int64_t GetLastPasswordEntryTimestampMs() const; + virtual void SetLastPromotionCheckTimestampMs(int64_t timestamp_ms); + virtual int64_t GetLastPromotionCheckTimestampMs() const; + // These are arbitrary labels displayed in the settings page for the user // to select. The actual mapping is done in the ProximityMonitorImpl. enum ProximityThreshold {
diff --git a/components/proximity_auth/proximity_auth_pref_manager_unittest.cc b/components/proximity_auth/proximity_auth_pref_manager_unittest.cc index 1c250775..9deed15a3 100644 --- a/components/proximity_auth/proximity_auth_pref_manager_unittest.cc +++ b/components/proximity_auth/proximity_auth_pref_manager_unittest.cc
@@ -27,6 +27,9 @@ const int64_t kPasswordEntryTimestampMs1 = 123456789L; const int64_t kPasswordEntryTimestampMs2 = 987654321L; +const int64_t kPromotionCheckTimestampMs1 = 1111111111L; +const int64_t kPromotionCheckTimestampMs2 = 2222222222L; + const ProximityAuthPrefManager::ProximityThreshold kProximityThreshold1 = ProximityAuthPrefManager::ProximityThreshold::kFar; const ProximityAuthPrefManager::ProximityThreshold kProximityThreshold2 = @@ -175,6 +178,17 @@ pref_manager.GetLastPasswordEntryTimestampMs()); } +TEST_F(ProximityAuthProximityAuthPrefManagerTest, LastPromotionCheckTimestamp) { + ProximityAuthPrefManager pref_manager(&pref_service_); + EXPECT_EQ(0L, pref_manager.GetLastPromotionCheckTimestampMs()); + pref_manager.SetLastPromotionCheckTimestampMs(kPromotionCheckTimestampMs1); + EXPECT_EQ(kPromotionCheckTimestampMs1, + pref_manager.GetLastPromotionCheckTimestampMs()); + pref_manager.SetLastPromotionCheckTimestampMs(kPromotionCheckTimestampMs2); + EXPECT_EQ(kPromotionCheckTimestampMs2, + pref_manager.GetLastPromotionCheckTimestampMs()); +} + TEST_F(ProximityAuthProximityAuthPrefManagerTest, ProximityThreshold) { ProximityAuthPrefManager pref_manager(&pref_service_); EXPECT_EQ(1, pref_manager.GetProximityThreshold());
diff --git a/components/proximity_auth/proximity_auth_pref_names.cc b/components/proximity_auth/proximity_auth_pref_names.cc index 31abf9b..bd5d956 100644 --- a/components/proximity_auth/proximity_auth_pref_names.cc +++ b/components/proximity_auth/proximity_auth_pref_names.cc
@@ -12,6 +12,10 @@ const char kProximityAuthLastPasswordEntryTimestampMs[] = "proximity_auth.last_password_entry_timestamp_ms"; +// The timestamp of the last promotion check in milliseconds. +const char kProximityAuthLastPromotionCheckTimestampMs[] = + "proximity_auth.last_promotion_check_timestamp_ms"; + // The dictionary containing remote BLE devices. const char kProximityAuthRemoteBleDevices[] = "proximity_auth.remote_ble_devices";
diff --git a/components/proximity_auth/proximity_auth_pref_names.h b/components/proximity_auth/proximity_auth_pref_names.h index abc7a57..50bb7c2 100644 --- a/components/proximity_auth/proximity_auth_pref_names.h +++ b/components/proximity_auth/proximity_auth_pref_names.h
@@ -10,6 +10,7 @@ extern const char kEasyUnlockProximityThreshold[]; extern const char kProximityAuthLastPasswordEntryTimestampMs[]; +extern const char kProximityAuthLastPromotionCheckTimestampMs[]; extern const char kProximityAuthRemoteBleDevices[]; extern const char kProximityAuthIsChromeOSLoginEnabled[];
diff --git a/components/ui_devtools/views/ui_devtools_dom_agent.cc b/components/ui_devtools/views/ui_devtools_dom_agent.cc index c4c3cbf..1e7638b 100644 --- a/components/ui_devtools/views/ui_devtools_dom_agent.cc +++ b/components/ui_devtools/views/ui_devtools_dom_agent.cc
@@ -4,6 +4,7 @@ #include "components/ui_devtools/views/ui_devtools_dom_agent.h" +#include "base/memory/ptr_util.h" #include "components/ui_devtools/devtools_server.h" #include "components/ui_devtools/views/ui_element.h" #include "components/ui_devtools/views/view_element.h"
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index f5b2aa5..6518cd2 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -427,6 +427,7 @@ Maybe<double> margin_left, Maybe<double> margin_right, Maybe<String> page_ranges, + Maybe<bool> ignore_invalid_page_ranges, std::unique_ptr<PrintToPDFCallback> callback) { callback->sendFailure(Response::Error("PrintToPDF is not implemented")); return;
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index 45ac79d..c03d5bc 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -96,6 +96,7 @@ Maybe<double> margin_left, Maybe<double> margin_right, Maybe<String> page_ranges, + Maybe<bool> ignore_invalid_page_ranges, std::unique_ptr<PrintToPDFCallback> callback) override; Response StartScreencast(Maybe<std::string> format, Maybe<int> quality,
diff --git a/content/browser/tracing/memory_instrumentation_browsertest.cc b/content/browser/tracing/memory_instrumentation_browsertest.cc new file mode 100644 index 0000000..ce347fd --- /dev/null +++ b/content/browser/tracing/memory_instrumentation_browsertest.cc
@@ -0,0 +1,119 @@ +// 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 <stdint.h> + +#include "base/bind.h" +#include "base/run_loop.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::Le; +using testing::Ge; +using testing::AllOf; +using memory_instrumentation::mojom::GlobalMemoryDumpPtr; +using memory_instrumentation::mojom::GlobalMemoryDump; +using memory_instrumentation::mojom::ProcessMemoryDumpPtr; +using memory_instrumentation::mojom::ProcessMemoryDump; +using memory_instrumentation::mojom::ProcessType; + +namespace content { + +class MemoryInstrumentationTest : public ContentBrowserTest { + protected: + void Navigate(Shell* shell) { + NavigateToURL(shell, GetTestUrl("", "title.html")); + } +}; + +uint64_t GetPrivateFootprintKb(ProcessType type, + const GlobalMemoryDump& global_dump) { + ProcessMemoryDump* target_dump = nullptr; + for (const ProcessMemoryDumpPtr& dump : global_dump.process_dumps) { + if (dump->process_type == type) { + EXPECT_FALSE(target_dump); + target_dump = dump.get(); + } + } + EXPECT_TRUE(target_dump); + return target_dump->os_dump->private_footprint_kb; +} + +GlobalMemoryDumpPtr DoGlobalDump() { + GlobalMemoryDumpPtr result = nullptr; + base::RunLoop run_loop; + memory_instrumentation::MemoryInstrumentation::GetInstance() + ->RequestGlobalDump(base::Bind( + [](base::Closure quit_closure, GlobalMemoryDumpPtr* out_result, + bool success, GlobalMemoryDumpPtr result) { + EXPECT_TRUE(success); + *out_result = std::move(result); + quit_closure.Run(); + }, + run_loop.QuitClosure(), &result)); + run_loop.Run(); + return result; +} + +// ASAN and TSAN fake some sys calls we need meaning we never get dumps for the +// processes. +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_PrivateFootprintComputation DISABLED_PrivateFootprintComputation +#else +#define MAYBE_PrivateFootprintComputation PrivateFootprintComputatio +#endif + +// Despite the location, this test is not tracing related. +// TODO(hjd): Move this once we have a resource_coordinator folder in browser. +IN_PROC_BROWSER_TEST_F(MemoryInstrumentationTest, + MAYBE_PrivateFootprintComputation) { + Navigate(shell()); + + // We have to pick a big size (>=64mb) to avoid an implementation detail of + // malloc on MacOS which doesn't free or mark as reusable small allocations + // after a free. + const int64_t kAllocSize = 65 * 1024 * 1024; + const int64_t kAllocSizeKb = kAllocSize / 1024; + + GlobalMemoryDumpPtr before_ptr = DoGlobalDump(); + + std::unique_ptr<char[]> buffer = base::MakeUnique<char[]>(kAllocSize); + memset(buffer.get(), 1, kAllocSize); + volatile char* x = static_cast<volatile char*>(buffer.get()); + EXPECT_EQ(x[0] + x[kAllocSize - 1], 2); + + content::WebContents* web_contents = shell()->web_contents(); + // Should allocate at least 4*10^6 / 1024 = 4000kb. + EXPECT_TRUE(content::ExecuteScript(web_contents, + "var a = Array(1000000).fill(1234);\n")); + + GlobalMemoryDumpPtr during_ptr = DoGlobalDump(); + + buffer.reset(); + + GlobalMemoryDumpPtr after_ptr = DoGlobalDump(); + + int64_t before_kb = GetPrivateFootprintKb(ProcessType::BROWSER, *before_ptr); + int64_t during_kb = GetPrivateFootprintKb(ProcessType::BROWSER, *during_ptr); + int64_t after_kb = GetPrivateFootprintKb(ProcessType::BROWSER, *after_ptr); + + EXPECT_THAT(after_kb - before_kb, + AllOf(Ge(-kAllocSizeKb / 10), Le(kAllocSizeKb / 10))); + EXPECT_THAT(during_kb - before_kb, + AllOf(Ge(kAllocSizeKb - 3000), Le(kAllocSizeKb + 3000))); + EXPECT_THAT(during_kb - after_kb, + AllOf(Ge(kAllocSizeKb - 3000), Le(kAllocSizeKb + 3000))); + + int64_t before_renderer_kb = + GetPrivateFootprintKb(ProcessType::RENDERER, *before_ptr); + int64_t during_renderer_kb = + GetPrivateFootprintKb(ProcessType::RENDERER, *during_ptr); + EXPECT_GE(during_renderer_kb - before_renderer_kb, 3000); +} + +} // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 88b0b0f..1d842a1 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -239,6 +239,10 @@ const base::Feature kRenderingPipelineThrottling{ "RenderingPipelineThrottling", base::FEATURE_ENABLED_BY_DEFAULT}; +// Collect renderer peak memory usage during page loads. +const base::Feature kReportRendererPeakMemoryStats{ + "ReportRendererPeakMemoryStats", base::FEATURE_DISABLED_BY_DEFAULT}; + // Require camera/mic requests from pepper plugins to be made from secure // origins. const base::Feature kRequireSecureOriginsForPepperMediaRequests{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index ea57fb06..cb04406f 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -64,6 +64,7 @@ CONTENT_EXPORT extern const base::Feature kRafAlignedMouseInputEvents; CONTENT_EXPORT extern const base::Feature kRafAlignedTouchInputEvents; CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling; +CONTENT_EXPORT extern const base::Feature kReportRendererPeakMemoryStats; CONTENT_EXPORT extern const base::Feature kRequireSecureOriginsForPepperMediaRequests; CONTENT_EXPORT extern const base::Feature kResourceLoadScheduler;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 1153000a..fc5dbae 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4,6 +4,7 @@ #include "content/renderer/render_frame_impl.h" +#include <string.h> #include <algorithm> #include <map> #include <string> @@ -1232,6 +1233,8 @@ #endif manifest_manager_ = new ManifestManager(this); + memset(&peak_memory_metrics_, 0, + sizeof(RenderThreadImpl::RendererMemoryMetrics)); } mojom::FrameHostAssociatedPtr RenderFrameImpl::GetFrameHost() { @@ -3976,6 +3979,7 @@ WebDataSource* ds = frame_->DataSource(); Send(new FrameHostMsg_DidFinishLoad(routing_id_, ds->GetRequest().Url())); + ReportPeakMemoryStats(); if (RenderThreadImpl::current()) { RenderThreadImpl::RendererMemoryMetrics memory_metrics; if (!RenderThreadImpl::current()->GetRendererMemoryMetrics(&memory_metrics)) @@ -6727,6 +6731,8 @@ std::unique_ptr<blink::WebURLLoader> RenderFrameImpl::CreateURLLoader( const blink::WebURLRequest& request, base::SingleThreadTaskRunner* task_runner) { + UpdatePeakMemoryStats(); + ChildThreadImpl* child_thread = ChildThreadImpl::current(); if (base::FeatureList::IsEnabled(features::kNetworkService) && child_thread) { // Use if per-frame or per-scheme URLLoaderFactory is given. @@ -6910,6 +6916,97 @@ #endif } +void RenderFrameImpl::UpdatePeakMemoryStats() { + if (!base::FeatureList::IsEnabled(features::kReportRendererPeakMemoryStats)) + return; + + RenderThreadImpl::RendererMemoryMetrics memory_metrics; + if (!RenderThreadImpl::current()->GetRendererMemoryMetrics(&memory_metrics)) + return; + peak_memory_metrics_.partition_alloc_kb = + std::max(peak_memory_metrics_.partition_alloc_kb, + memory_metrics.partition_alloc_kb); + peak_memory_metrics_.blink_gc_kb = + std::max(peak_memory_metrics_.blink_gc_kb, memory_metrics.blink_gc_kb); + peak_memory_metrics_.malloc_mb = + std::max(peak_memory_metrics_.malloc_mb, memory_metrics.malloc_mb); + peak_memory_metrics_.discardable_kb = std::max( + peak_memory_metrics_.discardable_kb, memory_metrics.discardable_kb); + peak_memory_metrics_.v8_main_thread_isolate_mb = + std::max(peak_memory_metrics_.v8_main_thread_isolate_mb, + memory_metrics.v8_main_thread_isolate_mb); + peak_memory_metrics_.total_allocated_mb = + std::max(peak_memory_metrics_.total_allocated_mb, + memory_metrics.total_allocated_mb); + peak_memory_metrics_.non_discardable_total_allocated_mb = + std::max(peak_memory_metrics_.non_discardable_total_allocated_mb, + memory_metrics.non_discardable_total_allocated_mb); + peak_memory_metrics_.total_allocated_per_render_view_mb = + std::max(peak_memory_metrics_.total_allocated_per_render_view_mb, + memory_metrics.total_allocated_per_render_view_mb); +} + +void RenderFrameImpl::ReportPeakMemoryStats() { + if (!base::FeatureList::IsEnabled(features::kReportRendererPeakMemoryStats)) + return; + + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.PartitionAlloc.PeakDuringLoad", + peak_memory_metrics_.partition_alloc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB("Memory.Experimental.Renderer.BlinkGC.PeakDuringLoad", + peak_memory_metrics_.blink_gc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB("Memory.Experimental.Renderer.Malloc.PeakDuringLoad", + peak_memory_metrics_.malloc_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Discardable.PeakDuringLoad", + peak_memory_metrics_.discardable_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.V8MainThreadIsolate.PeakDuringLoad", + peak_memory_metrics_.v8_main_thread_isolate_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocated.PeakDuringLoad", + peak_memory_metrics_.total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.NonDiscardableTotalAllocated." + "PeakDuringLoad", + peak_memory_metrics_.non_discardable_total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocatedPerRenderView." + "PeakDuringLoad", + peak_memory_metrics_.total_allocated_per_render_view_mb); + if (IsMainFrame()) { + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.PartitionAlloc." + "MainFrame.PeakDuringLoad", + peak_memory_metrics_.partition_alloc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.BlinkGC.MainFrame.PeakDuringLoad", + peak_memory_metrics_.blink_gc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Malloc.MainFrame.PeakDuringLoad", + peak_memory_metrics_.malloc_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Discardable.MainFrame.PeakDuringLoad", + peak_memory_metrics_.discardable_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.V8MainThreadIsolate." + "MainFrame.PeakDuringLoad", + peak_memory_metrics_.v8_main_thread_isolate_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocated." + "MainFrame.PeakDuringLoad", + peak_memory_metrics_.total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.NonDiscardableTotalAllocated." + "MainFrame.PeakDuringLoad", + peak_memory_metrics_.non_discardable_total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocatedPerRenderView." + "MainFrame.PeakDuringLoad", + peak_memory_metrics_.total_allocated_per_render_view_mb); + } +} + RenderFrameImpl::PendingNavigationInfo::PendingNavigationInfo( const NavigationPolicyInfo& info) : navigation_type(info.navigation_type),
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 39309d0a..900d476 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -48,6 +48,7 @@ #include "content/public/renderer/render_frame.h" #include "content/renderer/frame_blame_context.h" #include "content/renderer/media/media_factory.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_webcookiejar_impl.h" #include "ipc/ipc_message.h" #include "ipc/ipc_platform_file.h" @@ -1125,6 +1126,9 @@ void SendUpdateFaviconURL(blink::WebIconURL::Type icon_types_mask); + void UpdatePeakMemoryStats(); + void ReportPeakMemoryStats(); + // Stores the WebLocalFrame we are associated with. This is null from the // constructor until BindToFrame() is called, and it is null after // FrameDetached() is called until destruction (which is asynchronous in the @@ -1426,6 +1430,8 @@ // Callbacks that we should call when we get a routing token. std::vector<media::RoutingTokenCallback> pending_routing_token_callbacks_; + RenderThreadImpl::RendererMemoryMetrics peak_memory_metrics_; + base::WeakPtrFactory<RenderFrameImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 21739d7..4118485 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -714,6 +714,7 @@ "../browser/site_per_process_mac_browsertest.mm", "../browser/top_document_isolation_browsertest.cc", "../browser/tracing/background_tracing_manager_browsertest.cc", + "../browser/tracing/memory_instrumentation_browsertest.cc", "../browser/tracing/memory_tracing_browsertest.cc", "../browser/tracing/tracing_controller_browsertest.cc", "../browser/utility_process_host_impl_browsertest.cc",
diff --git a/docs/jumbo.md b/docs/jumbo.md index cce13df..4b76d07d 100644 --- a/docs/jumbo.md +++ b/docs/jumbo.md
@@ -15,9 +15,9 @@ Jumbo is currently implemented as a combined `gn` template and a python script. Eventually it may become a native `gn` feature. By -using the template `jumbo_target`, each target will split into one -action to "merge" the files and one action to compile the merged files -and any files left outside the merge. +(indirectly) using the template `internal_jumbo_target`, each target +will split into one action to "merge" the files and one action to +compile the merged files and any files left outside the merge. Template file: `//build/config/jumbo.gni` Merge script: `//build/config/merge_for_jumbo.py` @@ -65,15 +65,15 @@ ## Want to make your favourite piece of code jumbo? 1. Add `import("//build/config/jumbo.gni")` to `BUILD.gn`. -2. Change your target, for instance `static_library`, to `jumbo_target` -3. Add a local variable `target_type` with the name of the - final target/template. For instance `target_type = "static_library"` -4. Recompile and test. +2. Change your target, for instance `static_library`, to + `jumbo_static_library`. So far `source_set`, `component`, + `static_library` and `split_static_library` are supported. +3. Recompile and test. ### Example Change from: - static_library("foothing") { + source_set("foothing") { sources = [ "foothing.cc" "fooutil.cc" @@ -83,8 +83,7 @@ to: import("//build/config/jumbo.gni") # ADDED LINE - jumbo_target("foothing") { # CHANGED LINE - target_type = "static_library" # ADDED LINE + jumbo_source_set("foothing") { # CHANGED LINE sources = [ "foothing.cc" "fooutil.cc"
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.cc b/headless/lib/browser/headless_devtools_manager_delegate.cc index 36a2873d..ee99c614 100644 --- a/headless/lib/browser/headless_devtools_manager_delegate.cc +++ b/headless/lib/browser/headless_devtools_manager_delegate.cc
@@ -85,17 +85,16 @@ void PDFCreated( const content::DevToolsManagerDelegate::CommandCallback& callback, int command_id, - printing::HeadlessPrintManager::PrintResult print_result, + HeadlessPrintManager::PrintResult print_result, const std::string& data) { std::unique_ptr<base::DictionaryValue> response; - if (print_result == printing::HeadlessPrintManager::PRINT_SUCCESS) { + if (print_result == HeadlessPrintManager::PRINT_SUCCESS) { response = CreateSuccessResponse( - command_id, - printing::HeadlessPrintManager::PDFContentsToDictionaryValue(data)); + command_id, HeadlessPrintManager::PDFContentsToDictionaryValue(data)); } else { response = CreateErrorResponse( command_id, kErrorServerError, - printing::HeadlessPrintManager::PrintResultToString(print_result)); + HeadlessPrintManager::PrintResultToString(print_result)); } callback.Run(std::move(response)); } @@ -114,7 +113,7 @@ std::unique_ptr<base::DictionaryValue> ParsePrintSettings( int command_id, const base::DictionaryValue* params, - printing::HeadlessPrintSettings* settings) { + HeadlessPrintSettings* settings) { // We can safely ignore the return values of the following Get methods since // the defaults are already set in |settings|. params->GetBoolean("landscape", &settings->landscape); @@ -125,6 +124,8 @@ settings->scale < kScaleMinVal / 100) return CreateInvalidParamResponse(command_id, "scale"); params->GetString("pageRanges", &settings->page_ranges); + params->GetBoolean("ignoreInvalidPageRanges", + &settings->ignore_invalid_page_ranges); double paper_width_in_inch = printing::kLetterWidthInch; double paper_height_in_inch = printing::kLetterHeightInch; @@ -284,14 +285,14 @@ content::WebContents* web_contents = agent_host->GetWebContents(); content::RenderFrameHost* rfh = web_contents->GetMainFrame(); - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; std::unique_ptr<base::DictionaryValue> response = ParsePrintSettings(command_id, params, &settings); if (response) { callback.Run(std::move(response)); return; } - printing::HeadlessPrintManager::FromWebContents(web_contents) + HeadlessPrintManager::FromWebContents(web_contents) ->GetPDFContents(rfh, settings, base::Bind(&PDFCreated, callback, command_id)); #else
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.h b/headless/lib/browser/headless_devtools_manager_delegate.h index 0c699fa..22d2be0 100644 --- a/headless/lib/browser/headless_devtools_manager_delegate.h +++ b/headless/lib/browser/headless_devtools_manager_delegate.h
@@ -28,7 +28,7 @@ HEADLESS_EXPORT std::unique_ptr<base::DictionaryValue> ParsePrintSettings( int command_id, const base::DictionaryValue* params, - printing::HeadlessPrintSettings* settings); + HeadlessPrintSettings* settings); #endif class HeadlessDevToolsManagerDelegate
diff --git a/headless/lib/browser/headless_print_manager.cc b/headless/lib/browser/headless_print_manager.cc index 0e71c188..2c761cd 100644 --- a/headless/lib/browser/headless_print_manager.cc +++ b/headless/lib/browser/headless_print_manager.cc
@@ -19,9 +19,16 @@ #include "printing/print_job_constants.h" #include "printing/units.h" -DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::HeadlessPrintManager); +DEFINE_WEB_CONTENTS_USER_DATA_KEY(headless::HeadlessPrintManager); -namespace printing { +namespace headless { + +HeadlessPrintSettings::HeadlessPrintSettings() + : landscape(false), + display_header_footer(false), + should_print_backgrounds(false), + scale(1), + ignore_invalid_page_ranges(false) {} HeadlessPrintManager::HeadlessPrintManager(content::WebContents* web_contents) : PrintManager(web_contents) { @@ -74,9 +81,10 @@ // static HeadlessPrintManager::PageRangeStatus HeadlessPrintManager::PageRangeTextToPages(base::StringPiece page_range_text, + bool ignore_invalid_page_ranges, int pages_count, std::vector<int>* pages) { - PageRanges page_ranges; + printing::PageRanges page_ranges; for (const auto& range_string : base::SplitStringPiece(page_range_text, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { @@ -105,10 +113,17 @@ return SYNTAX_ERROR; } - if (range.from < 1 || range.from > range.to) - return SYNTAX_ERROR; - if (range.from > pages_count) - return LIMIT_ERROR; + if (range.from < 1 || range.from > range.to) { + if (!ignore_invalid_page_ranges) + return SYNTAX_ERROR; + continue; + } + if (range.from > pages_count) { + if (!ignore_invalid_page_ranges) + return LIMIT_ERROR; + continue; + } + if (range.to > pages_count) range.to = pages_count; @@ -118,7 +133,7 @@ range.to--; page_ranges.push_back(range); } - *pages = PageRange::GetPages(page_ranges); + *pages = printing::PageRange::GetPages(page_ranges); return PRINT_NO_ERROR; } @@ -135,14 +150,15 @@ callback_ = callback; print_params_ = GetPrintParamsFromSettings(settings); page_ranges_text_ = settings.page_ranges; + ignore_invalid_page_ranges_ = settings.ignore_invalid_page_ranges; rfh->Send(new PrintMsg_PrintPages(rfh->GetRoutingID())); } std::unique_ptr<PrintMsg_PrintPages_Params> HeadlessPrintManager::GetPrintParamsFromSettings( const HeadlessPrintSettings& settings) { - PrintSettings print_settings; - print_settings.set_dpi(kPointsPerInch); + printing::PrintSettings print_settings; + print_settings.set_dpi(printing::kPointsPerInch); print_settings.set_should_print_backgrounds( settings.should_print_backgrounds); print_settings.set_scale_factor(settings.scale); @@ -159,7 +175,7 @@ print_settings.set_url(base::UTF8ToUTF16(url)); } - print_settings.set_margin_type(CUSTOM_MARGINS); + print_settings.set_margin_type(printing::CUSTOM_MARGINS); print_settings.SetCustomMargins(settings.margins_in_points); gfx::Rect printable_area_device_units(settings.paper_size_in_points); @@ -167,8 +183,9 @@ printable_area_device_units, true); auto print_params = base::MakeUnique<PrintMsg_PrintPages_Params>(); - RenderParamsFromPrintSettings(print_settings, &print_params->params); - print_params->params.document_cookie = PrintSettings::NewCookie(); + printing::RenderParamsFromPrintSettings(print_settings, + &print_params->params); + print_params->params.document_cookie = printing::PrintSettings::NewCookie(); return print_params; } @@ -222,8 +239,9 @@ void HeadlessPrintManager::OnScriptedPrint( const PrintHostMsg_ScriptedPrint_Params& params, IPC::Message* reply_msg) { - PageRangeStatus status = PageRangeTextToPages( - page_ranges_text_, params.expected_pages_count, &print_params_->pages); + PageRangeStatus status = + PageRangeTextToPages(page_ranges_text_, ignore_invalid_page_ranges_, + params.expected_pages_count, &print_params_->pages); switch (status) { case SYNTAX_ERROR: printing_rfh_->Send(reply_msg); @@ -274,7 +292,8 @@ ReleaseJob(METAFILE_MAP_ERROR); return; } - auto metafile = base::MakeUnique<PdfMetafileSkia>(PDF_SKIA_DOCUMENT_TYPE); + auto metafile = base::MakeUnique<printing::PdfMetafileSkia>( + printing::PDF_SKIA_DOCUMENT_TYPE); if (!metafile->InitFromData(shared_buf->memory(), params.data_size)) { ReleaseJob(METAFILE_INVALID_HEADER); return; @@ -302,6 +321,7 @@ callback_.Reset(); print_params_.reset(); page_ranges_text_.clear(); + ignore_invalid_page_ranges_ = false; data_.clear(); expecting_first_page_ = true; number_pages_ = 0; @@ -323,4 +343,4 @@ Reset(); } -} // namespace printing +} // namespace headless
diff --git a/headless/lib/browser/headless_print_manager.h b/headless/lib/browser/headless_print_manager.h index 89a1815..100ae98 100644 --- a/headless/lib/browser/headless_print_manager.h +++ b/headless/lib/browser/headless_print_manager.h
@@ -14,23 +14,19 @@ #include "content/public/browser/web_contents_user_data.h" #include "headless/public/headless_export.h" #include "printing/print_settings.h" -#include "printing/printing_export.h" struct PrintHostMsg_DidPrintPage_Params; struct PrintHostMsg_ScriptedPrint_Params; struct PrintMsg_PrintPages_Params; -namespace printing { +namespace headless { -struct HeadlessPrintSettings { - HeadlessPrintSettings() - : landscape(false), - display_header_footer(false), - should_print_backgrounds(false), - scale(1) {} +// Exported for tests. +struct HEADLESS_EXPORT HeadlessPrintSettings { + HeadlessPrintSettings(); gfx::Size paper_size_in_points; - PageMargins margins_in_points; + printing::PageMargins margins_in_points; bool landscape; bool display_header_footer; @@ -39,10 +35,11 @@ double scale; std::string page_ranges; + bool ignore_invalid_page_ranges; }; class HeadlessPrintManager - : public PrintManager, + : public printing::PrintManager, public content::WebContentsUserData<HeadlessPrintManager> { public: enum PrintResult { @@ -75,6 +72,7 @@ // Exported for tests. HEADLESS_EXPORT static PageRangeStatus PageRangeTextToPages( base::StringPiece page_range_text, + bool ignore_invalid_page_ranges, int pages_count, std::vector<int>* pages); @@ -108,18 +106,19 @@ void Reset(); void ReleaseJob(PrintResult result); - content::RenderFrameHost* printing_rfh_; + content::RenderFrameHost* printing_rfh_ = nullptr; GetPDFCallback callback_; std::unique_ptr<PrintMsg_PrintPages_Params> print_params_; std::string page_ranges_text_; + bool ignore_invalid_page_ranges_ = false; std::string data_; // Set to true when OnDidPrintPage() should be expecting the first page. - bool expecting_first_page_; + bool expecting_first_page_ = true; DISALLOW_COPY_AND_ASSIGN(HeadlessPrintManager); }; -} // namespace printing +} // namespace headless #endif // HEADLESS_LIB_BROWSER_HEADLESS_PRINT_MANAGER_H_
diff --git a/headless/lib/browser/headless_printing_unittest.cc b/headless/lib/browser/headless_printing_unittest.cc index 2c9ae2d..5cdf858 100644 --- a/headless/lib/browser/headless_printing_unittest.cc +++ b/headless/lib/browser/headless_printing_unittest.cc
@@ -13,7 +13,7 @@ namespace headless { TEST(ParsePrintSettingsTest, Landscape) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; EXPECT_FALSE(settings.landscape); auto params = base::MakeUnique<base::DictionaryValue>(); @@ -25,7 +25,7 @@ } TEST(ParsePrintSettingsTest, HeaderFooter) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; EXPECT_FALSE(settings.display_header_footer); auto params = base::MakeUnique<base::DictionaryValue>(); @@ -37,7 +37,7 @@ } TEST(ParsePrintSettingsTest, PrintBackground) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; EXPECT_FALSE(settings.should_print_backgrounds); auto params = base::MakeUnique<base::DictionaryValue>(); @@ -49,7 +49,7 @@ } TEST(ParsePrintSettingsTest, Scale) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; EXPECT_DOUBLE_EQ(1, settings.scale); auto params = base::MakeUnique<base::DictionaryValue>(); @@ -69,22 +69,24 @@ } TEST(ParsePrintSettingsTest, PageRanges) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; EXPECT_EQ("", settings.page_ranges); auto params = base::MakeUnique<base::DictionaryValue>(); params->SetString("pageRanges", "abcd"); + params->SetBoolean("ignoreInvalidPageRanges", true); std::unique_ptr<base::DictionaryValue> response = ParsePrintSettings(0, params.get(), &settings); // Pass pageRanges text to settings directly and return no error, even if // it is invalid. The validation is deferred to HeadlessPrintMangager once the // total page count is available. See the PageRangeTextToPagesTest. EXPECT_EQ("abcd", settings.page_ranges); + EXPECT_TRUE(settings.ignore_invalid_page_ranges); EXPECT_EQ(nullptr, response); } TEST(ParsePrintSettingsTest, Paper) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; auto params = base::MakeUnique<base::DictionaryValue>(); std::unique_ptr<base::DictionaryValue> response = @@ -116,7 +118,7 @@ } TEST(ParsePrintSettingsTest, Margin) { - printing::HeadlessPrintSettings settings; + HeadlessPrintSettings settings; auto params = base::MakeUnique<base::DictionaryValue>(); std::unique_ptr<base::DictionaryValue> response = @@ -150,56 +152,62 @@ } TEST(PageRangeTextToPagesTest, General) { - using PM = printing::HeadlessPrintManager; + using PM = HeadlessPrintManager; std::vector<int> pages; std::vector<int> expected_pages; // "-" is full range of pages. - PM::PageRangeStatus status = PM::PageRangeTextToPages("-", 10, &pages); + PM::PageRangeStatus status = PM::PageRangeTextToPages("-", false, 10, &pages); expected_pages = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; EXPECT_EQ(expected_pages, pages); EXPECT_EQ(PM::PRINT_NO_ERROR, status); // If no start page is specified, we start at first page. - status = PM::PageRangeTextToPages("-5", 10, &pages); + status = PM::PageRangeTextToPages("-5", false, 10, &pages); expected_pages = {0, 1, 2, 3, 4}; EXPECT_EQ(expected_pages, pages); EXPECT_EQ(PM::PRINT_NO_ERROR, status); // If no end page is specified, we end at last page. - status = PM::PageRangeTextToPages("5-", 10, &pages); + status = PM::PageRangeTextToPages("5-", false, 10, &pages); expected_pages = {4, 5, 6, 7, 8, 9}; EXPECT_EQ(expected_pages, pages); EXPECT_EQ(PM::PRINT_NO_ERROR, status); // Multiple ranges are separated by commas. - status = PM::PageRangeTextToPages("1-3,9-10,4-6", 10, &pages); + status = PM::PageRangeTextToPages("1-3,9-10,4-6", false, 10, &pages); expected_pages = {0, 1, 2, 3, 4, 5, 8, 9}; EXPECT_EQ(expected_pages, pages); EXPECT_EQ(PM::PRINT_NO_ERROR, status); // White space is ignored. - status = PM::PageRangeTextToPages("1- 3, 9-10,4 -6", 10, &pages); + status = PM::PageRangeTextToPages("1- 3, 9-10,4 -6", false, 10, &pages); expected_pages = {0, 1, 2, 3, 4, 5, 8, 9}; EXPECT_EQ(expected_pages, pages); EXPECT_EQ(PM::PRINT_NO_ERROR, status); // End page beyond number of pages is supported and capped to number of pages. - status = PM::PageRangeTextToPages("1-10", 5, &pages); + status = PM::PageRangeTextToPages("1-10", false, 5, &pages); expected_pages = {0, 1, 2, 3, 4}; EXPECT_EQ(expected_pages, pages); EXPECT_EQ(PM::PRINT_NO_ERROR, status); // Start page beyond number of pages results in error. - status = PM::PageRangeTextToPages("1-3,9-10,4-6", 5, &pages); + status = PM::PageRangeTextToPages("1-3,9-10,4-6", false, 5, &pages); EXPECT_EQ(PM::LIMIT_ERROR, status); + // Invalid page ranges are ignored if |ignore_invalid_page_ranges| is true. + status = PM::PageRangeTextToPages("9-10,4-6,3-1", true, 5, &pages); + expected_pages = {3, 4}; + EXPECT_EQ(expected_pages, pages); + EXPECT_EQ(PM::PRINT_NO_ERROR, status); + // Invalid input results in error. - status = PM::PageRangeTextToPages("abcd", 10, &pages); + status = PM::PageRangeTextToPages("abcd", false, 10, &pages); EXPECT_EQ(PM::SYNTAX_ERROR, status); // Invalid input results in error. - status = PM::PageRangeTextToPages("1-3,9-a10,4-6", 10, &pages); + status = PM::PageRangeTextToPages("1-3,9-a10,4-6", false, 10, &pages); EXPECT_EQ(PM::SYNTAX_ERROR, status); }
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc index 4d36bb21..b5bfb40 100644 --- a/headless/lib/browser/headless_web_contents_impl.cc +++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -224,7 +224,7 @@ render_process_host_(web_contents->GetRenderProcessHost()), weak_ptr_factory_(this) { #if BUILDFLAG(ENABLE_BASIC_PRINTING) && !defined(CHROME_MULTIPLE_DLL_CHILD) - printing::HeadlessPrintManager::CreateForWebContents(web_contents); + HeadlessPrintManager::CreateForWebContents(web_contents); #endif web_contents_->SetDelegate(web_contents_delegate_.get()); render_process_host_->AddObserver(this);
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 8dbb0bff..4b2e4e04 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -365,8 +365,6 @@ - (void)activateBVCAndMakeCurrentBVCPrimary; // Sets |currentBVC| as the root view controller for the window. - (void)displayCurrentBVC; -// Shows the accounts settings UI. -- (void)showAccountsSettings; // Shows the Sync settings UI. - (void)showSyncSettings; // Shows the Save Passwords settings. @@ -1283,7 +1281,8 @@ WelcomeToChromeViewController* welcomeToChrome = [[WelcomeToChromeViewController alloc] initWithBrowserState:_mainBrowserState - tabModel:self.mainTabModel]; + tabModel:self.mainTabModel + dispatcher:self.mainBVC.dispatcher]; UINavigationController* navController = [[OrientationLimitingNavigationController alloc] initWithRootViewController:welcomeToChrome]; @@ -1320,31 +1319,18 @@ if (_startupParameters) return; - // This array should contain Class objects - one for each promo class. - // New PromoViewController subclasses should be added here. - // Note that ordering matters -- only the first promo in the array that - // returns true to +shouldBePresentedForProfile: will be shown. - // TODO(crbug.com/516154): Now that there's only one promo class, this - // implementation is overkill. - NSArray* possiblePromos = @[ [SigninPromoViewController class] ]; - for (id promoController in possiblePromos) { - Class promoClass = (Class)promoController; - DCHECK(class_isMetaClass(object_getClass(promoClass))); - DCHECK(class_getClassMethod(object_getClass(promoClass), - @selector(shouldBePresentedForBrowserState:))); - if ([promoClass shouldBePresentedForBrowserState:_mainBrowserState]) { - UIViewController* promoController = - [promoClass controllerToPresentForBrowserState:_mainBrowserState]; + // Show the sign-in promo if needed + if ([SigninPromoViewController + shouldBePresentedForBrowserState:_mainBrowserState]) { + UIViewController* promoController = [[SigninPromoViewController alloc] + initWithBrowserState:_mainBrowserState + dispatcher:self.mainBVC.dispatcher]; - dispatch_after( - dispatch_time(DISPATCH_TIME_NOW, - (int64_t)(kDisplayPromoDelay * NSEC_PER_SEC)), - dispatch_get_main_queue(), ^{ - [self showPromo:promoController]; - }); - - break; - } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(kDisplayPromoDelay * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self showPromo:promoController]; + }); } } @@ -1413,10 +1399,6 @@ } break; } - case IDC_SHOW_ACCOUNTS_SETTINGS: { - [self showAccountsSettings]; - break; - } case IDC_SHOW_SYNC_SETTINGS: [self showSyncSettings]; break; @@ -1916,8 +1898,10 @@ - (void)presentSignedInAccountsViewControllerForBrowserState: (ios::ChromeBrowserState*)browserState { - UIViewController* accountsViewController = [ - [SignedInAccountsViewController alloc] initWithBrowserState:browserState]; + UIViewController* accountsViewController = + [[SignedInAccountsViewController alloc] + initWithBrowserState:browserState + dispatcher:self.mainBVC.dispatcher]; [[self topPresentedViewController] presentViewController:accountsViewController animated:YES @@ -1940,12 +1924,14 @@ } - (void)showAccountsSettings { - if (_settingsNavigationController) - return; if ([self currentBrowserState]->IsOffTheRecord()) { NOTREACHED(); return; } + if (_settingsNavigationController) { + [_settingsNavigationController showAccountsSettings]; + return; + } _settingsNavigationController = [SettingsNavigationController newAccountsController:self.currentBrowserState delegate:self]; @@ -2060,7 +2046,8 @@ presentingViewController:[self topPresentedViewController] isPresentedOnSettings:areSettingsPresented accessPoint:accessPoint - promoAction:promoAction]; + promoAction:promoAction + dispatcher:self.mainBVC.dispatcher]; signin_ui::CompletionCallback completion = ^(BOOL success) { _signinInteractionController = nil; @@ -2101,7 +2088,8 @@ isPresentedOnSettings:areSettingsPresented accessPoint:signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN promoAction:signin_metrics::PromoAction:: - PROMO_ACTION_NO_SIGNIN_PROMO]; + PROMO_ACTION_NO_SIGNIN_PROMO + dispatcher:self.mainBVC.dispatcher]; [_signinInteractionController addAccountWithCompletion:^(BOOL success) { @@ -2441,6 +2429,11 @@ }]; } +- (id<ApplicationCommands, BrowserCommands>)dispatcherForSettings { + // Assume that settings always wants the dispatcher from the main BVC. + return self.mainBVC.dispatcher; +} + #pragma mark - UserFeedbackDataSource - (NSString*)currentPageDisplayURL {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index e2da779..405d2ff 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1122,8 +1122,8 @@ <message name="IDS_IOS_SETTINGS_PASSWORD_COPY_MENU_ITEM" desc="Context menu item available on the password cell in detailed view of a stored credential. The user can select it to copy the password to clipboard. [Length: should be one short word, is under 5em in English]"> Copy </message> - <message name="IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON" desc="Button that the user can press to delete the saved password. [Length: 31em]"> - Delete Saved Password + <message name="IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON" desc="Button that the user can press to delete a saved password or a site-bound exception preventing saving passwords. [Length: single line available]"> + Delete </message> <message name="IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL" desc="Accessibility label stating that the element is displaying a hidden password."> Hidden, Password @@ -1146,17 +1146,17 @@ <message name="IDS_IOS_SETTINGS_PASSWORD_SHOW_MENU_ITEM" desc="Context menu item available on the password cell in detailed view of a stored password. The user can select it to show the password to clipboard. [Length: should be one short word, is under 5em in English]"> Show </message> - <message name="IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE" desc="Confirmation that the site URL of a saved credential was copied. This is shown alone in an infobar at the bottom of the screen. [Length: 40em]"> - The site URL was copied. + <message name="IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE" desc="Confirmation that the site URL of a saved credential was copied. This is shown alone in an infobar at the bottom of the screen. [Length: one line]"> + Site address copied </message> - <message name="IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE" desc="Confirmation that the username was copied. This is shown alone in an infobar at the bottom of the screen. [Length: 40em]"> - Your username was copied. + <message name="IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE" desc="Confirmation that the username was copied. This is shown alone in an infobar at the bottom of the screen. [Length: one line]"> + Username copied </message> - <message name="IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE" desc="Confirmation that the password was copied. This is shown alone in an infobar at the bottom of the screen after the user successfully reauthenticates with Touch ID or PIN. [Length: 40em]"> - Your password was copied. + <message name="IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE" desc="Confirmation that the password was copied. This is shown alone in an infobar at the bottom of the screen after the user successfully reauthenticates with Touch ID or PIN. [Length: one line]"> + Password copied </message> - <message name="IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE" desc="Message informing the user that the password was not copied because the authentication failed. This is shown alone in an infobar at the bottom of the screen after the user tries to reauthenticate with Touch ID or PIN to copy the password and fails. [Length: 53em]"> - Authentication failed. Your password was not copied. + <message name="IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE" desc="Message informing the user that the password was not copied because the authentication failed. This is shown alone in an infobar at the bottom of the screen after the user tries to reauthenticate with Touch ID or PIN to copy the password and fails. [Length: one line]"> + Can't verify your identity. Password not copied. </message> <message name="IDS_IOS_SETTINGS_TITLE" desc="Title for the settings panel [iOS]."> Settings @@ -1222,13 +1222,13 @@ Username </message> <message name="IDS_IOS_SHOW_PASSWORD_VIEW_FEDERATION" desc="Label indicating that the text displayed below is the hostname of the identity provider used for the displayed credential. [Length: to fit on one line] [iOS only]"> - With Federation + Signed In With </message> <message name="IDS_IOS_CANCEL_PASSWORD_DELETION" desc="Label of a confirmation dialogue button which allows the user to cancel deletion of a stored password. [Length: one line] [iOS only]"> Cancel </message> <message name="IDS_IOS_CONFIRM_PASSWORD_DELETION" desc="Label of a confirmation dialogue button which allows the user to confirm deletion of a stored password. [Length: one line] [iOS only]"> - Delete Saved Password + Delete </message> <message name="IDS_IOS_SETTINGS_PASSWORDS_SAVED_HEADING" desc="The title for a list of username/site/password items. These items are already saved by the browser and can be deleted/edited. [Length: one line] [iOS only]"> Saved Passwords
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder.h b/ios/chrome/browser/metrics/tab_usage_recorder.h index b5a3e21..bd05457 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder.h +++ b/ios/chrome/browser/metrics/tab_usage_recorder.h
@@ -18,9 +18,6 @@ // Histogram names (visible for testing only). -// The prefix of the histogram names. Used to create a HistogramRecorder. -extern const char kTabUsageHistogramPrefix[]; - // The name of the histogram that records the state of the selected tab // (i.e. the tab being switched to). extern const char kSelectedTabHistogramName[];
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder.mm b/ios/chrome/browser/metrics/tab_usage_recorder.mm index 2b73c672..cbfcf9d0 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder.mm
@@ -13,8 +13,6 @@ #import "ios/web/public/web_state/web_state.h" #import "ios/web/web_state/ui/crw_web_controller.h" -const char kTabUsageHistogramPrefix[] = "Tab"; - // The histogram recording the state of the tab the user switches to. const char kSelectedTabHistogramName[] = "Tab.StatusWhenSwitchedBackToForeground";
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index e2a51f6e..533064fb 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -83,6 +83,7 @@ #include "ios/chrome/browser/translate/chrome_ios_translate_client.h" #import "ios/chrome/browser/u2f/u2f_controller.h" #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" @@ -1732,9 +1733,7 @@ signin_metrics::LogAccountReconcilorStateOnGaiaResponse( ios::AccountReconcilorFactory::GetForBrowserState(_browserState) ->GetState()); - GenericChromeCommand* command = - [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ACCOUNTS_SETTINGS]; - [self.view chromeExecuteCommand:command]; + [self.dispatcher showAccountsSettings]; } - (void)onAddAccount {
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index 50730cf..3f3b179 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -61,6 +61,7 @@ "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/images", "//ios/public/provider/chrome/browser/signin", + "//ios/shared/chrome/browser/ui/commands", "//ios/third_party/material_components_ios", "//ios/third_party/material_roboto_font_loader_ios", "//ui/base",
diff --git a/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm b/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm index e0ae467..2782fe5 100644 --- a/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm +++ b/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm
@@ -445,4 +445,9 @@ NOTREACHED(); } +- (id<ApplicationCommands, BrowserCommands>)dispatcherForSettings { + NOTREACHED(); + return nil; +} + @end
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h index 16835b8..d04b952c 100644 --- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h +++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h
@@ -10,9 +10,9 @@ #include "components/signin/core/browser/signin_metrics.h" #import "ios/chrome/browser/signin/constants.h" -@class ChromeSigninViewController; -@class GenericChromeCommand; +@protocol ApplicationSettingsCommands; @class ChromeIdentity; +@class ChromeSigninViewController; namespace ios { class ChromeBrowserState; @@ -49,10 +49,11 @@ identity:(ChromeIdentity*)identity; // Informs the delegate that the user has accepted the sign-in in |controller|. -// If |command| is not nil, the delegate is expected to execute it. +// If |showAccountSettings| is YES, the delegate is expected to cause the +// account settings to be shown. // This marks the end of the sign-in flow. - (void)didAcceptSignIn:(ChromeSigninViewController*)controller - executeCommand:(GenericChromeCommand*)command; + showAccountsSettings:(BOOL)showAccountsSettings; @end @@ -66,17 +67,23 @@ // It is valid to set this in the |willStartSignIn:| method of the delegate. @property(nonatomic, assign) ShouldClearData shouldClearData; +@property(nonatomic, weak, readonly) id<ApplicationSettingsCommands> dispatcher; + // Designated initializer. // * |browserState| is the current browser state. // * |isPresentedOnSettings| indicates whether the settings view controller is // part of the presented view controllers stack. // * |accessPoint| represents the access point that initiated the sign-in. // * |identity| will be signed in without requiring user input if not nil. +// * |dispatcher| is the dispatcher that can accept commands for displaying +// settings views. - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState isPresentedOnSettings:(BOOL)isPresentedOnSettings accessPoint:(signin_metrics::AccessPoint)accessPoint promoAction:(signin_metrics::PromoAction)promoAction - signInIdentity:(ChromeIdentity*)identity; + signInIdentity:(ChromeIdentity*)identity + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher; // Cancels the on-going authentication operation (if any). |delegate| will be // called with |didFailSignIn|.
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm index c0df24f..2026b2d7 100644 --- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
@@ -34,9 +34,6 @@ #include "ios/chrome/browser/ui/authentication/signin_account_selector_view_controller.h" #include "ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" -#import "ios/chrome/browser/ui/commands/generic_chrome_command.h" -#include "ios/chrome/browser/ui/commands/ios_command_ids.h" #import "ios/chrome/browser/ui/rtl_geometry.h" #import "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" @@ -181,18 +178,22 @@ @synthesize delegate = _delegate; @synthesize shouldClearData = _shouldClearData; +@synthesize dispatcher = _dispatcher; - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState isPresentedOnSettings:(BOOL)isPresentedOnSettings accessPoint:(signin_metrics::AccessPoint)accessPoint promoAction:(signin_metrics::PromoAction)promoAction - signInIdentity:(ChromeIdentity*)identity { + signInIdentity:(ChromeIdentity*)identity + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { self = [super init]; if (self) { _browserState = browserState; _isPresentedOnSettings = isPresentedOnSettings; _accessPoint = accessPoint; _promoAction = promoAction; + _dispatcher = dispatcher; if (identity) { _autoSignIn = YES; @@ -244,19 +245,19 @@ } } -- (void)acceptSignInAndExecuteCommand:(GenericChromeCommand*)command { +- (void)acceptSignInAndShowAccountsSettings:(BOOL)showAccountsSettings { signin_metrics::LogSigninAccessPointCompleted(_accessPoint, _promoAction); _didAcceptSignIn = YES; if (!_didFinishSignIn) { _didFinishSignIn = YES; - [_delegate didAcceptSignIn:self executeCommand:command]; + [_delegate didAcceptSignIn:self showAccountsSettings:showAccountsSettings]; } } - (void)acceptSignInAndCommitSyncChanges { DCHECK(_didSignIn); SyncSetupServiceFactory::GetForBrowserState(_browserState)->CommitChanges(); - [self acceptSignInAndExecuteCommand:nil]; + [self acceptSignInAndShowAccountsSettings:NO]; } - (void)setPrimaryButtonStyling:(MDCButton*)button { @@ -923,9 +924,7 @@ (SigninConfirmationViewController*)controller { DCHECK_EQ(_confirmationVC, controller); - GenericChromeCommand* command = - [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ACCOUNTS_SETTINGS]; - [self acceptSignInAndExecuteCommand:command]; + [self acceptSignInAndShowAccountsSettings:YES]; } - (void)signinConfirmationControllerDidReachBottom:
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h index 75cee37..0bb7482 100644 --- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h +++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h
@@ -7,6 +7,7 @@ #import <UIKit/UIKit.h> +@protocol ApplicationSettingsCommands; namespace ios { class ChromeBrowserState; } // namespace ios @@ -20,6 +21,7 @@ + (BOOL)shouldBePresentedForBrowserState:(ios::ChromeBrowserState*)browserState; - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState + dispatcher:(id<ApplicationSettingsCommands>)dispatcher NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNibName:(NSString*)name
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm index cc0aa96..d15cafb4 100644 --- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
@@ -19,9 +19,7 @@ #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" -#import "ios/chrome/browser/ui/commands/generic_chrome_command.h" -#include "ios/chrome/browser/ui/commands/ios_command_ids.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" @@ -193,9 +191,11 @@ MDCButton* _primaryButton; MDCButton* _secondaryButton; } +@property(nonatomic, readonly, weak) id<ApplicationSettingsCommands> dispatcher; @end @implementation SignedInAccountsViewController +@synthesize dispatcher = _dispatcher; + (BOOL)shouldBePresentedForBrowserState: (ios::ChromeBrowserState*)browserState { @@ -210,10 +210,13 @@ #pragma mark Initialization -- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { +- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { self = [super initWithNibName:nil bundle:nil]; if (self) { _browserState = browserState; + _dispatcher = dispatcher; _tokenServiceObserver.reset(new OAuth2TokenServiceObserverBridge( OAuth2TokenServiceFactory::GetForBrowserState(_browserState), self)); _transitionController = [[MDCDialogTransitionController alloc] init]; @@ -372,9 +375,7 @@ - (void)onSecondaryButtonPressed:(id)sender { [self dismiss]; - GenericChromeCommand* showAccountsSettingsCommand = - [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_ACCOUNTS_SETTINGS]; - [self chromeExecuteCommand:showAccountsSettingsCommand]; + [self.dispatcher showAccountsSettings]; } #pragma mark OAuth2TokenServiceObserverBridgeDelegate
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller.h b/ios/chrome/browser/ui/authentication/signin_interaction_controller.h index 748082a..e668d8e6 100644 --- a/ios/chrome/browser/ui/authentication/signin_interaction_controller.h +++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller.h
@@ -11,10 +11,10 @@ #include "components/signin/core/browser/signin_metrics.h" #include "ios/chrome/browser/signin/constants.h" +@protocol ApplicationSettingsCommands; namespace ios { class ChromeBrowserState; } - @class ChromeIdentity; // Interaction controller for sign-in related operations. This class is mainly a @@ -32,7 +32,9 @@ presentingViewController:(UIViewController*)presentingViewController isPresentedOnSettings:(BOOL)isPresentedOnSettings accessPoint:(signin_metrics::AccessPoint)accessPoint - promoAction:(signin_metrics::PromoAction)promoAction; + promoAction:(signin_metrics::PromoAction)promoAction + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher; // Starts user sign-in. // * |viewController| is the current view controller.
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller.mm b/ios/chrome/browser/ui/authentication/signin_interaction_controller.mm index 0f9905c..87e1799 100644 --- a/ios/chrome/browser/ui/authentication/signin_interaction_controller.mm +++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller.mm
@@ -17,7 +17,7 @@ #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/authentication/authentication_ui_util.h" #import "ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h" -#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/util/top_view_controller.h" #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/signin/chrome_identity.h" @@ -48,10 +48,15 @@ ChromeIdentity* signInIdentity_; BOOL identityAdded_; } + +@property(nonatomic, weak, readonly) id<ApplicationSettingsCommands> dispatcher; + @end @implementation SigninInteractionController +@synthesize dispatcher = dispatcher_; + - (id)init { NOTREACHED(); return nil; @@ -61,7 +66,9 @@ presentingViewController:(UIViewController*)presentingViewController isPresentedOnSettings:(BOOL)isPresentedOnSettings accessPoint:(signin_metrics::AccessPoint)accessPoint - promoAction:(signin_metrics::PromoAction)promoAction { + promoAction:(signin_metrics::PromoAction)promoAction + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { self = [super init]; if (self) { DCHECK(browserState); @@ -71,6 +78,7 @@ isPresentedOnSettings_ = isPresentedOnSettings; accessPoint_ = accessPoint; promoAction_ = promoAction; + dispatcher_ = dispatcher; } return self; } @@ -120,7 +128,7 @@ if (!identityInteractionManager_) { // Abort sign-in if the ChromeIdentityInteractionManager returned is // nil (this can happen when the iOS internal provider is not used). - [self runCompletionCallbackWithSuccess:NO executeCommand:nil]; + [self runCompletionCallbackWithSuccess:NO showAccountsSettings:NO]; return; } @@ -204,13 +212,13 @@ if (error) { // Filter out cancel and errors handled internally by ChromeIdentity. if (!ShouldHandleSigninError(error)) { - [self runCompletionCallbackWithSuccess:NO executeCommand:nil]; + [self runCompletionCallbackWithSuccess:NO showAccountsSettings:NO]; return; } __weak SigninInteractionController* weakSelf = self; ProceduralBlock dismissAction = ^{ - [weakSelf runCompletionCallbackWithSuccess:NO executeCommand:nil]; + [weakSelf runCompletionCallbackWithSuccess:NO showAccountsSettings:NO]; }; alertCoordinator_ = ios_internal::ErrorCoordinator( @@ -222,7 +230,7 @@ if (shouldSignIn) { [self showSigninViewControllerWithIdentity:identity identityAdded:YES]; } else { - [self runCompletionCallbackWithSuccess:YES executeCommand:nil]; + [self runCompletionCallbackWithSuccess:YES showAccountsSettings:NO]; } } @@ -275,7 +283,8 @@ isPresentedOnSettings:isPresentedOnSettings_ accessPoint:accessPoint_ promoAction:promoAction_ - signInIdentity:signInIdentity]; + signInIdentity:signInIdentity + dispatcher:self.dispatcher]; [signinViewController_ setDelegate:self]; [signinViewController_ setModalPresentationStyle:UIModalPresentationFormSheet]; @@ -302,16 +311,18 @@ } - (void)dismissSigninViewControllerWithSignInSuccess:(BOOL)success - executeCommand: - (GenericChromeCommand*)command { + showAccountsSettings: + (BOOL)showAccountsSettings { DCHECK(signinViewController_); if ((isCancelling_ && !isDismissing_) || ![presentingViewController_ presentedViewController]) { - [self runCompletionCallbackWithSuccess:success executeCommand:command]; + [self runCompletionCallbackWithSuccess:success + showAccountsSettings:showAccountsSettings]; return; } ProceduralBlock completion = ^{ - [self runCompletionCallbackWithSuccess:success executeCommand:command]; + [self runCompletionCallbackWithSuccess:success + showAccountsSettings:showAccountsSettings]; }; [self dismissPresentedViewControllersAnimated:YES completion:completion]; } @@ -328,7 +339,8 @@ - (void)didSkipSignIn:(ChromeSigninViewController*)controller { DCHECK_EQ(controller, signinViewController_); - [self dismissSigninViewControllerWithSignInSuccess:NO executeCommand:nil]; + [self dismissSigninViewControllerWithSignInSuccess:NO + showAccountsSettings:NO]; } - (void)didSignIn:(ChromeSigninViewController*)controller { @@ -349,26 +361,28 @@ ->GetChromeIdentityService() ->ForgetIdentity(identity, nil); } - [self dismissSigninViewControllerWithSignInSuccess:NO executeCommand:nil]; + [self dismissSigninViewControllerWithSignInSuccess:NO + showAccountsSettings:NO]; } } - (void)didFailSignIn:(ChromeSigninViewController*)controller { DCHECK_EQ(controller, signinViewController_); - [self dismissSigninViewControllerWithSignInSuccess:NO executeCommand:nil]; + [self dismissSigninViewControllerWithSignInSuccess:NO + showAccountsSettings:NO]; } - (void)didAcceptSignIn:(ChromeSigninViewController*)controller - executeCommand:(GenericChromeCommand*)command { + showAccountsSettings:(BOOL)showAccountsSettings { DCHECK_EQ(controller, signinViewController_); [self dismissSigninViewControllerWithSignInSuccess:YES - executeCommand:command]; + showAccountsSettings:showAccountsSettings]; } #pragma mark - Utility methods - (void)runCompletionCallbackWithSuccess:(BOOL)success - executeCommand:(GenericChromeCommand*)command { + showAccountsSettings:(BOOL)showAccountsSettings { // In order to avoid awkward double transitions, |identityInteractionManager_| // is not dismissed when requested (except when canceling). However, in case // of errors, |identityInteractionManager_| needs to be directly dismissed, @@ -379,7 +393,6 @@ identityInteractionManager_ = nil; signinViewController_ = nil; - UIViewController* presentingViewController = presentingViewController_; // Ensure self is not destroyed in the callbacks. SigninInteractionController* strongSelf = self; if (completionCallback_) { @@ -387,8 +400,8 @@ completionCallback_ = nil; } strongSelf = nil; - if (command) { - [presentingViewController chromeExecuteCommand:command]; + if (showAccountsSettings) { + [self.dispatcher showAccountsSettings]; } }
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index f2775a49..82d7c0d1 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -951,6 +951,16 @@ forProtocol:@protocol(BrowserCommands)]; [_dispatcher startDispatchingToTarget:applicationCommandEndpoint forProtocol:@protocol(ApplicationCommands)]; + // -startDispatchingToTarget:forProtocol: doesn't pick up protocols the + // passed protocol conforms to, so ApplicationSettingsCommands is explicitly + // dispatched to the endpoint as well. Since this is potentially + // fragile, DCHECK that it should still work (if the endpoint is nonnull). + DCHECK(!applicationCommandEndpoint || + [applicationCommandEndpoint + conformsToProtocol:@protocol(ApplicationSettingsCommands)]); + [_dispatcher + startDispatchingToTarget:applicationCommandEndpoint + forProtocol:@protocol(ApplicationSettingsCommands)]; _javaScriptDialogPresenter.reset( new JavaScriptDialogPresenterImpl(_dialogPresenter));
diff --git a/ios/chrome/browser/ui/commands/BUILD.gn b/ios/chrome/browser/ui/commands/BUILD.gn index 78cc897c..1da2ed3f 100644 --- a/ios/chrome/browser/ui/commands/BUILD.gn +++ b/ios/chrome/browser/ui/commands/BUILD.gn
@@ -29,6 +29,7 @@ "//base", "//components/browsing_data/core", "//components/signin/core/browser", + "//ios/shared/chrome/browser/ui/commands", "//ios/web", "//net", "//url",
diff --git a/ios/chrome/browser/ui/commands/application_commands.h b/ios/chrome/browser/ui/commands/application_commands.h index eea29e8e..48eec6bc 100644 --- a/ios/chrome/browser/ui/commands/application_commands.h +++ b/ios/chrome/browser/ui/commands/application_commands.h
@@ -9,11 +9,23 @@ @class OpenNewTabCommand; +// This protocol groups commands that are part of ApplicationCommands, but +// may also be forwarded directly to a settings navigation controller. +@protocol ApplicationSettingsCommands + +// Shows the accounts settings. +- (void)showAccountsSettings; + +@end + // Protocol for commands that will generally be handled by the application, // rather than a specific tab; in practice this means the MainController // instance. +// This protocol includes all of the methods in ApplicationSettingsCommands; an +// object that implements the methods in this protocol should be able to forward +// ApplicationSettingsCommands to the settings view controller if necessary. -@protocol ApplicationCommands<NSObject> +@protocol ApplicationCommands<NSObject, ApplicationSettingsCommands> // Shows the Settings UI. - (void)showSettings;
diff --git a/ios/chrome/browser/ui/commands/ios_command_ids.h b/ios/chrome/browser/ui/commands/ios_command_ids.h index 941ed2b..bab3cdfc 100644 --- a/ios/chrome/browser/ui/commands/ios_command_ids.h +++ b/ios/chrome/browser/ui/commands/ios_command_ids.h
@@ -47,7 +47,6 @@ #define IDC_PRELOAD_VOICE_SEARCH 40937 #define IDC_SHOW_BACK_HISTORY 40938 #define IDC_SHOW_FORWARD_HISTORY 40939 -#define IDC_SHOW_ACCOUNTS_SETTINGS 40943 #define IDC_CLOSE_SETTINGS 40944 #define IDC_SHOW_SAVE_PASSWORDS_SETTINGS 40945 #define IDC_READER_MODE 40947
diff --git a/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.h b/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.h index 5031039..e3b85cc 100644 --- a/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.h +++ b/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.h
@@ -10,12 +10,12 @@ extern NSString* const kSignInButtonAccessibilityIdentifier; extern NSString* const kSignInSkipButtonAccessibilityIdentifier; +@protocol ApplicationSettingsCommands; @class FirstRunConfiguration; -@class TabModel; - namespace ios { class ChromeBrowserState; } +@class TabModel; // A ChromeSigninViewController that is used during the run. @interface FirstRunChromeSigninViewController : ChromeSigninViewController @@ -24,7 +24,9 @@ - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState tabModel:(TabModel*)tabModel firstRunConfig:(FirstRunConfiguration*)firstRunConfig - signInIdentity:(ChromeIdentity*)identity; + signInIdentity:(ChromeIdentity*)identity + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher; @end
diff --git a/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm b/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm index 2a7d267..2312766 100644 --- a/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm
@@ -9,8 +9,7 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/first_run/first_run_configuration.h" #import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" -#import "ios/chrome/browser/ui/commands/generic_chrome_command.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/first_run/first_run_util.h" #import "ios/chrome/browser/ui/promos/signin_promo_view_controller.h" #include "ios/chrome/browser/ui/ui_util.h" @@ -45,14 +44,17 @@ - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState tabModel:(TabModel*)tabModel firstRunConfig:(FirstRunConfiguration*)firstRunConfig - signInIdentity:(ChromeIdentity*)identity { + signInIdentity:(ChromeIdentity*)identity + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { self = [super initWithBrowserState:browserState isPresentedOnSettings:NO accessPoint:signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE promoAction:signin_metrics::PromoAction:: PROMO_ACTION_NO_SIGNIN_PROMO - signInIdentity:identity]; + signInIdentity:identity + dispatcher:dispatcher]; if (self) { _tabModel = tabModel; _firstRunConfig = firstRunConfig; @@ -154,12 +156,14 @@ } - (void)didAcceptSignIn:(ChromeSigninViewController*)controller - executeCommand:(GenericChromeCommand*)command { + showAccountsSettings:(BOOL)showAccountsSettings { DCHECK_EQ(self, controller); // User is done with First Run after explicit sign-in accept. [self finishFirstRunAndDismiss]; - [command executeOnMainWindow]; + if (showAccountsSettings) { + [self.dispatcher showAccountsSettings]; + } } #pragma mark ChromeSigninViewController
diff --git a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h index bbc0064..c8c4ebb 100644 --- a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h +++ b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h
@@ -9,6 +9,7 @@ extern NSString* const kUMAMetricsButtonAccessibilityIdentifier; +@protocol ApplicationSettingsCommands; @class TabModel; namespace ios { @@ -29,6 +30,7 @@ // which can be nil. - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState tabModel:(TabModel*)tabModel + dispatcher:(id<ApplicationSettingsCommands>)dispatcher NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNibName:(NSString*)nibNameOrNil
diff --git a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm index ef930b3..b43a67e 100644 --- a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.mm
@@ -55,11 +55,14 @@ // The animation which occurs at launch has run. @property(nonatomic, assign) BOOL ranLaunchAnimation; +@property(nonatomic, readonly, weak) id<ApplicationSettingsCommands> dispatcher; + @end @implementation WelcomeToChromeViewController @synthesize ranLaunchAnimation = _ranLaunchAnimation; +@synthesize dispatcher = _dispatcher; + (BOOL)defaultStatsCheckboxValue { // Record metrics reporting as opt-in/opt-out only once. @@ -74,13 +77,16 @@ } - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState - tabModel:(TabModel*)tabModel { + tabModel:(TabModel*)tabModel + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { DCHECK(browserState); DCHECK(tabModel); self = [super initWithNibName:nil bundle:nil]; if (self) { browserState_ = browserState; tabModel_ = tabModel; + _dispatcher = dispatcher; } return self; } @@ -167,7 +173,8 @@ initWithBrowserState:browserState_ tabModel:tabModel_ firstRunConfig:firstRunConfig - signInIdentity:nil]; + signInIdentity:nil + dispatcher:self.dispatcher]; CATransition* transition = [CATransition animation]; transition.duration = kFadeOutAnimationDuration;
diff --git a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller_unittest.mm b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller_unittest.mm index 59d76fd..62ff0199 100644 --- a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller_unittest.mm
@@ -43,7 +43,8 @@ id tabModel = [OCMockObject mockForClass:[TabModel class]]; controller_ = [[WelcomeToChromeViewController alloc] initWithBrowserState:chrome_browser_state_.get() - tabModel:tabModel]; + tabModel:tabModel + dispatcher:nil]; [controller_ loadView]; }
diff --git a/ios/chrome/browser/ui/promos/BUILD.gn b/ios/chrome/browser/ui/promos/BUILD.gn index ef35caf..7b12027a 100644 --- a/ios/chrome/browser/ui/promos/BUILD.gn +++ b/ios/chrome/browser/ui/promos/BUILD.gn
@@ -5,7 +5,7 @@ source_set("promos") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "promo_view_controller.h", + # TODO(crbug.com/738881): Just move this into ui/signin "signin_promo_view_controller.h", "signin_promo_view_controller.mm", ]
diff --git a/ios/chrome/browser/ui/promos/promo_view_controller.h b/ios/chrome/browser/ui/promos/promo_view_controller.h deleted file mode 100644 index fd737d76..0000000 --- a/ios/chrome/browser/ui/promos/promo_view_controller.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2013 The Chromium 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_PROMOS_PROMO_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_PROMOS_PROMO_VIEW_CONTROLLER_H_ - -#import <UIKit/UIKit.h> - -#import "base/mac/scoped_nsobject.h" - -// Protocol for promotion view controllers. -// -// Note: On iPhone, this controller supports portrait orientation only. It -// should always be presented in an |OrientationLimitingNavigationController|. -@protocol PromoViewController - -// Returns whether or not a promo of the class type should be displayed. -// Subclasses should override this method. Base implementation returns NO. -+ (BOOL)shouldBePresentedForBrowserState:(ios::ChromeBrowserState*)browserState; - -// Returns an autoreleased subclass object, which will be displayed. -// Sublasses should override this method. Base implementation returns nil. -+ (UIViewController*)controllerToPresentForBrowserState: - (ios::ChromeBrowserState*)browserState; - -@end - -#endif // IOS_CHROME_BROWSER_UI_PROMOS_PROMO_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/promos/signin_promo_view_controller.h b/ios/chrome/browser/ui/promos/signin_promo_view_controller.h index 93e6698..ee254ad 100644 --- a/ios/chrome/browser/ui/promos/signin_promo_view_controller.h +++ b/ios/chrome/browser/ui/promos/signin_promo_view_controller.h
@@ -8,10 +8,8 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h" -#import "ios/chrome/browser/ui/promos/promo_view_controller.h" -@class SigninPromoViewController; - +@protocol ApplicationSettingsCommands; namespace ios { class ChromeBrowserState; } @@ -26,11 +24,15 @@ // // Note: On iPhone, this controller supports portrait orientation only. It // should always be presented in an |OrientationLimitingNavigationController|. -@interface SigninPromoViewController - : ChromeSigninViewController<PromoViewController> +@interface SigninPromoViewController : ChromeSigninViewController + +// YES if this promo should be shown for |browserState| ++ (BOOL)shouldBePresentedForBrowserState:(ios::ChromeBrowserState*)browserState; // Designated initializer. |browserState| must not be nil. -- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState; +- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher; // Records in user defaults that the promo has been shown along with the current // version number.
diff --git a/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm b/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm index 53f6bac..c52d1ce 100644 --- a/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm +++ b/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm
@@ -14,7 +14,7 @@ #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/signin/authentication_service.h" #include "ios/chrome/browser/signin/authentication_service_factory.h" -#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/signin/chrome_identity_service.h" #include "net/base/network_change_notifier.h" @@ -62,14 +62,17 @@ BOOL _addAccountOperation; } -- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { +- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { self = [super initWithBrowserState:browserState isPresentedOnSettings:NO accessPoint:signin_metrics::AccessPoint:: ACCESS_POINT_SIGNIN_PROMO promoAction:signin_metrics::PromoAction:: PROMO_ACTION_NO_SIGNIN_PROMO - signInIdentity:nil]; + signInIdentity:nil + dispatcher:dispatcher]; if (self) { super.delegate = self; } @@ -90,15 +93,14 @@ } - (void)dismissWithSignedIn:(BOOL)signedIn - executeCommand:(GenericChromeCommand*)command { + showAccountsSettings:(BOOL)showAccountsSettings { DCHECK(self.presentingViewController); UIViewController* presentingViewController = self.presentingViewController; [presentingViewController dismissViewControllerAnimated:YES completion:^{ - if (command) { - [presentingViewController - chromeExecuteCommand:command]; + if (showAccountsSettings) { + [self.dispatcher showAccountsSettings]; } }]; } @@ -176,12 +178,6 @@ return [identities count] > 0; } -+ (UIViewController*)controllerToPresentForBrowserState: - (ios::ChromeBrowserState*)browserState { - UIViewController* controller = - [[SigninPromoViewController alloc] initWithBrowserState:browserState]; - return controller; -} #pragma mark - ChromeSigninViewControllerDelegate @@ -199,12 +195,12 @@ DCHECK_EQ(self, controller); UMA_HISTOGRAM_ENUMERATION(kUMASSORecallPromoAction, ACTION_DISMISSED, PROMO_ACTION_COUNT); - [self dismissWithSignedIn:NO executeCommand:nil]; + [self dismissWithSignedIn:NO showAccountsSettings:NO]; } - (void)didFailSignIn:(ChromeSigninViewController*)controller { DCHECK_EQ(self, controller); - [self dismissWithSignedIn:NO executeCommand:nil]; + [self dismissWithSignedIn:NO showAccountsSettings:NO]; } - (void)didSignIn:(ChromeSigninViewController*)controller { @@ -218,14 +214,14 @@ } - (void)didAcceptSignIn:(ChromeSigninViewController*)controller - executeCommand:(GenericChromeCommand*)command { + showAccountsSettings:(BOOL)showAccountsSettings { DCHECK_EQ(self, controller); PromoAction promoAction = _addAccountOperation ? ACTION_ADDED_ANOTHER_ACCOUNT : ACTION_ENABLED_SSO_ACCOUNT; UMA_HISTOGRAM_ENUMERATION(kUMASSORecallPromoAction, promoAction, PROMO_ACTION_COUNT); - [self dismissWithSignedIn:YES executeCommand:command]; + [self dismissWithSignedIn:YES showAccountsSettings:showAccountsSettings]; } @end
diff --git a/ios/chrome/browser/ui/promos/signin_promo_view_controller_unittest.mm b/ios/chrome/browser/ui/promos/signin_promo_view_controller_unittest.mm index 29b10c1..2ae19d6 100644 --- a/ios/chrome/browser/ui/promos/signin_promo_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/promos/signin_promo_view_controller_unittest.mm
@@ -88,7 +88,8 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() ->AddIdentities(@[ @"foo", @"bar" ]); controller_ = [[FakeVersionSigninPromoViewController alloc] - initWithBrowserState:chrome_browser_state_.get()]; + initWithBrowserState:chrome_browser_state_.get() + dispatcher:nil]; } void TearDown() override {
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index b416d79..2915c2c 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -163,7 +163,7 @@ "//ios/public/provider/chrome/browser/signin", "//ios/public/provider/chrome/browser/user_feedback", "//ios/public/provider/chrome/browser/voice", - "//ios/shared/chrome/browser/ui/settings", + "//ios/shared/chrome/browser/ui/commands", "//ios/third_party/material_components_ios", "//ios/third_party/material_roboto_font_loader_ios", "//ios/web",
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h index f22449de..0d974878 100644 --- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h +++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h
@@ -18,6 +18,7 @@ // The accessibility identifier of the sync account cell. extern NSString* const kSettingsAccountsSyncCellId; +@protocol ApplicationSettingsCommands; namespace ios { class ChromeBrowserState; } // namespace ios @@ -33,6 +34,7 @@ // controller will close the setting screen when an account is added. - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount + dispatcher:(id<ApplicationSettingsCommands>)dispatcher NS_DESIGNATED_INITIALIZER; - (instancetype)initWithLayout:(UICollectionViewLayout*)layout
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm index bd7ceaa..08f0da6 100644 --- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
@@ -111,12 +111,18 @@ // phase to avoid observing services for a browser state that is being killed. - (void)stopBrowserStateServiceObservers; +@property(nonatomic, readonly, weak) id<ApplicationSettingsCommands> dispatcher; + @end @implementation AccountsCollectionViewController +@synthesize dispatcher = _dispatcher; + - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState - closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount { + closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount + dispatcher: + (id<ApplicationSettingsCommands>)dispatcher { DCHECK(browserState); DCHECK(!browserState->IsOffTheRecord()); UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; @@ -125,6 +131,7 @@ if (self) { _browserState = browserState; _closeSettingsOnAddAccount = closeSettingsOnAddAccount; + _dispatcher = dispatcher; browser_sync::ProfileSyncService* syncService = IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState); _syncObserver.reset(new SyncObserverBridge(self, syncService)); @@ -486,7 +493,8 @@ accessPoint:signin_metrics::AccessPoint:: ACCESS_POINT_SETTINGS promoAction:signin_metrics::PromoAction:: - PROMO_ACTION_NO_SIGNIN_PROMO]; + PROMO_ACTION_NO_SIGNIN_PROMO + dispatcher:self.dispatcher]; // |_authenticationOperationInProgress| is reset when the signin interaction // controller is dismissed.
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.h b/ios/chrome/browser/ui/settings/settings_collection_view_controller.h index 1b43cab..14ac579 100644 --- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.h +++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.h
@@ -8,6 +8,7 @@ #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" +@protocol ApplicationCommands; @protocol SettingsMainPageCommands; @class SigninInteractionController; namespace ios { @@ -38,12 +39,15 @@ @property(weak, nonatomic, readonly) SigninInteractionController* signinInteractionController; -// This controller's dispatcher. By default it is the controller itself. -@property(weak, nonatomic) id<SettingsMainPageCommands> dispatcher; +// Dispatcher for SettingsMainPageCommands. Defaults to self if not set. +// TODO(crbug.com/738881): Unify this with the dispatcher passed into the init. +@property(weak, nonatomic) id<SettingsMainPageCommands> + settingsMainPageDispatcher; // Initializes a new SettingsCollectionViewController. |browserState| must not // be nil and must not be an off-the-record browser state. - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState + dispatcher:(id<ApplicationCommands>)dispatcher NS_DESIGNATED_INITIALIZER; - (instancetype)initWithLayout:(UICollectionViewLayout*)layout
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm index 0a24ee54..68cc1d7 100644 --- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -53,6 +53,7 @@ #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/settings/about_chrome_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h" @@ -158,11 +159,11 @@ SettingsCollectionViewController* owner) : owner_(owner), observer_(this) { DCHECK(owner_); - SigninManager* sigin_manager = + SigninManager* signin_manager = ios::SigninManagerFactory::GetForBrowserState(browserState); - if (!sigin_manager) + if (!signin_manager) return; - observer_.Add(sigin_manager); + observer_.Add(signin_manager); } void SigninObserverBridge::GoogleSigninSucceeded(const std::string& account_id, @@ -231,6 +232,8 @@ BOOL _signinStarted; } +@property(nonatomic, readonly, weak) id<ApplicationCommands> dispatcher; + // Stops observing browser state services. This is required during the shutdown // phase to avoid observing services for a profile that is being killed. - (void)stopBrowserStateServiceObservers; @@ -238,11 +241,13 @@ @end @implementation SettingsCollectionViewController +@synthesize settingsMainPageDispatcher = _settingsMainPageDispatcher; @synthesize dispatcher = _dispatcher; #pragma mark Initialization -- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { +- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState + dispatcher:(id<ApplicationCommands>)dispatcher { DCHECK(!browserState->IsOffTheRecord()); UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; self = @@ -283,7 +288,8 @@ _prefObserverBridge->ObserveChangesForPreference( autofill::prefs::kAutofillEnabled, &_prefChangeRegistrar); - _dispatcher = self; + _settingsMainPageDispatcher = self; + _dispatcher = dispatcher; [self loadModel]; } @@ -740,7 +746,8 @@ case ItemTypeAccount: controller = [[AccountsCollectionViewController alloc] initWithBrowserState:_browserState - closeSettingsOnAddAccount:NO]; + closeSettingsOnAddAccount:NO + dispatcher:self.dispatcher]; break; case ItemTypeSearchEngine: controller = [[SearchEngineSettingsCollectionViewController alloc] @@ -782,7 +789,7 @@ // and only the switch is tappable. break; case ItemTypeCellCatalog: - [self.dispatcher showMaterialCellCatalog]; + [self.settingsMainPageDispatcher showMaterialCellCatalog]; break; default: break; @@ -985,7 +992,8 @@ isPresentedOnSettings:YES accessPoint:signin_metrics::AccessPoint:: ACCESS_POINT_SETTINGS - promoAction:promoAction]; + promoAction:promoAction + dispatcher:self.dispatcher]; __weak SettingsCollectionViewController* weakSelf = self; [_signinInteractionController
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.h b/ios/chrome/browser/ui/settings/settings_navigation_controller.h index c7c99cf..e3a61336 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.h +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.h
@@ -7,8 +7,11 @@ #import <UIKit/UIKit.h> -@class OpenUrlCommand; +#import "ios/chrome/browser/ui/commands/application_commands.h" + +@protocol BrowserCommands; @protocol ImportDataControllerDelegate; +@class OpenUrlCommand; @protocol UserFeedbackDataSource; namespace ios { @@ -37,10 +40,15 @@ // closed. - (void)closeSettings; +// Asks the delegate for a dispatcher that can be passed into child view +// controllers when they are created. +- (id<ApplicationCommands, BrowserCommands>)dispatcherForSettings; + @end // Controller to modify user settings. -@interface SettingsNavigationController : UINavigationController +@interface SettingsNavigationController + : UINavigationController<ApplicationSettingsCommands> // Whether sync changes should be committed when the settings are being // dismissed. Defaults to YES.
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index 00d47a8..3794b1ad 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -117,8 +117,10 @@ delegate: (id<SettingsNavigationControllerDelegate>) delegate { - UIViewController* controller = [[SettingsCollectionViewController alloc] - initWithBrowserState:browserState]; + SettingsCollectionViewController* controller = + [[SettingsCollectionViewController alloc] + initWithBrowserState:browserState + dispatcher:[delegate dispatcherForSettings]]; SettingsNavigationController* nc = [[SettingsNavigationController alloc] initWithRootViewController:controller browserState:browserState @@ -132,7 +134,8 @@ delegate:(id<SettingsNavigationControllerDelegate>)delegate { UIViewController* controller = [[AccountsCollectionViewController alloc] initWithBrowserState:browserState - closeSettingsOnAddAccount:YES]; + closeSettingsOnAddAccount:YES + dispatcher:[delegate dispatcherForSettings]]; SettingsNavigationController* nc = [[SettingsNavigationController alloc] initWithRootViewController:controller browserState:browserState @@ -500,13 +503,6 @@ CHECK_EQ(commandBrowserState, [self mainBrowserState]); break; } - case IDC_SHOW_ACCOUNTS_SETTINGS: { - UIViewController* controller = [[AccountsCollectionViewController alloc] - initWithBrowserState:mainBrowserState_ - closeSettingsOnAddAccount:NO]; - [self pushViewController:controller animated:YES]; - return; - } case IDC_SHOW_SYNC_SETTINGS: { UIViewController* controller = [[SyncSettingsCollectionViewController alloc] @@ -547,6 +543,16 @@ ]; } +#pragma mark - ApplicationSettingsCommands + +- (void)showAccountsSettings { + UIViewController* controller = [[AccountsCollectionViewController alloc] + initWithBrowserState:mainBrowserState_ + closeSettingsOnAddAccount:NO + dispatcher:[delegate_ dispatcherForSettings]]; + [self pushViewController:controller animated:YES]; +} + #pragma mark - Profile - (ios::ChromeBrowserState*)mainBrowserState {
diff --git a/ios/clean/chrome/browser/ui/settings/BUILD.gn b/ios/clean/chrome/browser/ui/settings/BUILD.gn index da44106..fae4fa0 100644 --- a/ios/clean/chrome/browser/ui/settings/BUILD.gn +++ b/ios/clean/chrome/browser/ui/settings/BUILD.gn
@@ -23,7 +23,6 @@ "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", - "//ios/shared/chrome/browser/ui/settings", ] }
diff --git a/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm b/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm index 751023cf..8194051 100644 --- a/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm +++ b/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm
@@ -73,6 +73,10 @@ [static_cast<id>(self.browser->dispatcher()) closeSettings]; } +- (id)dispatcherForSettings { + return nil; +} + #pragma mark - UINavigationControllerDelegate - (void)navigationController:(UINavigationController*)navigationController
diff --git a/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm b/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm index 89ef68f9..e89125d 100644 --- a/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm +++ b/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm
@@ -26,12 +26,15 @@ - (void)start { DCHECK(!self.browser->browser_state()->IsOffTheRecord()); + // TODO(crbug.com/738881): Clean up the dispatcher mess here. self.viewController = [[SettingsCollectionViewController alloc] - initWithBrowserState:self.browser->browser_state()]; + initWithBrowserState:self.browser->browser_state() + dispatcher:nil]; [self.browser->dispatcher() startDispatchingToTarget:self forProtocol:@protocol(SettingsMainPageCommands)]; - self.viewController.dispatcher = static_cast<id>(self.browser->dispatcher()); + self.viewController.settingsMainPageDispatcher = + static_cast<id<SettingsMainPageCommands>>(self.browser->dispatcher()); [super start]; }
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index f3beab2..1029ebe 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -7,6 +7,8 @@ #include <stddef.h> #include <algorithm> +#include <map> +#include <utility> #include "base/command_line.h" #include "base/environment.h" @@ -260,6 +262,54 @@ return params; } +std::string AudioManagerCras::GetAssociatedOutputDeviceID( + const std::string& input_device_id) { + if (!base::FeatureList::IsEnabled(features::kEnumerateAudioDevices)) + return ""; + + chromeos::AudioDeviceList devices; + chromeos::CrasAudioHandler* audio_handler = chromeos::CrasAudioHandler::Get(); + audio_handler->GetAudioDevices(&devices); + + if ((beamforming_on_device_id_ && + input_device_id == beamforming_on_device_id_) || + (beamforming_off_device_id_ && + input_device_id == beamforming_off_device_id_)) { + // These are special devices derived from the internal mic array, so they + // should be associated to the internal speaker. + const chromeos::AudioDevice* internal_speaker = + audio_handler->GetDeviceByType(chromeos::AUDIO_TYPE_INTERNAL_SPEAKER); + return internal_speaker ? base::Uint64ToString(internal_speaker->id) : ""; + } + + // At this point, we know we have an ordinary input device, so we look up its + // device_name, which identifies which hardware device it belongs to. + uint64_t device_id = 0; + if (!base::StringToUint64(input_device_id, &device_id)) + return ""; + const chromeos::AudioDevice* input_device = + audio_handler->GetDeviceFromId(device_id); + if (!input_device) + return ""; + + const base::StringPiece device_name = input_device->device_name; + + // Now search for an output device with the same device name. + auto output_device_it = std::find_if( + devices.begin(), devices.end(), + [device_name](const chromeos::AudioDevice& device) { + return !device.is_input && device.device_name == device_name; + }); + return output_device_it == devices.end() + ? "" + : base::Uint64ToString(output_device_it->id); +} + +std::string AudioManagerCras::GetDefaultOutputDeviceID() { + return base::Uint64ToString( + chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode()); +} + const char* AudioManagerCras::GetName() { return "CRAS"; }
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h index f23d132..7cf1200 100644 --- a/media/audio/cras/audio_manager_cras.h +++ b/media/audio/cras/audio_manager_cras.h
@@ -7,7 +7,9 @@ #include <cras_types.h> +#include <memory> #include <string> +#include <vector> #include "base/compiler_specific.h" #include "base/macros.h" @@ -30,6 +32,9 @@ void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters( const std::string& device_id) override; + std::string GetAssociatedOutputDeviceID( + const std::string& input_device_id) override; + std::string GetDefaultOutputDeviceID() override; const char* GetName() override; // AudioManagerBase implementation.
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h index 0d84abd3..576b2ca 100644 --- a/services/metrics/public/cpp/ukm_recorder.h +++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -27,6 +27,7 @@ class SubresourceFilterMetricsObserver; class UkmPageLoadMetricsObserver; class LocalNetworkRequestsPageLoadMetricsObserver; +class MediaEngagementContentsObserver; namespace autofill { class AutofillMetrics; @@ -116,6 +117,7 @@ friend password_manager::PasswordFormMetricsRecorder; friend previews::PreviewsUKMObserver; friend resource_coordinator::CoordinationUnitManager; + friend MediaEngagementContentsObserver; FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, AddEntryWithEmptyMetrics); FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, EntryBuilderAndSerialization); FRIEND_TEST_ALL_PREFIXES(UkmServiceTest,
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc index 9d888b6..ffa871a 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
@@ -44,6 +44,20 @@ g_instance = nullptr; } +void MemoryInstrumentation::RequestGlobalDump( + RequestGlobalDumpCallback callback) { + const auto& coordinator = GetCoordinatorBindingForCurrentThread(); + auto callback_adapter = [](RequestGlobalDumpCallback callback, bool success, + uint64_t dump_id, mojom::GlobalMemoryDumpPtr ptr) { + if (callback) + callback.Run(success, std::move(ptr)); + }; + base::trace_event::MemoryDumpRequestArgs args = { + 0, MemoryDumpType::SUMMARY_ONLY, MemoryDumpLevelOfDetail::BACKGROUND}; + coordinator->RequestGlobalMemoryDump(args, + base::Bind(callback_adapter, callback)); +} + void MemoryInstrumentation::RequestGlobalDumpAndAppendToTrace( MemoryDumpType dump_type, MemoryDumpLevelOfDetail level_of_detail,
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h index a8e38ae..aa872c7 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
@@ -29,6 +29,8 @@ public: using MemoryDumpType = base::trace_event::MemoryDumpType; using MemoryDumpLevelOfDetail = base::trace_event::MemoryDumpLevelOfDetail; + using RequestGlobalDumpCallback = + base::Callback<void(bool success, mojom::GlobalMemoryDumpPtr)>; using RequestGlobalDumpAndAppendToTraceCallback = base::Callback<void(bool success, uint64_t dump_id)>; @@ -36,6 +38,14 @@ const std::string& service_name); static MemoryInstrumentation* GetInstance(); + // Requests a global memory dump. + // Returns asynchronously, via the callback argument: + // (true, global_dump) if succeeded; + // (false, nullptr) if failed. + // The callback (if not null), will be posted on the same thread of the + // RequestGlobalDump() call. + void RequestGlobalDump(RequestGlobalDumpCallback); + // Requests a global memory dump and serializes the result into the trace. // This requires that both tracing and the memory-infra category have been // previousy enabled. Will just gracefully fail otherwise.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 46786d2..fe70666 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2787,11 +2787,8 @@ crbug.com/657748 external/wpt/css/css-display-3/display-contents-before-after-002.html [ Failure ] crbug.com/657748 external/wpt/css/css-display-3/display-contents-dynamic-flex-002-inline.html [ Failure ] crbug.com/657748 external/wpt/css/css-display-3/display-contents-dynamic-flex-002-none.html [ Failure ] -crbug.com/657748 external/wpt/css/css-display-3/display-contents-dynamic-flex-003-inline.html [ Failure ] -crbug.com/657748 external/wpt/css/css-display-3/display-contents-dynamic-flex-003-none.html [ Failure ] crbug.com/657748 external/wpt/css/css-display-3/display-contents-dynamic-table-001-inline.html [ Failure ] crbug.com/657748 external/wpt/css/css-display-3/display-contents-flex-002.html [ Failure ] -crbug.com/657748 external/wpt/css/css-display-3/display-contents-flex-003.html [ Failure ] # ====== End of display: contents tests ======
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/page/frameNavigatedToUnreachableUrl-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/page/frameNavigatedToUnreachableUrl-expected.txt new file mode 100644 index 0000000..db23b959 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/page/frameNavigatedToUnreachableUrl-expected.txt
@@ -0,0 +1,4 @@ +Tests that the unreachable url is reported when navigating to a nonexistent page. +Page navigated, url = data:text/html,chromewebdata +UnreachableUrl = idont_exist.html +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/page/frameNavigatedToUnreachableUrl.js b/third_party/WebKit/LayoutTests/inspector-protocol/page/frameNavigatedToUnreachableUrl.js new file mode 100644 index 0000000..ea4a70e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/page/frameNavigatedToUnreachableUrl.js
@@ -0,0 +1,17 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank( + 'Tests that the unreachable url is reported when navigating to a ' + + 'nonexistent page.'); + + dp.Page.enable(); + session.evaluate(` + var frame = document.createElement('iframe'); + frame.src = '${testRunner.url('../resources/idont_exist.html')}'; + document.body.appendChild(frame); + `); + let result = await dp.Page.onceFrameNavigated(); + testRunner.log('Page navigated, url = ' + result.params.frame.url); + testRunner.log('UnreachableUrl = ' + + result.params.frame.unreachableUrl.split('/').pop()); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py index 62d0866..f0509f8 100644 --- a/third_party/WebKit/PRESUBMIT.py +++ b/third_party/WebKit/PRESUBMIT.py
@@ -32,7 +32,9 @@ results = [] if errors: results.append(output_api.PresubmitError( - 'Files that include non-Blink variant mojoms found:', errors)) + 'Files that include non-Blink variant mojoms found. ' + 'You must include .mojom-blink.h or .mojom-shared.h instead:', + errors)) return results
diff --git a/third_party/WebKit/Source/controller/BUILD.gn b/third_party/WebKit/Source/controller/BUILD.gn index f2d71745..f2d66bf 100644 --- a/third_party/WebKit/Source/controller/BUILD.gn +++ b/third_party/WebKit/Source/controller/BUILD.gn
@@ -19,6 +19,7 @@ "//third_party/WebKit/Source/core", "//third_party/WebKit/Source/modules", "//third_party/WebKit/Source/platform", + "//third_party/WebKit/Source/web", "//v8", ] @@ -34,7 +35,6 @@ sources = [ "BlinkInitializer.cpp", - "BlinkInitializer.h", "ControllerExport.h", ]
diff --git a/third_party/WebKit/Source/controller/BlinkInitializer.cpp b/third_party/WebKit/Source/controller/BlinkInitializer.cpp index 8add6961..a314d18a 100644 --- a/third_party/WebKit/Source/controller/BlinkInitializer.cpp +++ b/third_party/WebKit/Source/controller/BlinkInitializer.cpp
@@ -28,8 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "controller/BlinkInitializer.h" - #include "bindings/core/v8/V8Initializer.h" #include "core/animation/AnimationClock.h" #include "modules/ModulesInitializer.h" @@ -41,7 +39,9 @@ #include "platform/wtf/WTF.h" #include "public/platform/Platform.h" #include "public/platform/WebThread.h" +#include "public/web/WebKit.h" #include "v8/include/v8.h" +#include "web/WebFactoryImpl.h" namespace blink { @@ -66,13 +66,15 @@ return *initializer; } -void InitializeBlink(Platform* platform) { +void Initialize(Platform* platform) { Platform::Initialize(platform); V8Initializer::InitializeMainThread(); GetModulesInitializer().Initialize(); + WebFactoryImpl::Initialize(); + // currentThread is null if we are running on a thread without a message loop. if (WebThread* current_thread = platform->CurrentThread()) { DCHECK(!g_end_of_task_runner);
diff --git a/third_party/WebKit/Source/controller/BlinkInitializer.h b/third_party/WebKit/Source/controller/BlinkInitializer.h deleted file mode 100644 index 98690599..0000000 --- a/third_party/WebKit/Source/controller/BlinkInitializer.h +++ /dev/null
@@ -1,19 +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 BlinkInitializer_h -#define BlinkInitializer_h - -#include "controller/ControllerExport.h" - -namespace blink { - -class Platform; - -// The embedder must call this function before using blink. -CONTROLLER_EXPORT void InitializeBlink(Platform*); - -} // namespace blink - -#endif // BlinkInitializer_h
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index c120cc0..743abe13 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1106,8 +1106,7 @@ } # Compiles the code generated by the targets above. -jumbo_target("core_generated") { - target_type = core_link_small_target_type +target("jumbo_" + core_link_small_target_type, "core_generated") { sources = bindings_core_v8_files # Add all sources generated by the targets above.
diff --git a/third_party/WebKit/Source/core/core.gni b/third_party/WebKit/Source/core/core.gni index 0749c98..55a7de8 100644 --- a/third_party/WebKit/Source/core/core.gni +++ b/third_party/WebKit/Source/core/core.gni
@@ -74,23 +74,22 @@ # visibility # Normal meaning if defined. If undefined, defaults to everything in core. template("blink_core_sources") { - jumbo_target(target_name) { - if (is_component_build) { - target_type = "source_set" + if (is_component_build) { + target_type = "jumbo_source_set" - # This assert avoids an unused variable warning. - assert(!defined(invoker.split_count) || invoker.split_count != 0) - } else if (!defined(invoker.split_count)) { - target_type = "static_library" - } else { - target_type = "split_static_library" - } - + # This assert avoids an unused variable warning. + assert(!defined(invoker.split_count) || invoker.split_count != 0) + } else if (!defined(invoker.split_count)) { + target_type = "jumbo_static_library" + } else { + target_type = "jumbo_split_static_library" + } + target(target_type, target_name) { # The visibility will get overridden by forward_variables_from below if the # invoker defined it. visibility = [ "//third_party/WebKit/Source/core/*" ] - if (target_type == "split_static_library") { + if (target_type == "jumbo_split_static_library") { split_count = invoker.split_count }
diff --git a/third_party/WebKit/Source/core/dom/Text.cpp b/third_party/WebKit/Source/core/dom/Text.cpp index ab56be4..0459dd5 100644 --- a/third_party/WebKit/Source/core/dom/Text.cpp +++ b/third_party/WebKit/Source/core/dom/Text.cpp
@@ -282,7 +282,8 @@ if (!ContainsOnlyWhitespace()) return true; - if (!CanHaveWhitespaceChildren(parent)) + if (style.Display() != EDisplay::kContents && + !CanHaveWhitespaceChildren(parent)) return false; // pre-wrap in SVG never makes layoutObject.
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp index e79a3b3..c3c29886f 100644 --- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp +++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -38,6 +38,7 @@ #include "core/dom/TreeScope.h" #include "core/editing/EditingUtilities.h" #include "core/editing/FrameSelection.h" +#include "core/editing/SelectionModifier.h" #include "core/editing/iterators/TextIterator.h" #include "core/frame/Deprecation.h" #include "core/frame/LocalFrame.h" @@ -414,11 +415,11 @@ if (!IsAvailable()) return; - FrameSelection::EAlteration alter; + SelectionModifyAlteration alter; if (DeprecatedEqualIgnoringCase(alter_string, "extend")) - alter = FrameSelection::kAlterationExtend; + alter = SelectionModifyAlteration::kExtend; else if (DeprecatedEqualIgnoringCase(alter_string, "move")) - alter = FrameSelection::kAlterationMove; + alter = SelectionModifyAlteration::kMove; else return;
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp index 857e7dca..5367457 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -340,7 +340,7 @@ // "selectstart" event is dispatched and canceled, otherwise returns true. // When |userTriggered| is |NotUserTrigged|, return value specifies whether // selection is modified or not. -bool FrameSelection::Modify(EAlteration alter, +bool FrameSelection::Modify(SelectionModifyAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered user_triggered) {
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h index e897f56..82df7f8 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelection.h +++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -50,6 +50,7 @@ class Range; class SelectionEditor; class LayoutSelection; +enum class SelectionModifyAlteration; class TextIteratorBehavior; struct PaintInvalidatorContext; @@ -77,7 +78,6 @@ } ~FrameSelection(); - enum EAlteration { kAlterationMove, kAlterationExtend }; enum SetSelectionOption { // 1 << 0 is reserved for EUserTriggered kCloseTyping = 1 << 1, @@ -137,7 +137,7 @@ bool Contains(const LayoutPoint&); - bool Modify(EAlteration, + bool Modify(SelectionModifyAlteration, SelectionDirection, TextGranularity, EUserTriggered = kNotUserTriggered);
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp index b6dd9d6..5645187 100644 --- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp +++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -12,6 +12,7 @@ #include "core/editing/EditingTestBase.h" #include "core/editing/FrameCaret.h" #include "core/editing/SelectionController.h" +#include "core/editing/SelectionModifier.h" #include "core/frame/LocalFrameView.h" #include "core/html/HTMLBodyElement.h" #include "core/input/EventHandler.h" @@ -171,7 +172,7 @@ .Extend( ToPositionInDOMTree(PositionInFlatTree(GetDocument().body(), 2))) .Build()); - Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, + Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionForward, TextGranularity::kWord); EXPECT_EQ(Position(two, 0), VisibleSelectionInDOMTree().Start()); EXPECT_EQ(Position(two, 3), VisibleSelectionInDOMTree().End()); @@ -188,7 +189,7 @@ SelectionInDOMTree::Builder().Collapse(end_of_text).Build()); EXPECT_FALSE( - Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kCharacter, kNotUserTriggered)) << "Selection.modify() returns false for non-user-triggered call when " "selection isn't modified."; @@ -196,7 +197,7 @@ Selection().ComputeVisibleSelectionInDOMTreeDeprecated().Start()) << "Selection isn't modified"; - EXPECT_TRUE(Selection().Modify(FrameSelection::kAlterationMove, + EXPECT_TRUE(Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kCharacter, kUserTriggered)) << "Selection.modify() returns true for user-triggered call";
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp index 0dcc99e..f256911 100644 --- a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
@@ -560,14 +560,14 @@ granularity == TextGranularity::kDocumentBoundary; } -bool SelectionModifier::Modify(EAlteration alter, +bool SelectionModifier::Modify(SelectionModifyAlteration alter, SelectionDirection direction, TextGranularity granularity) { DCHECK(!GetFrame()->GetDocument()->NeedsLayoutTreeUpdate()); DocumentLifecycle::DisallowTransitionScope disallow_transition( GetFrame()->GetDocument()->Lifecycle()); - if (alter == FrameSelection::kAlterationExtend) { + if (alter == SelectionModifyAlteration::kExtend) { selection_ = CreateVisibleSelection(PrepareToExtendSeelction(selection_, direction)); } @@ -577,25 +577,25 @@ VisiblePosition position; switch (direction) { case kDirectionRight: - if (alter == FrameSelection::kAlterationMove) + if (alter == SelectionModifyAlteration::kMove) position = ModifyMovingRight(granularity); else position = ModifyExtendingRight(granularity); break; case kDirectionForward: - if (alter == FrameSelection::kAlterationExtend) + if (alter == SelectionModifyAlteration::kExtend) position = ModifyExtendingForward(granularity); else position = ModifyMovingForward(granularity); break; case kDirectionLeft: - if (alter == FrameSelection::kAlterationMove) + if (alter == SelectionModifyAlteration::kMove) position = ModifyMovingLeft(granularity); else position = ModifyExtendingLeft(granularity); break; case kDirectionBackward: - if (alter == FrameSelection::kAlterationExtend) + if (alter == SelectionModifyAlteration::kExtend) position = ModifyExtendingBackward(granularity); else position = ModifyMovingBackward(granularity); @@ -606,7 +606,7 @@ return false; if (IsSpatialNavigationEnabled(GetFrame())) { - if (!was_range && alter == FrameSelection::kAlterationMove && + if (!was_range && alter == SelectionModifyAlteration::kMove && position.DeepEquivalent() == original_start_position.DeepEquivalent()) return false; } @@ -620,14 +620,14 @@ LineDirectionPointForBlockDirectionNavigation(selection_.Start()); switch (alter) { - case FrameSelection::kAlterationMove: + case SelectionModifyAlteration::kMove: selection_ = CreateVisibleSelection( SelectionInDOMTree::Builder() .Collapse(position.ToPositionWithAffinity()) .SetIsDirectional(ShouldAlwaysUseDirectionalSelection(GetFrame())) .Build()); break; - case FrameSelection::kAlterationExtend: + case SelectionModifyAlteration::kExtend: if (!selection_.IsCaret() && (granularity == TextGranularity::kWord || @@ -712,9 +712,10 @@ return true; } -bool SelectionModifier::ModifyWithPageGranularity(EAlteration alter, - unsigned vertical_distance, - VerticalDirection direction) { +bool SelectionModifier::ModifyWithPageGranularity( + SelectionModifyAlteration alter, + unsigned vertical_distance, + VerticalDirection direction) { if (!vertical_distance) return false; @@ -722,7 +723,7 @@ DocumentLifecycle::DisallowTransitionScope disallow_transition( GetFrame()->GetDocument()->Lifecycle()); - if (alter == FrameSelection::kAlterationExtend) { + if (alter == SelectionModifyAlteration::kExtend) { selection_ = CreateVisibleSelection(PrepareToExtendSeelction( selection_, direction == FrameSelection::kDirectionUp ? kDirectionBackward @@ -732,7 +733,7 @@ VisiblePosition pos; LayoutUnit x_pos; switch (alter) { - case FrameSelection::kAlterationMove: + case SelectionModifyAlteration::kMove: pos = CreateVisiblePosition(direction == FrameSelection::kDirectionUp ? selection_.Start() : selection_.End(), @@ -741,7 +742,7 @@ direction == FrameSelection::kDirectionUp ? selection_.Start() : selection_.End()); break; - case FrameSelection::kAlterationExtend: + case SelectionModifyAlteration::kExtend: pos = CreateVisiblePosition(selection_.Extent(), selection_.Affinity()); x_pos = LineDirectionPointForBlockDirectionNavigation(selection_.Extent()); @@ -782,7 +783,7 @@ return false; switch (alter) { - case FrameSelection::kAlterationMove: + case SelectionModifyAlteration::kMove: selection_ = CreateVisibleSelection( SelectionInDOMTree::Builder() .Collapse(result.ToPositionWithAffinity()) @@ -792,7 +793,7 @@ : TextAffinity::kDownstream) .Build()); break; - case FrameSelection::kAlterationExtend: { + case SelectionModifyAlteration::kExtend: { selection_ = CreateVisibleSelection(SelectionInDOMTree::Builder() .Collapse(selection_.Base()) .Extend(result.DeepEquivalent())
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifier.h b/third_party/WebKit/Source/core/editing/SelectionModifier.h index 62fbaa7a..c77f320 100644 --- a/third_party/WebKit/Source/core/editing/SelectionModifier.h +++ b/third_party/WebKit/Source/core/editing/SelectionModifier.h
@@ -34,11 +34,12 @@ namespace blink { +enum class SelectionModifyAlteration { kMove, kExtend }; + class SelectionModifier { STACK_ALLOCATED(); public: - using EAlteration = FrameSelection::EAlteration; using VerticalDirection = FrameSelection::VerticalDirection; // |frame| is used for providing settings. @@ -52,8 +53,8 @@ } const VisibleSelection& Selection() const { return selection_; } - bool Modify(EAlteration, SelectionDirection, TextGranularity); - bool ModifyWithPageGranularity(EAlteration, + bool Modify(SelectionModifyAlteration, SelectionDirection, TextGranularity); + bool ModifyWithPageGranularity(SelectionModifyAlteration, unsigned vertical_distance, VerticalDirection);
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index b7368fd..b7e2470 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -203,7 +203,7 @@ SelectionModifier selection_modifier( frame, frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated()); if (selection_modifier.Selection().IsCaret()) - selection_modifier.Modify(FrameSelection::kAlterationExtend, direction, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, direction, granularity); StaticRangeVector* ranges = new StaticRangeVector; // We only supports single selections. @@ -1155,7 +1155,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kCharacter, kUserTriggered); return true; } @@ -1164,7 +1164,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kCharacter, kUserTriggered); return true; @@ -1174,7 +1174,7 @@ Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify(FrameSelection::kAlterationMove, + return frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kLine, kUserTriggered); } @@ -1183,8 +1183,9 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, - TextGranularity::kLine, kUserTriggered); + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kLine, + kUserTriggered); return true; } @@ -1192,7 +1193,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kCharacter, kUserTriggered); return true; } @@ -1201,8 +1202,9 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, - TextGranularity::kCharacter, kUserTriggered); + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kCharacter, + kUserTriggered); return true; } @@ -1210,7 +1212,7 @@ Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify(FrameSelection::kAlterationMove, + return frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionLeft, TextGranularity::kCharacter, kUserTriggered); } @@ -1219,7 +1221,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionLeft, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionLeft, TextGranularity::kCharacter, kUserTriggered); return true; } @@ -1227,7 +1229,7 @@ // Returns true if selection is modified. bool ModifySelectionyWithPageGranularity( LocalFrame& frame, - FrameSelection::EAlteration alter, + SelectionModifyAlteration alter, unsigned vertical_distance, FrameSelection::VerticalDirection direction) { SelectionModifier selection_modifier( @@ -1241,7 +1243,7 @@ FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle | kUserTriggered, - alter == FrameSelection::kAlterationMove + alter == SelectionModifyAlteration::kMove ? CursorAlignOnScroll::kAlways : CursorAlignOnScroll::kIfNeeded); return true; @@ -1255,7 +1257,7 @@ if (!distance) return false; return ModifySelectionyWithPageGranularity( - frame, FrameSelection::kAlterationMove, distance, + frame, SelectionModifyAlteration::kMove, distance, FrameSelection::kDirectionDown); } @@ -1267,7 +1269,7 @@ if (!distance) return false; return ModifySelectionyWithPageGranularity( - frame, FrameSelection::kAlterationExtend, distance, + frame, SelectionModifyAlteration::kExtend, distance, FrameSelection::kDirectionDown); } @@ -1279,7 +1281,7 @@ if (!distance) return false; return ModifySelectionyWithPageGranularity( - frame, FrameSelection::kAlterationMove, distance, + frame, SelectionModifyAlteration::kMove, distance, FrameSelection::kDirectionUp); } @@ -1291,7 +1293,7 @@ if (!distance) return false; return ModifySelectionyWithPageGranularity( - frame, FrameSelection::kAlterationExtend, distance, + frame, SelectionModifyAlteration::kExtend, distance, FrameSelection::kDirectionUp); } @@ -1299,7 +1301,7 @@ Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify(FrameSelection::kAlterationMove, + return frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionRight, TextGranularity::kCharacter, kUserTriggered); } @@ -1308,7 +1310,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionRight, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionRight, TextGranularity::kCharacter, kUserTriggered); return true; } @@ -1317,7 +1319,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kDocumentBoundary, kUserTriggered); return true; } @@ -1327,7 +1329,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kDocumentBoundary, kUserTriggered); return true; @@ -1337,7 +1339,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kLineBoundary, kUserTriggered); return true; } @@ -1346,7 +1348,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kLineBoundary, kUserTriggered); return true; @@ -1356,7 +1358,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kParagraphBoundary, kUserTriggered); return true; } @@ -1366,7 +1368,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kParagraphBoundary, kUserTriggered); return true; @@ -1376,7 +1378,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kSentenceBoundary, kUserTriggered); return true; } @@ -1386,7 +1388,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kSentenceBoundary, kUserTriggered); return true; @@ -1396,7 +1398,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kDocumentBoundary, kUserTriggered); return true; } @@ -1405,7 +1407,8 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kDocumentBoundary, kUserTriggered); return true; } @@ -1414,7 +1417,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kSentenceBoundary, kUserTriggered); return true; } @@ -1423,7 +1426,8 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kSentenceBoundary, kUserTriggered); return true; } @@ -1432,7 +1436,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kLineBoundary, kUserTriggered); return true; } @@ -1441,8 +1445,9 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, - TextGranularity::kLineBoundary, kUserTriggered); + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kLineBoundary, + kUserTriggered); return true; } @@ -1450,7 +1455,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kParagraphBoundary, kUserTriggered); return true; } @@ -1459,7 +1464,8 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kParagraphBoundary, kUserTriggered); return true; } @@ -1468,7 +1474,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kParagraph, kUserTriggered); return true; } @@ -1477,7 +1483,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kParagraph, kUserTriggered); return true; @@ -1487,7 +1493,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kParagraph, kUserTriggered); return true; } @@ -1496,8 +1502,9 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, - TextGranularity::kParagraph, kUserTriggered); + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kParagraph, + kUserTriggered); return true; } @@ -1505,7 +1512,7 @@ Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify(FrameSelection::kAlterationMove, + return frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kLine, kUserTriggered); } @@ -1514,7 +1521,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kLine, kUserTriggered); return true; @@ -1524,7 +1531,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionBackward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionBackward, TextGranularity::kWord, kUserTriggered); return true; } @@ -1533,7 +1540,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kWord, kUserTriggered); return true; @@ -1543,7 +1550,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionForward, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionForward, TextGranularity::kWord, kUserTriggered); return true; } @@ -1552,8 +1559,9 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward, - TextGranularity::kWord, kUserTriggered); + frame.Selection().Modify(SelectionModifyAlteration::kExtend, + kDirectionForward, TextGranularity::kWord, + kUserTriggered); return true; } @@ -1561,7 +1569,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionLeft, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionLeft, TextGranularity::kWord, kUserTriggered); return true; } @@ -1570,7 +1578,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionLeft, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionLeft, TextGranularity::kWord, kUserTriggered); return true; } @@ -1579,7 +1587,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionRight, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionRight, TextGranularity::kWord, kUserTriggered); return true; } @@ -1588,7 +1596,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionRight, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionRight, TextGranularity::kWord, kUserTriggered); return true; } @@ -1597,7 +1605,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionLeft, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionLeft, TextGranularity::kLineBoundary, kUserTriggered); return true; } @@ -1606,7 +1614,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionLeft, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionLeft, TextGranularity::kLineBoundary, kUserTriggered); return true; } @@ -1615,7 +1623,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationMove, kDirectionRight, + frame.Selection().Modify(SelectionModifyAlteration::kMove, kDirectionRight, TextGranularity::kLineBoundary, kUserTriggered); return true; } @@ -1624,7 +1632,7 @@ Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(FrameSelection::kAlterationExtend, kDirectionRight, + frame.Selection().Modify(SelectionModifyAlteration::kExtend, kDirectionRight, TextGranularity::kLineBoundary, kUserTriggered); return true; }
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp index 682a212..302342f 100644 --- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -743,11 +743,11 @@ GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); SelectionModifier selection_modifier(*frame, EndingSelection()); - selection_modifier.Modify(FrameSelection::kAlterationExtend, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, granularity); if (kill_ring && selection_modifier.Selection().IsCaret() && granularity != TextGranularity::kCharacter) { - selection_modifier.Modify(FrameSelection::kAlterationExtend, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, TextGranularity::kCharacter); } @@ -802,7 +802,7 @@ return; // Extend the selection backward into the last cell, then deletion will // handle the move. - selection_modifier.Modify(FrameSelection::kAlterationExtend, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, kDirectionBackward, granularity); // If the caret is just after a table, select the table and don't delete // anything. @@ -915,11 +915,11 @@ // Do nothing in the case that the caret is at the start of a // root editable element or at the start of a document. SelectionModifier selection_modifier(*frame, EndingSelection()); - selection_modifier.Modify(FrameSelection::kAlterationExtend, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, kDirectionForward, granularity); if (kill_ring && selection_modifier.Selection().IsCaret() && granularity != TextGranularity::kCharacter) { - selection_modifier.Modify(FrameSelection::kAlterationExtend, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, kDirectionForward, TextGranularity::kCharacter); } @@ -958,7 +958,7 @@ if (granularity == TextGranularity::kParagraphBoundary && selection_modifier.Selection().IsCaret() && IsEndOfParagraph(selection_modifier.Selection().VisibleEnd())) { - selection_modifier.Modify(FrameSelection::kAlterationExtend, + selection_modifier.Modify(SelectionModifyAlteration::kExtend, kDirectionForward, TextGranularity::kCharacter); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp index d2c9b162..337dbbb7 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -827,7 +827,11 @@ name = frame->DeprecatedLocalOwner()->getAttribute(HTMLNames::idAttr); frame_object->setName(name); } - + if (frame->GetDocument() && frame->GetDocument()->Loader() && + !frame->GetDocument()->Loader()->UnreachableURL().IsEmpty()) { + frame_object->setUnreachableUrl( + frame->GetDocument()->Loader()->UnreachableURL().GetString()); + } return frame_object; }
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 8732e5e..fe4cbbb 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -91,8 +91,9 @@ { "name": "name", "type": "string", "optional": true, "description": "Frame's name as specified in the tag." }, { "name": "url", "type": "string", "description": "Frame document's URL." }, { "name": "securityOrigin", "type": "string", "description": "Frame document's security origin." }, - { "name": "mimeType", "type": "string", "description": "Frame document's mimeType as determined by the browser." } - ] + { "name": "mimeType", "type": "string", "description": "Frame document's mimeType as determined by the browser." }, + { "name": "unreachableUrl", "type": "string", "optional": "true", "experimental": "true", "description": "If the frame failed to load, this contains the URL that could not be loaded." } + ] }, { "id": "FrameResource", @@ -488,7 +489,8 @@ {"name": "marginBottom", "type": "number", "optional": true, "description": "Bottom margin in inches. Defaults to 1cm (~0.4 inches)."}, {"name": "marginLeft", "type": "number", "optional": true, "description": "Left margin in inches. Defaults to 1cm (~0.4 inches)."}, {"name": "marginRight", "type": "number", "optional": true, "description": "Right margin in inches. Defaults to 1cm (~0.4 inches)."}, - {"name": "pageRanges", "type": "string", "optional": true, "description": "Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages."} + {"name": "pageRanges", "type": "string", "optional": true, "description": "Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages."}, + {"name": "ignoreInvalidPageRanges", "type": "boolean", "optional": true, "description": "Whether to silently ignore invalid but successfully parsed page ranges, such as '3-2'. Defaults to false."} ], "returns": [ { "name": "data", "type": "string", "description": "Base64-encoded pdf data." }
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 index 48cbc12..6593488 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -793,10 +793,6 @@ status: "experimental", }, { - name: "PaymentDetailsError", - status: "stable", - }, - { name: "PaymentDetailsModifierData", status: "experimental", },
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index 3f18b26..148b260 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -16,7 +16,6 @@ deps = [ "//skia", - "//third_party/WebKit/Source/controller", "//third_party/WebKit/Source/core", "//third_party/WebKit/Source/modules", "//third_party/WebKit/Source/platform",
diff --git a/third_party/WebKit/Source/web/WebKit.cpp b/third_party/WebKit/Source/web/WebKit.cpp index 169c52447..54d56cd0 100644 --- a/third_party/WebKit/Source/web/WebKit.cpp +++ b/third_party/WebKit/Source/web/WebKit.cpp
@@ -34,7 +34,6 @@ #include "bindings/core/v8/V8BindingForCore.h" #include "bindings/core/v8/V8GCController.h" -#include "controller/BlinkInitializer.h" #include "core/layout/LayoutTheme.h" #include "core/page/Page.h" #include "core/workers/WorkerBackingThread.h" @@ -47,16 +46,9 @@ #include "platform/wtf/allocator/Partitions.h" #include "platform/wtf/text/AtomicString.h" #include "platform/wtf/text/TextEncoding.h" -#include "web/WebFactoryImpl.h" namespace blink { -void Initialize(Platform* platform) { - InitializeBlink(platform); - - WebFactoryImpl::Initialize(); -} - v8::Isolate* MainThreadIsolate() { return V8PerIsolateData::MainThreadIsolate(); }
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 399550d..65a999e1 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -851,6 +851,11 @@ args.force_local_build): AddSvnToPathOnWin() + if use_head_revision: + # TODO(hans): Trunk was updated; remove after the next roll. + global VERSION + VERSION = '6.0.0' + global CLANG_REVISION, PACKAGE_VERSION if args.print_revision: if use_head_revision or args.llvm_force_head_revision:
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3a75eab..0af1396 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -97038,6 +97038,12 @@ label="Recorded 10 minutes after backgrounded."/> <suffix name="AfterBackgrounded.15min" label="Recorded 15 minutes after backgrounded."/> + <suffix name="PeakDuringLoad" + label="Polled each time CreateURLLoader is called, and the maximum + value is recorded when DidFinishLoad is called."/> + <suffix name="MainFrame.PeakDuringLoad" + label="In the main frame, polled each time CreateURLLoader is called, + and the maximum value is recorded when DidFinishLoad is called."/> <affected-histogram name="Memory.Experimental.Renderer.BlinkGC"/> <affected-histogram name="Memory.Experimental.Renderer.Discardable"/> <affected-histogram name="Memory.Experimental.Renderer.Malloc"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index f803add1..2204b5b 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -463,6 +463,24 @@ </metric> </event> +<event name="Media.Engagement.SessionFinished"> + <owner>beccahughes@chromium.org</owner> + <owner>media-dev@chromium.org</owner> + <summary> + The Media Engagement index stores the number of significant media playbacks + per origin and the number of visits. From that we calculate a Media + Engagement Score. + + To tweak the scoring function we are logging the total number of significant + media playbacks, the total number of visits, the calculated engagement score + and the new number of significant media playbacks that occured this visit. + </summary> + <metric name="Engagement.Score"/> + <metric name="Playbacks.Delta"/> + <metric name="Playbacks.Total"/> + <metric name="Visits.Total"/> +</event> + <event name="Media.WatchTime"> <owner>dalecurtis@chromium.org</owner> <summary>
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc index b5eb3546..d867d75e 100644 --- a/ui/keyboard/keyboard_controller_unittest.cc +++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "testing/gtest/include/gtest/gtest.h"