diff --git a/DEPS b/DEPS index 296d6a7..b96737a 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'aeef5610d7a3fe4a53fc27b20486da79bf7a949a', + 'skia_revision': '7adde145d3913cfd67b90bf83a9ea54386a285a7', # 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': 'ad889a602199a98d5f2605c6cb346071199df55f', + 'v8_revision': '5d22cf824391a2049c91e15bad9488a4ce57321a', # 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. @@ -52,7 +52,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'b4533de1fdf7f5ac2fb4824582e13cb55ca94dd8', + 'angle_revision': '6a6b09c9b62b003ca96b036d0249db5ce99cc269', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '4bd198f6a85c700acbbd23c0b666c846636526d2', + 'catapult_revision': 'e6b04fef1997055d90390256fe96282bbbd98a51', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/base/metrics/histogram_macros.h b/base/metrics/histogram_macros.h index 9e3caec..7847376 100644 --- a/base/metrics/histogram_macros.h +++ b/base/metrics/histogram_macros.h
@@ -256,6 +256,39 @@ INTERNAL_HISTOGRAM_SPARSE_SLOWLY(name, sample) //------------------------------------------------------------------------------ +// Histogram instantiation helpers. + +// Support a collection of histograms, perhaps one for each entry in an +// enumeration. This macro manages a block of pointers, adding to a specific +// one by its index. +// +// A typical instantiation looks something like this: +// STATIC_HISTOGRAM_POINTER_GROUP( +// GetHistogramNameForIndex(histogram_index), +// histogram_index, MAXIMUM_HISTOGRAM_INDEX, Add(some_delta), +// base::Histogram::FactoryGet( +// GetHistogramNameForIndex(histogram_index), +// MINIMUM_SAMPLE, MAXIMUM_SAMPLE, BUCKET_COUNT, +// base::HistogramBase::kUmaTargetedHistogramFlag)); +// +// Though it seems inefficient to generate the name twice, the first +// instance will be used only for DCHECK builds and the second will +// execute only during the first access to the given index, after which +// the pointer is cached and the name never needed again. +#define STATIC_HISTOGRAM_POINTER_GROUP(constant_histogram_name, index, \ + constant_maximum, \ + histogram_add_method_invocation, \ + histogram_factory_get_invocation) \ + do { \ + static base::subtle::AtomicWord atomic_histograms[constant_maximum]; \ + DCHECK_LE(0, index); \ + DCHECK_LT(index, constant_maximum); \ + HISTOGRAM_POINTER_USE(&atomic_histograms[index], constant_histogram_name, \ + histogram_add_method_invocation, \ + histogram_factory_get_invocation); \ + } while (0) + +//------------------------------------------------------------------------------ // Deprecated histogram macros. Not recommended for current use. // Legacy name for UMA_HISTOGRAM_COUNTS_1M. Suggest using explicit naming
diff --git a/base/task_scheduler/task_traits.h b/base/task_scheduler/task_traits.h index 6f6ab09..8354650 100644 --- a/base/task_scheduler/task_traits.h +++ b/base/task_scheduler/task_traits.h
@@ -141,10 +141,6 @@ // Returns true if tasks with these traits may use base/ sync primitives. bool with_base_sync_primitives() const { return with_base_sync_primitives_; } - // DEPRECATED - // TODO(fdoray): Remove this as part of crbug.com/675660 - bool with_file_io() const { return may_block(); } - // Returns the priority of tasks with these traits. TaskPriority priority() const { return priority_; }
diff --git a/base/third_party/symbolize/symbolize.cc b/base/third_party/symbolize/symbolize.cc index d767895..0932e64a 100644 --- a/base/third_party/symbolize/symbolize.cc +++ b/base/third_party/symbolize/symbolize.cc
@@ -56,6 +56,7 @@ #if defined(HAVE_SYMBOLIZE) +#include <algorithm> #include <limits> #include "symbolize.h" @@ -296,10 +297,12 @@ // Read at most NUM_SYMBOLS symbols at once to save read() calls. ElfW(Sym) buf[NUM_SYMBOLS]; - const ssize_t len = ReadFromOffset(fd, &buf, sizeof(buf), offset); + int num_symbols_to_read = std::min(NUM_SYMBOLS, num_symbols - i); + const ssize_t len = + ReadFromOffset(fd, &buf, sizeof(buf[0]) * num_symbols_to_read, offset); SAFE_ASSERT(len % sizeof(buf[0]) == 0); const ssize_t num_symbols_in_buf = len / sizeof(buf[0]); - SAFE_ASSERT(num_symbols_in_buf <= sizeof(buf)/sizeof(buf[0])); + SAFE_ASSERT(num_symbols_in_buf <= num_symbols_to_read); for (int j = 0; j < num_symbols_in_buf; ++j) { const ElfW(Sym)& symbol = buf[j]; uint64_t start_address = symbol.st_value;
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index be917fd..8f3beb1 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -52,6 +52,9 @@ } namespace mojo { class SyncCallRestrictions; +namespace edk { +class ScopedIPCSupport; +} } namespace ui { class CommandBufferClientImpl; @@ -193,6 +196,7 @@ friend class PlatformThread; friend class android::JavaHandlerThread; friend class mojo::SyncCallRestrictions; + friend class mojo::edk::ScopedIPCSupport; friend class ui::CommandBufferClientImpl; friend class ui::CommandBufferLocal; friend class ui::GpuState;
diff --git a/blimp/engine/app/blimp_engine_crash_keys.cc b/blimp/engine/app/blimp_engine_crash_keys.cc index 848521c3..dd2a258 100644 --- a/blimp/engine/app/blimp_engine_crash_keys.cc +++ b/blimp/engine/app/blimp_engine_crash_keys.cc
@@ -103,6 +103,8 @@ // Temporary for https://crbug.com/668633. { "swdh_set_hosted_version_worker_pid", crash_keys::kSmallSize }, { "swdh_set_hosted_version_host_pid", crash_keys::kSmallSize }, + { "swdh_set_hosted_version_is_new_process", crash_keys::kSmallSize }, + { "swdh_set_hosted_version_restart_count", crash_keys::kSmallSize }, }; return base::debug::InitCrashKeys(engine_keys, arraysize(engine_keys),
diff --git a/build/config/ios/BUILD.gn b/build/config/ios/BUILD.gn index 0dda3e5..ec6b9e6 100644 --- a/build/config/ios/BUILD.gn +++ b/build/config/ios/BUILD.gn
@@ -6,6 +6,23 @@ import("//build/config/sysroot.gni") import("//build/toolchain/toolchain.gni") +declare_args() { + # Enabling this option makes clang compile to an intermediate + # representation ("bitcode"), and not to native code. This is preferred + # when including WebRTC in the apps that will be sent to Apple's App Store + # and mandatory for the apps that run on watchOS or tvOS. + # The option only works when building with Xcode (use_xcode_clang = true). + # Mimicking how Xcode handles it, the production builds (is_debug = false) + # get real bitcode sections added, while the debug builds (is_debug = true) + # only get bitcode-section "markers" added in them. + # NOTE: This option is ignored when building versions for the iOS simulator, + # where a part of libvpx is compiled from the assembly code written using + # Intel assembly syntax; Yasm / Nasm do not support emitting bitcode parts. + # That is not a limitation for now as Xcode mandates the presence of bitcode + # only when building bitcode-enabled projects for real devices (ARM CPUs). + enable_ios_bitcode = false +} + # This is included by reference in the //build/config/compiler:runtime_library # config that is applied to all targets. It is here to separate out the logic # that is iOS-only. Please see that target for advice on what should go in @@ -24,6 +41,14 @@ common_flags += [ "-miphoneos-version-min=$ios_deployment_target" ] } + if (use_xcode_clang && enable_ios_bitcode && !use_ios_simulator) { + if (is_debug) { + common_flags += [ "-fembed-bitcode-marker" ] + } else { + common_flags += [ "-fembed-bitcode" ] + } + } + asmflags = common_flags cflags = common_flags ldflags = common_flags
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 2ebac33..2b0d2c5 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -870,6 +870,10 @@ </intent-filter> </receiver> + <receiver android:name="org.chromium.chrome.browser.ntp.ContentSuggestionsNotificationHelper$OpenUrlReceiver" + android:exported="false"/> + <receiver android:name="org.chromium.chrome.browser.ntp.ContentSuggestionsNotificationHelper$DeleteReceiver" + android:exported="false"/> <receiver android:name="org.chromium.chrome.browser.ntp.ContentSuggestionsNotificationHelper$TimeoutReceiver" android:exported="false"/>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java index 337a3a9..a149fca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
@@ -11,6 +11,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; @@ -20,6 +21,8 @@ import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.library_loader.LibraryLoader; import org.chromium.chrome.R; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.ShortcutHelper; @@ -30,13 +33,42 @@ * * Exposes helper functions to native C++ code. */ +@JNINamespace("ntp_snippets") public class ContentSuggestionsNotificationHelper { private static final String NOTIFICATION_TAG = "ContentSuggestionsNotification"; private static final String NOTIFICATION_ID_EXTRA = "notification_id"; + private static final String PREF_CACHED_ACTION_TAP = + "ntp.content_suggestions.notification.cached_action_tap"; + private static final String PREF_CACHED_ACTION_DISMISSAL = + "ntp.content_suggestions.notification.cached_action_dismissal"; + private static final String PREF_CACHED_ACTION_HIDE_DEADLINE = + "ntp.content_suggestions.notification.cached_action_hide_deadline"; + private static final String PREF_CACHED_CONSECUTIVE_IGNORED = + "ntp.content_suggestions.notification.cached_consecutive_ignored"; + private ContentSuggestionsNotificationHelper() {} // Prevent instantiation /** + * Opens the content suggestion when notification is tapped. + */ + public static final class OpenUrlReceiver extends BroadcastReceiver { + public void onReceive(Context context, Intent intent) { + openUrl(intent.getData()); + recordCachedActionMetric(PREF_CACHED_ACTION_TAP); + } + } + + /** + * Records dismissal when notification is swiped away. + */ + public static final class DeleteReceiver extends BroadcastReceiver { + public void onReceive(Context context, Intent intent) { + recordCachedActionMetric(PREF_CACHED_ACTION_DISMISSAL); + } + } + + /** * Removes the notification after a timeout period. */ public static final class TimeoutReceiver extends BroadcastReceiver { @@ -44,19 +76,19 @@ int id = intent.getIntExtra(NOTIFICATION_ID_EXTRA, -1); if (id < 0) return; hideNotification(id); + recordCachedActionMetric(PREF_CACHED_ACTION_HIDE_DEADLINE); } } - @CalledByNative - private static void openUrl(String url) { + private static void openUrl(Uri uri) { Context context = ContextUtils.getApplicationContext(); - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - intent.setClass(context, ChromeLauncherActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); - intent.putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); + Intent intent = new Intent() + .setAction(Intent.ACTION_VIEW) + .setData(uri) + .setClass(context, ChromeLauncherActivity.class) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()) + .putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true); IntentHandler.addTrustedIntentExtras(intent); context.startActivity(intent); } @@ -81,16 +113,13 @@ } } - Intent intent = new Intent() - .setAction(Intent.ACTION_VIEW) - .setData(Uri.parse(url)) - .setClass(context, ChromeLauncherActivity.class) - .putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true) - .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); + Intent contentIntent = new Intent(context, OpenUrlReceiver.class).setData(Uri.parse(url)); + Intent deleteIntent = new Intent(context, DeleteReceiver.class).setData(Uri.parse(url)); NotificationCompat.Builder builder = new NotificationCompat.Builder(context) .setAutoCancel(true) - .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0)) + .setContentIntent(PendingIntent.getBroadcast(context, 0, contentIntent, 0)) + .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0)) .setContentTitle(title) .setContentText(text) .setGroup(NOTIFICATION_TAG) @@ -134,4 +163,65 @@ manager.cancel(NOTIFICATION_TAG, 0); } } + + /** + * Records that an action was performed on a notification. + * + * Also tracks the number of consecutively-ignored notifications, resetting it on a tap or + * otherwise incrementing it. + * + * This method may be called when the native library is not loaded. If it is loaded, the metrics + * will immediately be sent to C++. If not, it will cache them for a later call to + * flushCachedMetrics(). + * + * @param prefName The name of the action metric pref to update (<tt>PREF_CACHED_ACTION_*</tt>) + */ + private static void recordCachedActionMetric(String prefName) { + assert prefName.startsWith("ntp.content_suggestions.notification.cached_action_"); + + SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); + int currentValue = prefs.getInt(prefName, 0); + int consecutiveIgnored = 0; + if (!prefName.equals(PREF_CACHED_ACTION_TAP)) { + consecutiveIgnored = 1 + prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0); + } + prefs.edit() + .putInt(prefName, currentValue + 1) + .putInt(PREF_CACHED_CONSECUTIVE_IGNORED, consecutiveIgnored) + .apply(); + + if (LibraryLoader.isInitialized()) { + flushCachedMetrics(); + } + } + + /** + * Invokes nativeReceiveFlushedMetrics() with cached metrics and resets them. + * + * It may be called from either native or Java code, as long as the native libray is loaded. + */ + @CalledByNative + private static void flushCachedMetrics() { + assert LibraryLoader.isInitialized(); + + SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); + int tapCount = prefs.getInt(PREF_CACHED_ACTION_TAP, 0); + int dismissalCount = prefs.getInt(PREF_CACHED_ACTION_DISMISSAL, 0); + int hideDeadlineCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_DEADLINE, 0); + int consecutiveIgnored = prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0); + + if (tapCount > 0 || dismissalCount > 0 || hideDeadlineCount > 0) { + nativeReceiveFlushedMetrics(tapCount, dismissalCount, hideDeadlineCount, + consecutiveIgnored); + prefs.edit() + .remove(PREF_CACHED_ACTION_TAP) + .remove(PREF_CACHED_ACTION_DISMISSAL) + .remove(PREF_CACHED_ACTION_HIDE_DEADLINE) + .remove(PREF_CACHED_CONSECUTIVE_IGNORED) + .apply(); + } + } + + private static native void nativeReceiveFlushedMetrics( + int tapCount, int dismissalCount, int hideDeadlineCount, int consecutiveIgnored); }
diff --git a/chrome/app/chrome_crash_reporter_client_win.cc b/chrome/app/chrome_crash_reporter_client_win.cc index b658c7e..b13781d9 100644 --- a/chrome/app/chrome_crash_reporter_client_win.cc +++ b/chrome/app/chrome_crash_reporter_client_win.cc
@@ -197,6 +197,8 @@ // Temporary for https://crbug.com/668633. {"swdh_set_hosted_version_worker_pid", crash_keys::kSmallSize}, {"swdh_set_hosted_version_host_pid", crash_keys::kSmallSize}, + {"swdh_set_hosted_version_is_new_process", crash_keys::kSmallSize}, + {"swdh_set_hosted_version_restart_count", crash_keys::kSmallSize}, }; // This dynamic set of keys is used for sets of key value pairs when gathering
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 0c5824d8..80d4e578 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -7576,7 +7576,7 @@ Passwords </message> <message name="IDS_PASSWORDS_AUTO_SIGNIN_TITLE" desc="Title for 'Auto sign-in' checkbox in the password dialog"> - Auto Sign-in + Auto sign-in </message> <message name="IDS_PASSWORDS_AUTO_SIGNIN_DESCRIPTION" desc="Text under 'Auto sign-in' checkbox"> Automatically sign in to websites using stored credentials. When the feature is disabled, you will be asked for confirmation every time before signing in to a website.
diff --git a/chrome/app_shim/chrome_main_app_mode_mac.mm b/chrome/app_shim/chrome_main_app_mode_mac.mm index 9d2b483..33be302 100644 --- a/chrome/app_shim/chrome_main_app_mode_mac.mm +++ b/chrome/app_shim/chrome_main_app_mode_mac.mm
@@ -641,7 +641,9 @@ g_io_thread = io_thread; mojo::edk::Init(); - mojo::edk::ScopedIPCSupport ipc_support(io_thread->task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + io_thread->task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); // Find already running instances of Chrome. pid_t pid = -1;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 25118bc..b847498 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -746,6 +746,8 @@ "ntp_snippets/download_suggestions_provider.h", "ntp_snippets/ntp_snippets_features.cc", "ntp_snippets/ntp_snippets_features.h", + "ntp_snippets/ntp_snippets_metrics.cc", + "ntp_snippets/ntp_snippets_metrics.h", "ntp_tiles/chrome_most_visited_sites_factory.cc", "ntp_tiles/chrome_most_visited_sites_factory.h", "ntp_tiles/chrome_popular_sites_factory.cc",
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 8a18442..d09a583 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -63,6 +63,7 @@ #include "chrome/browser/android/metrics/uma_utils.h" #include "chrome/browser/android/metrics/variations_session.h" #include "chrome/browser/android/net/external_estimate_provider_android.h" +#include "chrome/browser/android/ntp/content_suggestions_notification_helper.h" #include "chrome/browser/android/ntp/most_visited_sites_bridge.h" #include "chrome/browser/android/ntp/ntp_snippets_bridge.h" #include "chrome/browser/android/ntp/recent_tabs_page_prefs.h" @@ -260,6 +261,8 @@ ConnectionInfoPopupAndroid::RegisterConnectionInfoPopupAndroid}, {"SecurityStateModel", RegisterSecurityStateModelAndroid}, {"ConnectivityChecker", chrome::android::RegisterConnectivityChecker}, + {"ContentSuggestionsNotificationHelper", + ntp_snippets::ContentSuggestionsNotificationHelper::Register}, {"ContextMenuHelper", RegisterContextMenuHelper}, {"ContextualSearchManager", RegisterContextualSearchManager}, {"ContextualSearchSceneLayer", RegisterContextualSearchSceneLayer},
diff --git a/chrome/browser/android/ntp/content_suggestions_notification_helper.cc b/chrome/browser/android/ntp/content_suggestions_notification_helper.cc index db5abdd3..ccfdc9e 100644 --- a/chrome/browser/android/ntp/content_suggestions_notification_helper.cc +++ b/chrome/browser/android/ntp/content_suggestions_notification_helper.cc
@@ -8,20 +8,39 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ntp_snippets/ntp_snippets_features.h" +#include "chrome/browser/ntp_snippets/ntp_snippets_metrics.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_service.h" +#include "components/variations/variations_associated_data.h" #include "jni/ContentSuggestionsNotificationHelper_jni.h" #include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" +using base::android::JavaParamRef; + namespace ntp_snippets { -void ContentSuggestionsNotificationHelper::OpenURL(const GURL& url) { - JNIEnv* env = base::android::AttachCurrentThread(); - Java_ContentSuggestionsNotificationHelper_openUrl( - env, base::android::ConvertUTF8ToJavaString(env, url.spec())); +namespace { + +bool IsDisabledForProfile(Profile* profile) { + PrefService* prefs = profile->GetPrefs(); + int current = + prefs->GetInteger(prefs::kContentSuggestionsConsecutiveIgnoredPrefName); + int limit = variations::GetVariationParamByFeatureAsInt( + kContentSuggestionsNotificationsFeature, + kContentSuggestionsNotificationsIgnoredLimitParam, + kContentSuggestionsNotificationsIgnoredDefaultLimit); + return current >= limit; } +} // namespace + void ContentSuggestionsNotificationHelper::SendNotification( const GURL& url, const base::string16& title, @@ -50,4 +69,59 @@ Java_ContentSuggestionsNotificationHelper_hideAllNotifications(env); } +void ContentSuggestionsNotificationHelper::FlushCachedMetrics() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_ContentSuggestionsNotificationHelper_flushCachedMetrics(env); +} + +bool ContentSuggestionsNotificationHelper::IsDisabledForProfile( + Profile* profile) { + return ntp_snippets::IsDisabledForProfile(profile); +} + +// static +bool ContentSuggestionsNotificationHelper::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +static void ReceiveFlushedMetrics(JNIEnv* env, + const JavaParamRef<jclass>& class_object, + jint tap_count, + jint dismissal_count, + jint hide_deadline_count, + jint consecutive_ignored) { + DVLOG(1) << "Flushing metrics: tap_count=" << tap_count + << "; dismissal_count=" << dismissal_count + << "; hide_deadline_count=" << hide_deadline_count + << "; consecutive_ignored=" << consecutive_ignored; + Profile* profile = ProfileManager::GetLastUsedProfile()->GetOriginalProfile(); + PrefService* prefs = profile->GetPrefs(); + + for (int i = 0; i < tap_count; ++i) { + RecordContentSuggestionsNotificationAction(CONTENT_SUGGESTIONS_TAP); + } + for (int i = 0; i < dismissal_count; ++i) { + RecordContentSuggestionsNotificationAction(CONTENT_SUGGESTIONS_DISMISSAL); + } + for (int i = 0; i < hide_deadline_count; ++i) { + RecordContentSuggestionsNotificationAction( + CONTENT_SUGGESTIONS_HIDE_DEADLINE); + } + + const bool was_disabled = IsDisabledForProfile(profile); + if (tap_count == 0) { + // There were no taps, consecutive_ignored has not been reset and continues + // from where it left off. If there was a tap, then Java has provided us + // with the number of ignored notifications since that point. + consecutive_ignored += + prefs->GetInteger(prefs::kContentSuggestionsConsecutiveIgnoredPrefName); + } + prefs->SetInteger(prefs::kContentSuggestionsConsecutiveIgnoredPrefName, + consecutive_ignored); + const bool is_disabled = IsDisabledForProfile(profile); + if (!was_disabled && is_disabled) { + RecordContentSuggestionsNotificationOptOut(CONTENT_SUGGESTIONS_IMPLICIT); + } +} + } // namespace ntp_snippets
diff --git a/chrome/browser/android/ntp/content_suggestions_notification_helper.h b/chrome/browser/android/ntp/content_suggestions_notification_helper.h index e9c7d93c..05f54b1e 100644 --- a/chrome/browser/android/ntp/content_suggestions_notification_helper.h +++ b/chrome/browser/android/ntp/content_suggestions_notification_helper.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_ANDROID_NTP_CONTENT_SUGGESTIONS_NOTIFICATION_HELPER_H_ #define CHROME_BROWSER_ANDROID_NTP_CONTENT_SUGGESTIONS_NOTIFICATION_HELPER_H_ +#include <jni.h> #include <string> #include "base/macros.h" @@ -12,6 +13,8 @@ #include "base/time/time.h" #include "url/gurl.h" +class Profile; + namespace gfx { class Image; } // namespace gfx @@ -20,7 +23,6 @@ class ContentSuggestionsNotificationHelper { public: - static void OpenURL(const GURL& url); static void SendNotification(const GURL& url, const base::string16& title, const base::string16& text, @@ -28,6 +30,22 @@ base::Time timeout_at); static void HideAllNotifications(); + // Moves metrics tracked in Java into native histograms. Should be called when + // the native library starts up, to capture any actions that were taken since + // the last time it was running. (Harmless to call more often, though) + // + // Also updates the "consecutive ignored" preference, which is computed from + // the actions taken on notifications, and maybe the "opt outs" metric, which + // is computed in turn from that. + static void FlushCachedMetrics(); + + // True if the user has ignored enough notifications that we no longer think + // that the user is interested in them. + static bool IsDisabledForProfile(Profile* profile); + + // Registers JNI methods. + static bool Register(JNIEnv* env); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(ContentSuggestionsNotificationHelper); };
diff --git a/chrome/browser/android/ntp/content_suggestions_notifier_service.cc b/chrome/browser/android/ntp/content_suggestions_notifier_service.cc index cb7bfab..56a6bb5 100644 --- a/chrome/browser/android/ntp/content_suggestions_notifier_service.cc +++ b/chrome/browser/android/ntp/content_suggestions_notifier_service.cc
@@ -12,7 +12,9 @@ #include "chrome/browser/notifications/notification.h" #include "chrome/browser/notifications/notification_handler.h" #include "chrome/browser/ntp_snippets/ntp_snippets_features.h" +#include "chrome/browser/ntp_snippets/ntp_snippets_metrics.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" #include "components/ntp_snippets/content_suggestions_service.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" @@ -68,13 +70,16 @@ Profile* profile, PrefService* prefs) : service_(service), + profile_(profile), prefs_(prefs), app_status_listener_(base::Bind(&NotifyingObserver::AppStatusChanged, base::Unretained(this))), weak_ptr_factory_(this) {} void OnNewSuggestions(Category category) override { - if (!ShouldNotifyInState(app_status_listener_.GetState())) { + if (!ShouldNotifyInState(app_status_listener_.GetState()) || + ContentSuggestionsNotificationHelper::IsDisabledForProfile(profile_)) { + DVLOG(1) << "notification suppressed"; return; } const ContentSuggestion* suggestion = GetSuggestionToNotifyAbout(category); @@ -108,25 +113,33 @@ case CategoryStatus::NOT_PROVIDED: case CategoryStatus::SIGNED_OUT: ContentSuggestionsNotificationHelper::HideAllNotifications(); + RecordContentSuggestionsNotificationAction( + CONTENT_SUGGESTIONS_HIDE_DISABLED); break; } } void OnSuggestionInvalidated( const ContentSuggestion::ID& suggestion_id) override { + // TODO(sfiera): handle concurrent notifications and non-articles properly. if (suggestion_id.category().IsKnownCategory(KnownCategories::ARTICLES) && (suggestion_id.id_within_category() == prefs_->GetString(kNotificationIDWithinCategory))) { ContentSuggestionsNotificationHelper::HideAllNotifications(); + RecordContentSuggestionsNotificationAction( + CONTENT_SUGGESTIONS_HIDE_EXPIRY); } } void OnFullRefreshRequired() override { ContentSuggestionsNotificationHelper::HideAllNotifications(); + RecordContentSuggestionsNotificationAction(CONTENT_SUGGESTIONS_HIDE_EXPIRY); } void ContentSuggestionsServiceShutdown() override { ContentSuggestionsNotificationHelper::HideAllNotifications(); + RecordContentSuggestionsNotificationAction( + CONTENT_SUGGESTIONS_HIDE_SHUTDOWN); } private: @@ -154,6 +167,8 @@ void AppStatusChanged(base::android::ApplicationState state) { if (!ShouldNotifyInState(state)) { ContentSuggestionsNotificationHelper::HideAllNotifications(); + RecordContentSuggestionsNotificationAction( + CONTENT_SUGGESTIONS_HIDE_FRONTMOST); } } @@ -172,9 +187,14 @@ prefs_->SetString(kNotificationIDWithinCategory, id.id_within_category()); ContentSuggestionsNotificationHelper::SendNotification( url, title, publisher, CropSquare(image), timeout_at); + RecordContentSuggestionsNotificationImpression( + id.category().IsKnownCategory(KnownCategories::ARTICLES) + ? CONTENT_SUGGESTIONS_ARTICLE + : CONTENT_SUGGESTIONS_NONARTICLE); } ContentSuggestionsService* const service_; + Profile* const profile_; PrefService* const prefs_; base::android::ApplicationStatusListener app_status_listener_; @@ -190,6 +210,7 @@ : observer_(base::MakeUnique<NotifyingObserver>(suggestions, profile, profile->GetPrefs())) { + ContentSuggestionsNotificationHelper::FlushCachedMetrics(); suggestions->AddObserver(observer_.get()); } @@ -199,4 +220,6 @@ void ContentSuggestionsNotifierService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterStringPref(kNotificationIDWithinCategory, std::string()); + registry->RegisterIntegerPref( + prefs::kContentSuggestionsConsecutiveIgnoredPrefName, 0); }
diff --git a/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc index 9cd7a6e..4374579 100644 --- a/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc +++ b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.cc
@@ -12,21 +12,22 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_infobar_delegate.h" -#include "chrome/browser/permissions/permission_manager.h" +#include "chrome/browser/android/search_geolocation/search_geolocation_service.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_types.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" -#include "components/search_engines/template_url.h" -#include "components/search_engines/template_url_service.h" #include "components/variations/variations_associated_data.h" -#include "content/public/browser/permission_type.h" #include "content/public/browser/web_contents.h" #include "jni/GeolocationHeader_jni.h" #include "jni/SearchGeolocationDisclosureTabHelper_jni.h" #include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h" +#include "url/origin.h" namespace { @@ -77,10 +78,69 @@ void SearchGeolocationDisclosureTabHelper::NavigationEntryCommitted( const content::LoadCommittedDetails& load_details) { - if (consistent_geolocation_enabled_) { - MaybeShowDefaultSearchGeolocationDisclosure( - web_contents()->GetVisibleURL()); + if (consistent_geolocation_enabled_) + MaybeShowDisclosure(web_contents()->GetVisibleURL()); +} + +void SearchGeolocationDisclosureTabHelper::MaybeShowDisclosure( + const GURL& gurl) { + if (!ShouldShowDisclosureForUrl(gurl)) + return; + + // Check that the Chrome app has geolocation permission. + JNIEnv* env = base::android::AttachCurrentThread(); + if (!Java_GeolocationHeader_hasGeolocationPermission(env)) + return; + + // Don't show the infobar if the user has dismissed it, or they've seen it + // enough times already. + PrefService* prefs = GetProfile()->GetPrefs(); + bool dismissed_already = + prefs->GetBoolean(prefs::kSearchGeolocationDisclosureDismissed); + int shown_count = + prefs->GetInteger(prefs::kSearchGeolocationDisclosureShownCount); + if (dismissed_already || shown_count >= GetMaxShowCount()) { + // Record metrics for the state of permissions after the disclosure has been + // shown. This is not done immediately after showing the last disclosure + // (i.e. at the end of this function), but on the next omnibox search, to + // allow the metric to capture changes to settings done by the user as a + // result of clicking on the Settings link in the disclosure. + RecordPostDisclosureMetrics(gurl); + return; } + + // Or if it has been shown too recently. + base::Time last_shown = base::Time::FromInternalValue( + prefs->GetInt64(prefs::kSearchGeolocationDisclosureLastShowDate)); + if (GetTimeNow() - last_shown < base::TimeDelta::FromDays(GetDaysPerShow())) { + return; + } + + // Record metrics for the state of permissions before the disclosure has been + // shown. + RecordPreDisclosureMetrics(gurl); + + // Only show the disclosure if the geolocation permission is set ask (i.e. has + // not been explicitly set or revoked). + ContentSetting status = + HostContentSettingsMapFactory::GetForProfile(GetProfile()) + ->GetContentSetting(gurl, gurl, CONTENT_SETTINGS_TYPE_GEOLOCATION, + std::string()); + if (status != CONTENT_SETTING_ASK) + return; + + // And only show disclosure if the DSE geolocation setting is on. + SearchGeolocationService* service = + SearchGeolocationService::Factory::GetForBrowserContext(GetProfile()); + if (!service->GetDSEGeolocationSetting()) + return; + + // All good, let's show the disclosure and increment the shown count. + SearchGeolocationDisclosureInfoBarDelegate::Create(web_contents(), gurl); + shown_count++; + prefs->SetInteger(prefs::kSearchGeolocationDisclosureShownCount, shown_count); + prefs->SetInt64(prefs::kSearchGeolocationDisclosureLastShowDate, + GetTimeNow().ToInternalValue()); } // static @@ -111,89 +171,20 @@ return RegisterNativesImpl(env); } -void SearchGeolocationDisclosureTabHelper:: - MaybeShowDefaultSearchGeolocationDisclosure(const GURL& gurl) { - // Don't show in incognito. - if (GetProfile()->IsOffTheRecord()) - return; - - if (!ShouldShowDisclosureForUrl(gurl)) - return; - - // Don't show the infobar if the user has dismissed it, or they've seen it - // enough times already. - PrefService* prefs = GetProfile()->GetPrefs(); - bool dismissed_already = - prefs->GetBoolean(prefs::kSearchGeolocationDisclosureDismissed); - int shown_count = - prefs->GetInteger(prefs::kSearchGeolocationDisclosureShownCount); - if (dismissed_already || shown_count >= GetMaxShowCount()) { - // Record metrics for the state of permissions after the disclosure has been - // shown. This is not done immediately after showing the last disclosure - // (i.e. at the end of this function), but on the next omnibox search, to - // allow the metric to capture changes to settings done by the user as a - // result of clicking on the Settings link in the disclosure. - RecordPostDisclosureMetrics(gurl); - return; - } - - // Or if it has been shown too recently. - base::Time last_shown = base::Time::FromInternalValue( - prefs->GetInt64(prefs::kSearchGeolocationDisclosureLastShowDate)); - if (GetTimeNow() - last_shown < base::TimeDelta::FromDays(GetDaysPerShow())) { - return; - } - - // Check that the Chrome app has geolocation permission. - JNIEnv* env = base::android::AttachCurrentThread(); - if (!Java_GeolocationHeader_hasGeolocationPermission(env)) - return; - - // Record metrics for the state of permissions before the disclosure has been - // shown. - RecordPreDisclosureMetrics(gurl); - - // Only show the disclosure if the geolocation permission is set to ASK - // (i.e. has not been explicitly set or revoked). - blink::mojom::PermissionStatus status = - PermissionManager::Get(GetProfile()) - ->GetPermissionStatus(content::PermissionType::GEOLOCATION, gurl, - gurl); - if (status != blink::mojom::PermissionStatus::ASK) - return; - - // All good, let's show the disclosure and increment the shown count. - SearchGeolocationDisclosureInfoBarDelegate::Create(web_contents(), gurl); - shown_count++; - prefs->SetInteger(prefs::kSearchGeolocationDisclosureShownCount, shown_count); - prefs->SetInt64(prefs::kSearchGeolocationDisclosureLastShowDate, - GetTimeNow().ToInternalValue()); -} - bool SearchGeolocationDisclosureTabHelper::ShouldShowDisclosureForUrl( const GURL& gurl) { + SearchGeolocationService* service = + SearchGeolocationService::Factory::GetForBrowserContext(GetProfile()); + + // Check the service first, as we don't want to show the infobar even when + // testing if it does not exist. + if (!service) + return false; + if (gIgnoreUrlChecksForTesting) return true; - // Only show the disclosure for default search navigations from the omnibox. - TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(GetProfile()); - bool is_search_url = - template_url_service->IsSearchResultsPageFromDefaultSearchProvider( - gurl); - if (!is_search_url) - return false; - - // Only show the disclosure if Google is the default search engine. - TemplateURL* default_search = - template_url_service->GetDefaultSearchProvider(); - if (!default_search || - !default_search->url_ref().HasGoogleBaseURLs( - template_url_service->search_terms_data())) { - return false; - } - - return true; + return service->UseDSEGeolocationSetting(url::Origin(gurl)); } void SearchGeolocationDisclosureTabHelper::RecordPreDisclosureMetrics( @@ -201,15 +192,15 @@ PrefService* prefs = GetProfile()->GetPrefs(); if (!prefs->GetBoolean( prefs::kSearchGeolocationPreDisclosureMetricsRecorded)) { - blink::mojom::PermissionStatus status = - PermissionManager::Get(GetProfile()) - ->GetPermissionStatus(content::PermissionType::GEOLOCATION, gurl, - gurl); - UMA_HISTOGRAM_ENUMERATION("GeolocationDisclosure.PreDisclosurePermission", - static_cast<base::HistogramBase::Sample>(status), - static_cast<base::HistogramBase::Sample>( - blink::mojom::PermissionStatus::LAST) + - 1); + ContentSetting status = + HostContentSettingsMapFactory::GetForProfile(GetProfile()) + ->GetContentSetting(gurl, gurl, CONTENT_SETTINGS_TYPE_GEOLOCATION, + std::string()); + UMA_HISTOGRAM_ENUMERATION( + "GeolocationDisclosure.PreDisclosureContentSetting", + static_cast<base::HistogramBase::Sample>(status), + static_cast<base::HistogramBase::Sample>(CONTENT_SETTING_NUM_SETTINGS) + + 1); prefs->SetBoolean(prefs::kSearchGeolocationPreDisclosureMetricsRecorded, true); } @@ -220,15 +211,15 @@ PrefService* prefs = GetProfile()->GetPrefs(); if (!prefs->GetBoolean( prefs::kSearchGeolocationPostDisclosureMetricsRecorded)) { - blink::mojom::PermissionStatus status = - PermissionManager::Get(GetProfile()) - ->GetPermissionStatus(content::PermissionType::GEOLOCATION, gurl, - gurl); - UMA_HISTOGRAM_ENUMERATION("GeolocationDisclosure.PostDisclosurePermission", - static_cast<base::HistogramBase::Sample>(status), - static_cast<base::HistogramBase::Sample>( - blink::mojom::PermissionStatus::LAST) + - 1); + ContentSetting status = + HostContentSettingsMapFactory::GetForProfile(GetProfile()) + ->GetContentSetting(gurl, gurl, CONTENT_SETTINGS_TYPE_GEOLOCATION, + std::string()); + UMA_HISTOGRAM_ENUMERATION( + "GeolocationDisclosure.PostDisclosureContentSetting", + static_cast<base::HistogramBase::Sample>(status), + static_cast<base::HistogramBase::Sample>(CONTENT_SETTING_NUM_SETTINGS) + + 1); prefs->SetBoolean(prefs::kSearchGeolocationPostDisclosureMetricsRecorded, true); }
diff --git a/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h index 771e6228f..7b3607f 100644 --- a/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h +++ b/chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h
@@ -30,6 +30,8 @@ void NavigationEntryCommitted( const content::LoadCommittedDetails& load_details) override; + void MaybeShowDisclosure(const GURL& gurl); + static void ResetDisclosure(Profile* profile); static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); @@ -42,8 +44,6 @@ friend class content::WebContentsUserData< SearchGeolocationDisclosureTabHelper>; - void MaybeShowDefaultSearchGeolocationDisclosure(const GURL& gurl); - bool ShouldShowDisclosureForUrl(const GURL& gurl); // Record metrics, once per client, of the permission state before and after
diff --git a/chrome/browser/certificate_manager_model.cc b/chrome/browser/certificate_manager_model.cc index dd86c235..d1b4381 100644 --- a/chrome/browser/certificate_manager_model.cc +++ b/chrome/browser/certificate_manager_model.cc
@@ -212,12 +212,12 @@ return rv; } -int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module, +int CertificateManagerModel::ImportFromPKCS12(PK11SlotInfo* slot_info, const std::string& data, const base::string16& password, bool is_extractable) { - int result = cert_db_->ImportFromPKCS12(module, data, password, - is_extractable, NULL); + int result = cert_db_->ImportFromPKCS12(slot_info, data, + password, is_extractable, NULL); if (result == net::OK) Refresh(); return result;
diff --git a/chrome/browser/certificate_manager_model.h b/chrome/browser/certificate_manager_model.h index 81e65e4..434ad2d 100644 --- a/chrome/browser/certificate_manager_model.h +++ b/chrome/browser/certificate_manager_model.h
@@ -83,9 +83,9 @@ // Import private keys and certificates from PKCS #12 encoded // |data|, using the given |password|. If |is_extractable| is false, - // mark the private key as unextractable from the module. + // mark the private key as unextractable from the slot. // Returns a net error code on failure. - int ImportFromPKCS12(net::CryptoModule* module, const std::string& data, + int ImportFromPKCS12(PK11SlotInfo* slot_info, const std::string& data, const base::string16& password, bool is_extractable); // Import user certificate from DER encoded |data|.
diff --git a/chrome/browser/chromeos/file_manager/zip_file_creator.cc b/chrome/browser/chromeos/file_manager/zip_file_creator.cc index 5a3a2f4..d5d66208 100644 --- a/chrome/browser/chromeos/file_manager/zip_file_creator.cc +++ b/chrome/browser/chromeos/file_manager/zip_file_creator.cc
@@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/message_loop/message_loop.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/task_scheduler/post_task.h" #include "chrome/common/chrome_utility_messages.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" @@ -22,7 +22,7 @@ namespace { // Creates the destination zip file only if it does not already exist. -base::File OpenFileHandleOnBlockingThreadPool(const base::FilePath& zip_path) { +base::File OpenFileHandleAsync(const base::FilePath& zip_path) { return base::File(zip_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); } @@ -45,10 +45,9 @@ void ZipFileCreator::Start() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - base::PostTaskAndReplyWithResult( - BrowserThread::GetBlockingPool(), - FROM_HERE, - base::Bind(&OpenFileHandleOnBlockingThreadPool, dest_file_), + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, base::TaskTraits().MayBlock(), + base::Bind(&OpenFileHandleAsync, dest_file_), base::Bind(&ZipFileCreator::OnOpenFileHandle, this)); }
diff --git a/chrome/browser/chromeos/policy/device_active_directory_policy_manager.cc b/chrome/browser/chromeos/policy/device_active_directory_policy_manager.cc index 57b376d..ecefddc 100644 --- a/chrome/browser/chromeos/policy/device_active_directory_policy_manager.cc +++ b/chrome/browser/chromeos/policy/device_active_directory_policy_manager.cc
@@ -32,6 +32,8 @@ // Does nothing if |store_| hasn't yet initialized. PublishPolicy(); + + RefreshPolicies(); } void DeviceActiveDirectoryPolicyManager::Shutdown() {
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h index 544ff61..ec84452 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h +++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
@@ -31,6 +31,7 @@ // CloudPolicyStore implementation for device policy on Chrome OS. Policy is // stored/loaded via D-Bus to/from session_manager. +// TODO(tnagel): Either drop "Cloud" from the name or refactor. class DeviceCloudPolicyStoreChromeOS : public CloudPolicyStore, public chromeos::DeviceSettingsService::Observer {
diff --git a/chrome/browser/chromeos/policy/user_active_directory_policy_manager.cc b/chrome/browser/chromeos/policy/user_active_directory_policy_manager.cc index 5f5aa8f..273caa1 100644 --- a/chrome/browser/chromeos/policy/user_active_directory_policy_manager.cc +++ b/chrome/browser/chromeos/policy/user_active_directory_policy_manager.cc
@@ -35,6 +35,8 @@ // Does nothing if |store_| hasn't yet initialized. PublishPolicy(); + + RefreshPolicies(); } void UserActiveDirectoryPolicyManager::Shutdown() {
diff --git a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc index 207a807..b426846 100644 --- a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
@@ -204,9 +204,8 @@ // has been a credential error, or if the initial session creation was not // completed (the oauth_token_status is not set to valid by OAuth2LoginManager // until profile creation/session restore is complete). - // TODO(tnagel): Don't limit blocking to cloud managed users. const bool block_forever_for_policy = - !is_active_directory && !user_manager->IsLoggedInAsStub() && + !user_manager->IsLoggedInAsStub() && (user_manager->IsCurrentUserNew() || user_manager->GetActiveUser()->force_online_signin() || user_manager->GetActiveUser()->oauth_token_status() !=
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index f63d065..748fb3e 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -2258,7 +2258,7 @@ : disable_reasons; } - if (FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) { + if (extensions::ExternalInstallManager::IsPromptingEnabled()) { // External extensions are initially disabled. We prompt the user before // enabling them. Hosted apps are excepted because they are not dangerous // (they need to be launched by the user anyway). We also don't prompt for
diff --git a/chrome/browser/extensions/external_install_manager.cc b/chrome/browser/extensions/external_install_manager.cc index 802627a..330b59e 100644 --- a/chrome/browser/extensions/external_install_manager.cc +++ b/chrome/browser/extensions/external_install_manager.cc
@@ -12,12 +12,14 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/external_install_error.h" #include "chrome/browser/profiles/profile.h" +#include "components/version_info/version_info.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_url_handlers.h" @@ -84,6 +86,16 @@ ExternalInstallManager::~ExternalInstallManager() { } + +bool ExternalInstallManager::IsPromptingEnabled() { + // Enable this feature on canary on mac. +#if defined(OS_MACOSX) && defined(GOOGLE_CHROME_BUILD) + return GetCurrentChannel() <= version_info::Channel::CANARY; +#else + return FeatureSwitch::prompt_for_external_extensions()->IsEnabled(); +#endif +} + void ExternalInstallManager::AddExternalInstallError(const Extension* extension, bool is_new_profile) { // Error already exists or has been previously shown. @@ -116,7 +128,7 @@ void ExternalInstallManager::UpdateExternalExtensionAlert() { // If the feature is not enabled do nothing. - if (!FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) + if (!IsPromptingEnabled()) return; // Look for any extensions that were disabled because of being unacknowledged @@ -219,7 +231,7 @@ bool ExternalInstallManager::IsUnacknowledgedExternalExtension( const Extension& extension) const { - if (!FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) + if (!IsPromptingEnabled()) return false; int disable_reasons = extension_prefs_->GetDisableReasons(extension.id());
diff --git a/chrome/browser/extensions/external_install_manager.h b/chrome/browser/extensions/external_install_manager.h index 99c60cb4..0f0b73d 100644 --- a/chrome/browser/extensions/external_install_manager.h +++ b/chrome/browser/extensions/external_install_manager.h
@@ -34,6 +34,9 @@ bool is_first_run); ~ExternalInstallManager() override; + // Returns true if prompting for external extensions is enabled. + static bool IsPromptingEnabled(); + // Removes the error associated with a given extension. void RemoveExternalInstallError(const std::string& extension_id);
diff --git a/chrome/browser/geolocation/OWNERS b/chrome/browser/geolocation/OWNERS index df3450e..59d7e30 100644 --- a/chrome/browser/geolocation/OWNERS +++ b/chrome/browser/geolocation/OWNERS
@@ -1,2 +1,4 @@ +benwells@chromium.org mvanouwerkerk@chromium.org +raymes@chromium.org timvolodine@chromium.org
diff --git a/chrome/browser/geolocation/geolocation_permission_context_android.cc b/chrome/browser/geolocation/geolocation_permission_context_android.cc index 51f1f1b..40c1563 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_android.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_android.cc
@@ -10,12 +10,14 @@ #include "base/bind.h" #include "chrome/browser/android/location_settings.h" #include "chrome/browser/android/location_settings_impl.h" +#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h" #include "chrome/browser/android/search_geolocation/search_geolocation_service.h" #include "chrome/browser/permissions/permission_request_id.h" #include "chrome/browser/permissions/permission_update_infobar_delegate_android.h" #include "chrome/browser/profiles/profile.h" #include "components/infobars/core/infobar.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "url/gurl.h" @@ -104,6 +106,33 @@ GeolocationPermissionContext::CancelPermissionRequest(web_contents, id); } +void GeolocationPermissionContextAndroid::NotifyPermissionSet( + const PermissionRequestID& id, + const GURL& requesting_origin, + const GURL& embedding_origin, + const BrowserPermissionCallback& callback, + bool persist, + ContentSetting content_setting) { + GeolocationPermissionContext::NotifyPermissionSet(id, requesting_origin, + embedding_origin, callback, + persist, content_setting); + + // If this is the default search origin, and the DSE Geolocation setting is + // being used, potentially show the disclosure. + if (requesting_origin == embedding_origin) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID(id.render_process_id(), + id.render_frame_id())); + SearchGeolocationDisclosureTabHelper* disclosure_helper = + SearchGeolocationDisclosureTabHelper::FromWebContents(web_contents); + + // The tab helper can be null in tests. + if (disclosure_helper) + disclosure_helper->MaybeShowDisclosure(requesting_origin); + } +} + void GeolocationPermissionContextAndroid::HandleUpdateAndroidPermissions( const PermissionRequestID& id, const GURL& requesting_frame_origin,
diff --git a/chrome/browser/geolocation/geolocation_permission_context_android.h b/chrome/browser/geolocation/geolocation_permission_context_android.h index b939a09..a739df6 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_android.h +++ b/chrome/browser/geolocation/geolocation_permission_context_android.h
@@ -62,6 +62,12 @@ const BrowserPermissionCallback& callback) override; void CancelPermissionRequest(content::WebContents* web_contents, const PermissionRequestID& id) override; + void NotifyPermissionSet(const PermissionRequestID& id, + const GURL& requesting_origin, + const GURL& embedding_origin, + const BrowserPermissionCallback& callback, + bool persist, + ContentSetting content_setting) override; void HandleUpdateAndroidPermissions(const PermissionRequestID& id, const GURL& requesting_frame_origin,
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc index ea95288..352d037 100644 --- a/chrome/browser/io_thread_unittest.cc +++ b/chrome/browser/io_thread_unittest.cc
@@ -107,7 +107,7 @@ protected: IOThreadTestWithIOThreadObject() : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD | - content::TestBrowserThreadBundle::DONT_START_THREADS) { + content::TestBrowserThreadBundle::DONT_CREATE_THREADS) { #if BUILDFLAG(ENABLE_EXTENSIONS) event_router_forwarder_ = new extensions::EventRouterForwarder; #endif @@ -139,7 +139,7 @@ // Now that IOThread object is registered starting the threads will // call the IOThread::Init(). This sets up the environment needed for // these tests. - thread_bundle_.Start(); + thread_bundle_.CreateThreads(); } ~IOThreadTestWithIOThreadObject() override {
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_features.cc b/chrome/browser/ntp_snippets/ntp_snippets_features.cc index 45b1a386..65b70ba 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_features.cc +++ b/chrome/browser/ntp_snippets/ntp_snippets_features.cc
@@ -9,3 +9,5 @@ const char kContentSuggestionsNotificationsAlwaysNotifyParam[] = "always_notify"; +const char kContentSuggestionsNotificationsIgnoredLimitParam[] = + "ignored_limit";
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_features.h b/chrome/browser/ntp_snippets/ntp_snippets_features.h index 02a33f6a..5e7817c 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_features.h +++ b/chrome/browser/ntp_snippets/ntp_snippets_features.h
@@ -14,4 +14,9 @@ // "true": always send a notification when we receive ARTICLES suggestions extern const char kContentSuggestionsNotificationsAlwaysNotifyParam[]; +// An integer. The number of notifications that can be ignored. If the user +// ignores this many notifications or more, we stop sending them. +extern const char kContentSuggestionsNotificationsIgnoredLimitParam[]; +constexpr int kContentSuggestionsNotificationsIgnoredDefaultLimit = 3; + #endif // CHROME_BROWSER_NTP_SNIPPETS_NTP_SNIPPETS_FEATURES_H_
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_metrics.cc b/chrome/browser/ntp_snippets/ntp_snippets_metrics.cc new file mode 100644 index 0000000..5084741c --- /dev/null +++ b/chrome/browser/ntp_snippets/ntp_snippets_metrics.cc
@@ -0,0 +1,36 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ntp_snippets/ntp_snippets_metrics.h" + +#include "base/metrics/histogram_macros.h" + +namespace { + +const char kContentSuggestionsNotificationImpressions[] = + "NewTabPage.ContentSuggestions.Notifications.Impressions"; +const char kContentSuggestionsNotificationActions[] = + "NewTabPage.ContentSuggestions.Notifications.Actions"; +const char kContentSuggestionsNotificationOptOuts[] = + "NewTabPage.ContentSuggestions.Notifications.AutoOptOuts"; + +} // namespace + +void RecordContentSuggestionsNotificationImpression( + ContentSuggestionsNotificationImpression what) { + UMA_HISTOGRAM_ENUMERATION(kContentSuggestionsNotificationImpressions, what, + MAX_CONTENT_SUGGESTIONS_NOTIFICATION_IMPRESSION); +} + +void RecordContentSuggestionsNotificationAction( + ContentSuggestionsNotificationAction what) { + UMA_HISTOGRAM_ENUMERATION(kContentSuggestionsNotificationActions, what, + MAX_CONTENT_SUGGESTIONS_NOTIFICATION_ACTION); +} + +void RecordContentSuggestionsNotificationOptOut( + ContentSuggestionsNotificationOptOut what) { + UMA_HISTOGRAM_ENUMERATION(kContentSuggestionsNotificationOptOuts, what, + MAX_CONTENT_SUGGESTIONS_NOTIFICATION_OPT_OUT); +}
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_metrics.h b/chrome/browser/ntp_snippets/ntp_snippets_metrics.h new file mode 100644 index 0000000..de37765 --- /dev/null +++ b/chrome/browser/ntp_snippets/ntp_snippets_metrics.h
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NTP_SNIPPETS_NTP_SNIPPETS_METRICS_H_ +#define CHROME_BROWSER_NTP_SNIPPETS_NTP_SNIPPETS_METRICS_H_ + +enum ContentSuggestionsNotificationImpression { + CONTENT_SUGGESTIONS_ARTICLE = 0, // Server-provided "articles" category. + CONTENT_SUGGESTIONS_NONARTICLE, // Anything else. + + MAX_CONTENT_SUGGESTIONS_NOTIFICATION_IMPRESSION +}; + +enum ContentSuggestionsNotificationAction { + CONTENT_SUGGESTIONS_TAP = 0, // User tapped notification to open article. + CONTENT_SUGGESTIONS_DISMISSAL, // User swiped notification to dismiss it. + + CONTENT_SUGGESTIONS_HIDE_DEADLINE, // notification_extra().deadline passed. + CONTENT_SUGGESTIONS_HIDE_EXPIRY, // NTP no longer shows notified article. + CONTENT_SUGGESTIONS_HIDE_FRONTMOST, // Chrome became the frontmost app. + CONTENT_SUGGESTIONS_HIDE_DISABLED, // NTP no longer shows whole category. + CONTENT_SUGGESTIONS_HIDE_SHUTDOWN, // Content sugg service is shutting down. + + MAX_CONTENT_SUGGESTIONS_NOTIFICATION_ACTION +}; + +enum ContentSuggestionsNotificationOptOut { + CONTENT_SUGGESTIONS_IMPLICIT = 0, // User ignored notifications. + CONTENT_SUGGESTIONS_EXPLICIT, // User explicitly opted-out. + + MAX_CONTENT_SUGGESTIONS_NOTIFICATION_OPT_OUT +}; + +void RecordContentSuggestionsNotificationImpression( + ContentSuggestionsNotificationImpression what); +void RecordContentSuggestionsNotificationAction( + ContentSuggestionsNotificationAction what); +void RecordContentSuggestionsNotificationOptOut( + ContentSuggestionsNotificationOptOut what); + +#endif // CHROME_BROWSER_NTP_SNIPPETS_NTP_SNIPPETS_METRICS_H_
diff --git a/chrome/browser/password_manager/credential_manager_browsertest.cc b/chrome/browser/password_manager/credential_manager_browsertest.cc index d10b3634..be572bb 100644 --- a/chrome/browser/password_manager/credential_manager_browsertest.cc +++ b/chrome/browser/password_manager/credential_manager_browsertest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/ui/passwords/passwords_model_delegate.h" #include "chrome/test/base/ui_test_utils.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" -#include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/test_password_store.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -23,28 +22,6 @@ namespace { -// A helper class that synchronously waits until the password store handles a -// GetLogins() request. -class PasswordStoreResultsObserver - : public password_manager::PasswordStoreConsumer { - public: - PasswordStoreResultsObserver() = default; - - void OnGetPasswordStoreResults( - std::vector<std::unique_ptr<autofill::PasswordForm>> results) override { - run_loop_.Quit(); - } - - void Wait() { - run_loop_.Run(); - } - - private: - base::RunLoop run_loop_; - - DISALLOW_COPY_AND_ASSIGN(PasswordStoreResultsObserver); -}; - class CredentialManagerBrowserTest : public PasswordManagerBrowserTestBase { public: CredentialManagerBrowserTest() = default; @@ -54,17 +31,6 @@ GetState() == password_manager::ui::CREDENTIAL_REQUEST_STATE; } - // Make sure that the password store processed all the previous calls which - // are executed on another thread. - void WaitForPasswordStore() { - scoped_refptr<password_manager::PasswordStore> password_store = - PasswordStoreFactory::GetForProfile( - browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS); - PasswordStoreResultsObserver syncer; - password_store->GetAutofillableLoginsWithAffiliatedRealms(&syncer); - syncer.Wait(); - } - // Similarly to PasswordManagerBrowserTestBase::NavigateToFile this is a // wrapper around ui_test_utils::NavigateURL that waits until DidFinishLoad() // fires. Different to NavigateToFile this method allows passing a test_server
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index a17d1f5..65af571 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1412,6 +1412,81 @@ EXPECT_FALSE(prompt_observer->IsShowingSavePrompt()); } +// Tests whether a attempted submission of a malicious credentials gets blocked. +// This simulates a case which is described in http://crbug.com/571580. +IN_PROC_BROWSER_TEST_F( + PasswordManagerBrowserTestBase, + NoPromptForSeperateLoginFormWhenSwitchingFromHttpsToHttp) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ::switches::kAllowRunningInsecureContent); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ::switches::kIgnoreCertificateErrors); + const base::FilePath::CharType kDocRoot[] = + FILE_PATH_LITERAL("chrome/test/data"); + net::EmbeddedTestServer https_test_server( + net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); + ASSERT_TRUE(https_test_server.Start()); + + std::string path = "/password/password_form.html"; + GURL https_url(https_test_server.GetURL(path)); + ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme)); + + NavigationObserver form_observer(WebContents()); + ui_test_utils::NavigateToURL(browser(), https_url); + form_observer.Wait(); + + std::string fill_and_submit_redirect = + "document.getElementById('username_redirect').value = 'user';" + "document.getElementById('password_redirect').value = 'password';" + "document.getElementById('submit_redirect').click()"; + ASSERT_TRUE( + content::ExecuteScript(RenderViewHost(), fill_and_submit_redirect)); + + NavigationObserver redirect_observer(WebContents()); + redirect_observer.SetPathToWaitFor("/password/redirect.html"); + redirect_observer.Wait(); + + // Normally the redirect happens to done.html. Here an attack is simulated + // that hijacks the redirect to a attacker controlled page. + GURL http_url( + embedded_test_server()->GetURL("/password/simple_password.html")); + std::string attacker_redirect = + "window.location.href = '" + http_url.spec() + "';"; + ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), attacker_redirect)); + + NavigationObserver attacker_observer(WebContents()); + attacker_observer.SetPathToWaitFor("/password/simple_password.html"); + attacker_observer.Wait(); + + std::string fill_and_submit_attacker_form = + "document.getElementById('username_field').value = 'attacker_username';" + "document.getElementById('password_field').value = 'attacker_password';" + "document.getElementById('input_submit_button').click()"; + ASSERT_TRUE( + content::ExecuteScript(RenderViewHost(), fill_and_submit_attacker_form)); + + NavigationObserver done_observer(WebContents()); + done_observer.SetPathToWaitFor("/password/done.html"); + done_observer.Wait(); + + WaitForPasswordStore(); + BubbleObserver prompt_observer(WebContents()); + EXPECT_TRUE(prompt_observer.IsShowingSavePrompt()); + prompt_observer.AcceptSavePrompt(); + + // Wait for password store and check that credentials are stored. + WaitForPasswordStore(); + scoped_refptr<password_manager::TestPasswordStore> password_store = + static_cast<password_manager::TestPasswordStore*>( + PasswordStoreFactory::GetForProfile( + browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS) + .get()); + EXPECT_FALSE(password_store->IsEmpty()); + CheckThatCredentialsStored(password_store.get(), base::ASCIIToUTF16("user"), + base::ASCIIToUTF16("password")); +} + IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, PromptWhenPasswordFormWithoutUsernameFieldSubmitted) { scoped_refptr<password_manager::TestPasswordStore> password_store =
diff --git a/chrome/browser/password_manager/password_manager_test_base.cc b/chrome/browser/password_manager/password_manager_test_base.cc index 44180f5..e8d0327 100644 --- a/chrome/browser/password_manager/password_manager_test_base.cc +++ b/chrome/browser/password_manager/password_manager_test_base.cc
@@ -25,6 +25,30 @@ #include "content/public/test/test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" +namespace { + +// A helper class that synchronously waits until the password store handles a +// GetLogins() request. +class PasswordStoreResultsObserver + : public password_manager::PasswordStoreConsumer { + public: + PasswordStoreResultsObserver() = default; + + void OnGetPasswordStoreResults( + std::vector<std::unique_ptr<autofill::PasswordForm>> results) override { + run_loop_.Quit(); + } + + void Wait() { run_loop_.Run(); } + + private: + base::RunLoop run_loop_; + + DISALLOW_COPY_AND_ASSIGN(PasswordStoreResultsObserver); +}; + +} // namespace + NavigationObserver::NavigationObserver(content::WebContents* web_contents) : content::WebContentsObserver(web_contents), quit_on_entry_committed_(false), @@ -230,6 +254,15 @@ << ", expected_value = " << expected_value; } +void PasswordManagerBrowserTestBase::WaitForPasswordStore() { + scoped_refptr<password_manager::PasswordStore> password_store = + PasswordStoreFactory::GetForProfile(browser()->profile(), + ServiceAccessType::IMPLICIT_ACCESS); + PasswordStoreResultsObserver syncer; + password_store->GetAutofillableLoginsWithAffiliatedRealms(&syncer); + syncer.Wait(); +} + void PasswordManagerBrowserTestBase::CheckElementValue( const std::string& element_id, const std::string& expected_value) {
diff --git a/chrome/browser/password_manager/password_manager_test_base.h b/chrome/browser/password_manager/password_manager_test_base.h index 5d36a1e..96180c9 100644 --- a/chrome/browser/password_manager/password_manager_test_base.h +++ b/chrome/browser/password_manager/password_manager_test_base.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/password_manager/core/browser/password_store_consumer.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/test_utils.h" @@ -122,6 +123,9 @@ void WaitForElementValue(const std::string& iframe_id, const std::string& element_id, const std::string& expected_value); + // Make sure that the password store processed all the previous calls which + // are executed on another thread. + void WaitForPasswordStore(); // Checks that the current "value" attribute of the HTML element with // |element_id| is equal to |expected_value|. void CheckElementValue(const std::string& element_id,
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc index 69d7fb1..65551c02 100644 --- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc +++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -165,7 +165,7 @@ IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchHistograms) { PrefetchFromFile(kPrefetchPage, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED); histogram_tester().ExpectTotalCount( - "Prerender.websame_NoStatePrefetchTTFCP.Warm", 0); + "Prerender.websame_PrefetchTTFCP.Warm.Cacheable.Visible", 0); test_utils::FirstContentfulPaintManagerWaiter* fcp_waiter = test_utils::FirstContentfulPaintManagerWaiter::Create(
diff --git a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc index 6a482e1..db561a30 100644 --- a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc +++ b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
@@ -264,7 +264,9 @@ // Needed for IPC. mojo::edk::Init(); - mojo::edk::ScopedIPCSupport ipc_support(service_process.io_task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + service_process.io_task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); MockServiceIPCServer server(&service_process, service_process.io_task_runner(), @@ -520,7 +522,8 @@ TEST_F(CloudPrintProxyPolicyStartupTest, StartAndShutdown) { mojo::edk::Init(); mojo::edk::ScopedIPCSupport ipc_support( - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal();
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index c89e97de..a947940 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -1307,14 +1307,13 @@ // cert will be selected automatically, then a test which uses WebSocket runs. IN_PROC_BROWSER_TEST_F(SSLUITestWithClientCert, TestWSSClientCert) { // Import a client cert for test. - scoped_refptr<net::CryptoModule> crypt_module = cert_db_->GetPublicModule(); + crypto::ScopedPK11Slot public_slot = cert_db_->GetPublicSlot(); std::string pkcs12_data; base::FilePath cert_path = net::GetTestCertsDirectory().Append( FILE_PATH_LITERAL("websocket_client_cert.p12")); EXPECT_TRUE(base::ReadFileToString(cert_path, &pkcs12_data)); - EXPECT_EQ(net::OK, - cert_db_->ImportFromPKCS12( - crypt_module.get(), pkcs12_data, base::string16(), true, NULL)); + EXPECT_EQ(net::OK, cert_db_->ImportFromPKCS12(public_slot.get(), pkcs12_data, + base::string16(), true, NULL)); // Start WebSocket test server with TLS and client cert authentication. net::SpawnedTestServer::SSLOptions options(
diff --git a/chrome/browser/ui/webui/options/certificate_manager_handler.cc b/chrome/browser/ui/webui/options/certificate_manager_handler.cc index bf7e29c3..95e5f53 100644 --- a/chrome/browser/ui/webui/options/certificate_manager_handler.cc +++ b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
@@ -857,7 +857,7 @@ // for Chrome OS when the "Import and Bind" option is chosen. bool is_extractable = !use_hardware_backed_; int result = certificate_manager_model_->ImportFromPKCS12( - module_.get(), file_data_, password_, is_extractable); + module_->os_module_handle(), file_data_, password_, is_extractable); ImportExportCleanup(); web_ui()->CallJavascriptFunctionUnsafe("CertificateRestoreOverlay.dismiss"); int string_id;
diff --git a/chrome/browser/ui/webui/settings/certificates_handler.cc b/chrome/browser/ui/webui/settings/certificates_handler.cc index 16503d82..cee6591 100644 --- a/chrome/browser/ui/webui/settings/certificates_handler.cc +++ b/chrome/browser/ui/webui/settings/certificates_handler.cc
@@ -740,7 +740,7 @@ // for Chrome OS when the "Import and Bind" option is chosen. bool is_extractable = !use_hardware_backed_; int result = certificate_manager_model_->ImportFromPKCS12( - module_.get(), file_data_, password_, is_extractable); + module_->os_module_handle(), file_data_, password_, is_extractable); ImportExportCleanup(); int string_id; switch (result) {
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index d759105..d85cdca 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -250,6 +250,8 @@ // Temporary for https://crbug.com/668633. { "swdh_set_hosted_version_worker_pid", crash_keys::kSmallSize }, { "swdh_set_hosted_version_host_pid", crash_keys::kSmallSize }, + { "swdh_set_hosted_version_is_new_process", crash_keys::kSmallSize }, + { "swdh_set_hosted_version_restart_count", crash_keys::kSmallSize }, }; // This dynamic set of keys is used for sets of key value pairs when gathering
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index e60041c..a510af5 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -1543,6 +1543,11 @@ // Keeps track of sync promo collapsed state in the Other Devices menu. const char kNtpCollapsedSyncPromo[] = "ntp.collapsed_sync_promo"; + +// Tracks how many notifications the user has ignored, so we can tell when we +// should stop showing them. +const char kContentSuggestionsConsecutiveIgnoredPrefName[] = + "ntp.content_suggestions.notifications.consecutive_ignored"; #endif // defined(OS_ANDROID) // Which page should be visible on the new tab page v4
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 67f9145..f0b812c9 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -557,6 +557,7 @@ extern const char kNtpCollapsedRecentlyClosedTabs[]; extern const char kNtpCollapsedSnapshotDocument[]; extern const char kNtpCollapsedSyncPromo[]; +extern const char kContentSuggestionsConsecutiveIgnoredPrefName[]; #endif // defined(OS_ANDROID) extern const char kNtpShownPage[];
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc index 3e3b8d8..394bc255 100644 --- a/chrome/service/service_process.cc +++ b/chrome/service/service_process.cc
@@ -171,8 +171,9 @@ // Initialize Mojo early so things can use it. mojo::edk::Init(); - mojo_ipc_support_.reset( - new mojo::edk::ScopedIPCSupport(io_thread_->task_runner())); + mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport( + io_thread_->task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); request_context_getter_ = new ServiceURLRequestContextGetter();
diff --git a/chrome/test/base/mojo_test_connector.cc b/chrome/test/base/mojo_test_connector.cc index 34135f4..2fb999e 100644 --- a/chrome/test/base/mojo_test_connector.cc +++ b/chrome/test/base/mojo_test_connector.cc
@@ -16,7 +16,6 @@ #include "content/public/test/test_launcher.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/process_delegate.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "services/catalog/store.h" #include "services/service_manager/public/cpp/connector.h"
diff --git a/chrome/test/base/run_all_unittests.cc b/chrome/test/base/run_all_unittests.cc index 17d4e8c..8536390 100644 --- a/chrome/test/base/run_all_unittests.cc +++ b/chrome/test/base/run_all_unittests.cc
@@ -8,13 +8,15 @@ #include "base/test/test_io_thread.h" #include "chrome/test/base/chrome_unit_test_suite.h" #include "content/public/test/unittest_test_suite.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" int main(int argc, char **argv) { content::UnitTestTestSuite test_suite(new ChromeUnitTestSuite(argc, argv)); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + test_io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); return base::LaunchUnitTests( argc, argv, base::Bind(&content::UnitTestTestSuite::Run,
diff --git a/chromecast/crash/cast_crash_keys.cc b/chromecast/crash/cast_crash_keys.cc index 991ced9..72db754 100644 --- a/chromecast/crash/cast_crash_keys.cc +++ b/chromecast/crash/cast_crash_keys.cc
@@ -108,6 +108,8 @@ // Temporary for https://crbug.com/668633. { "swdh_set_hosted_version_worker_pid", kSmallSize }, { "swdh_set_hosted_version_host_pid", kSmallSize }, + { "swdh_set_hosted_version_is_new_process", kSmallSize }, + { "swdh_set_hosted_version_restart_count", kSmallSize }, }; return base::debug::InitCrashKeys(fixed_keys, arraysize(fixed_keys),
diff --git a/chromeos/dbus/auth_policy_client.cc b/chromeos/dbus/auth_policy_client.cc index f3181c9b..43578e3 100644 --- a/chromeos/dbus/auth_policy_client.cc +++ b/chromeos/dbus/auth_policy_client.cc
@@ -71,12 +71,11 @@ void RefreshUserPolicy(const AccountId& account_id, const RefreshPolicyCallback& callback) override { + DCHECK(account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY); dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface, authpolicy::kAuthPolicyRefreshUserPolicy); dbus::MessageWriter writer(&method_call); - // TODO(tnagel): Switch to GUID once authpolicyd, session_manager and - // cryptohome support it, cf. https://crbug.com/677497. - writer.AppendString(account_id.GetUserEmail()); + writer.AppendString(account_id.GetAccountIdKey()); proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&AuthPolicyClientImpl::HandleRefreshPolicyCallback,
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc index e12ac310..f434dcd4 100644 --- a/chromeos/login/auth/cryptohome_authenticator.cc +++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -212,17 +212,17 @@ scoped_refptr<CryptohomeAuthenticator> resolver, bool ephemeral, bool create_if_nonexistent) { + if (attempt->user_context.GetAccountId().GetAccountType() == + AccountType::ACTIVE_DIRECTORY) { + cryptohome::SetGaiaIdMigrationStatusDone( + attempt->user_context.GetAccountId()); + } const bool is_gaiaid_migration_started = switches::IsGaiaIdMigrationStarted(); if (!is_gaiaid_migration_started) { UMACryptohomeMigrationToGaiaId(CryptohomeMigrationToGaiaId::NOT_STARTED); DoMount(attempt, resolver, ephemeral, create_if_nonexistent); return; } - if (attempt->user_context.GetAccountId().GetAccountType() == - AccountType::ACTIVE_DIRECTORY) { - cryptohome::SetGaiaIdMigrationStatusDone( - attempt->user_context.GetAccountId()); - } const bool already_migrated = cryptohome::GetGaiaIdMigrationStatus( attempt->user_context.GetAccountId()); const bool has_account_key =
diff --git a/chromeos/network/onc/onc_certificate_importer_impl.cc b/chromeos/network/onc/onc_certificate_importer_impl.cc index 7ab59a0..1f04a696 100644 --- a/chromeos/network/onc/onc_certificate_importer_impl.cc +++ b/chromeos/network/onc/onc_certificate_importer_impl.cc
@@ -286,12 +286,12 @@ crypto::ScopedPK11Slot private_slot(nssdb->GetPrivateSlot()); if (!private_slot) return false; - scoped_refptr<net::CryptoModule> module( - net::CryptoModule::CreateFromHandle(private_slot.get())); + net::CertificateList imported_certs; - int import_result = nssdb->ImportFromPKCS12( - module.get(), decoded_pkcs12, base::string16(), false, &imported_certs); + int import_result = + nssdb->ImportFromPKCS12(private_slot.get(), decoded_pkcs12, + base::string16(), false, &imported_certs); if (import_result != net::OK) { std::string error_string = net::ErrorToString(import_result); LOG(ERROR) << "Unable to import client certificate, error: "
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc index 0941c60..93d1bc6 100644 --- a/components/autofill/core/common/save_password_progress_logger.cc +++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -266,6 +266,8 @@ return "Invalid form"; case SavePasswordProgressLogger::STRING_SYNC_CREDENTIAL: return "Credential is used for syncing passwords"; + case STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME: + return "Blocked password due to same origin but insecure scheme"; case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVED_FORM: return "provisionally_saved_form"; case SavePasswordProgressLogger::STRING_IGNORE_POSSIBLE_USERNAMES:
diff --git a/components/autofill/core/common/save_password_progress_logger.h b/components/autofill/core/common/save_password_progress_logger.h index e5aaa70..de8a082 100644 --- a/components/autofill/core/common/save_password_progress_logger.h +++ b/components/autofill/core/common/save_password_progress_logger.h
@@ -90,6 +90,7 @@ STRING_FORM_BLACKLISTED, STRING_INVALID_FORM, STRING_SYNC_CREDENTIAL, + STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME, STRING_PROVISIONALLY_SAVED_FORM, STRING_IGNORE_POSSIBLE_USERNAMES, STRING_ON_PASSWORD_FORMS_RENDERED_METHOD,
diff --git a/components/nacl/common/nacl_service.cc b/components/nacl/common/nacl_service.cc index 3ce685d..fb19f6a8 100644 --- a/components/nacl/common/nacl_service.cc +++ b/components/nacl/common/nacl_service.cc
@@ -101,8 +101,9 @@ std::unique_ptr<service_manager::ServiceContext> CreateNaClServiceContext( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, mojo::ScopedMessagePipeHandle* ipc_channel) { - auto ipc_support = - base::MakeUnique<mojo::edk::ScopedIPCSupport>(std::move(io_task_runner)); + auto ipc_support = base::MakeUnique<mojo::edk::ScopedIPCSupport>( + std::move(io_task_runner), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); EstablishMojoConnection(); IPC::mojom::ChannelBootstrapPtr bootstrap;
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc index f8f1e64..db8803d 100644 --- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc +++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -112,6 +112,19 @@ SendLog(message); } +void BrowserSavePasswordProgressLogger::LogSuccessiveOrigins( + StringID label, + const GURL& old_origin, + const GURL& new_origin) { + std::string message = GetStringFromID(label) + ": {\n"; + message += + GetStringFromID(STRING_ORIGIN) + ": " + ScrubURL(old_origin) + "\n"; + message += + GetStringFromID(STRING_ORIGIN) + ": " + ScrubURL(new_origin) + "\n"; + message += "}"; + SendLog(message); +} + std::string BrowserSavePasswordProgressLogger::FormStructureToFieldsLogString( const autofill::FormStructure& form_structure) { std::string result;
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.h b/components/password_manager/core/browser/browser_save_password_progress_logger.h index ae556a2..d5c94232 100644 --- a/components/password_manager/core/browser/browser_save_password_progress_logger.h +++ b/components/password_manager/core/browser/browser_save_password_progress_logger.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "components/autofill/core/common/save_password_progress_logger.h" +#include "url/gurl.h" namespace autofill { class FormStructure; @@ -35,6 +36,12 @@ void LogFormStructure(StringID label, const autofill::FormStructure& form); // Browser-specific addition to the base class' Log* methods. The input is + // sanitized and passed to SendLog for display. + void LogSuccessiveOrigins(StringID label, + const GURL& old_origin, + const GURL& new_origin); + + // Browser-specific addition to the base class' Log* methods. The input is // passed to SendLog for display. void LogString(StringID label, const std::string& s);
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 491c5a60..574e49a 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -273,6 +273,17 @@ return; } + bool should_block = ShouldBlockPasswordForSameOriginButDifferentScheme(form); + metrics_util::LogShouldBlockPasswordForSameOriginButDifferentScheme( + should_block); + if (should_block) { + if (logger) + logger->LogSuccessiveOrigins( + Logger::STRING_BLOCK_PASSWORD_SAME_ORIGIN_INSECURE_SCHEME, + main_frame_url_.GetOrigin(), form.origin.GetOrigin()); + return; + } + auto matched_manager_it = pending_login_managers_.end(); PasswordFormManager::MatchResultMask current_match_result = PasswordFormManager::RESULT_NO_MATCH; @@ -562,6 +573,15 @@ return true; } +bool PasswordManager::ShouldBlockPasswordForSameOriginButDifferentScheme( + const PasswordForm& form) const { + const GURL& old_origin = main_frame_url_.GetOrigin(); + const GURL& new_origin = form.origin.GetOrigin(); + return old_origin.host_piece() == new_origin.host_piece() && + old_origin.SchemeIsCryptographic() && + !new_origin.SchemeIsCryptographic(); +} + bool PasswordManager::ShouldPromptUserToSavePassword() const { return !client_->IsAutomaticPasswordSavingEnabled() && (provisional_save_manager_->IsNewLogin() ||
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index 467f6a88..ccc1d89 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -11,6 +11,7 @@ #include <vector> #include "base/callback.h" +#include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/strings/string16.h" @@ -183,6 +184,10 @@ #endif private: + FRIEND_TEST_ALL_PREFIXES( + PasswordManagerTest, + ShouldBlockPasswordForSameOriginButDifferentSchemeTest); + enum ProvisionalSaveFailure { SAVING_DISABLED, EMPTY_PASSWORD, @@ -210,6 +215,13 @@ // non-blacklisted. bool CanProvisionalManagerSave(); + // Returns true if there already exists a provisionally saved password form + // from the same origin as |form|, but with a different and secure scheme. + // This prevents a potential attack where users can be tricked into saving + // unwanted credentials, see http://crbug.com/571580 for details. + bool ShouldBlockPasswordForSameOriginButDifferentScheme( + const autofill::PasswordForm& form) const; + // Returns true if the user needs to be prompted before a password can be // saved (instead of automatically saving // the password), based on inspecting the state of
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index 7b55d8d..8bc566bc 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -104,6 +104,12 @@ CHROME_SIGNIN_ACTION_COUNT); } +void LogShouldBlockPasswordForSameOriginButDifferentScheme(bool should_block) { + UMA_HISTOGRAM_BOOLEAN( + "PasswordManager.ShouldBlockPasswordForSameOriginButDifferentScheme", + should_block); +} + void LogAccountChooserUsability(AccountChooserUsabilityMetric usability) { UMA_HISTOGRAM_ENUMERATION("PasswordManager.AccountChooserDialogUsability", usability, ACCOUNT_CHOOSER_USABILITY_COUNT);
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index 9582c88..c2377f1 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -216,6 +216,9 @@ // Log a user action on showing the Chrome sign in promo. void LogSyncSigninPromoUserAction(SyncSignInUserAction action); +// Logs whether a password was rejected due to same origin but different scheme. +void LogShouldBlockPasswordForSameOriginButDifferentScheme(bool should_block); + // Log if the account chooser has empty username or duplicate usernames. void LogAccountChooserUsability(AccountChooserUsabilityMetric usability);
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index f45f191..5ce7d40 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -33,6 +33,7 @@ using testing::_; using testing::AnyNumber; using testing::Return; +using testing::ReturnRef; using testing::SaveArg; using testing::WithArg; @@ -67,6 +68,7 @@ void(const autofill::PasswordForm&)); MOCK_METHOD0(AutomaticPasswordSaveIndicator, void()); MOCK_METHOD0(GetPrefs, PrefService*()); + MOCK_CONST_METHOD0(GetMainFrameURL, const GURL&()); MOCK_METHOD0(GetDriver, PasswordManagerDriver*()); MOCK_CONST_METHOD0(GetStoreResultFilter, const MockStoreResultFilter*()); @@ -135,6 +137,9 @@ .WillRepeatedly(Return(password_autofill_manager_.get())); EXPECT_CALL(client_, DidLastPageLoadEncounterSSLErrors()) .WillRepeatedly(Return(false)); + + ON_CALL(client_, GetMainFrameURL()) + .WillByDefault(ReturnRef(GURL::EmptyGURL())); } void TearDown() override { @@ -748,6 +753,104 @@ manager()->OnPasswordFormsRendered(&driver_, observed, true); } +TEST_F(PasswordManagerTest, + ShouldBlockPasswordForSameOriginButDifferentSchemeTest) { + constexpr struct { + const char* old_origin; + const char* new_origin; + bool result; + } kTestData[] = { + // Same origin and same scheme. + {"https://example.com/login", "https://example.com/login", false}, + // Same host and same scheme, different port. + {"https://example.com:443/login", "https://example.com:444/login", false}, + // Same host but different scheme (https to http). + {"https://example.com/login", "http://example.com/login", true}, + // Same host but different scheme (http to https). + {"http://example.com/login", "https://example.com/login", false}, + // Different TLD, same schemes. + {"https://example.com/login", "https://example.org/login", false}, + // Different TLD, different schemes. + {"https://example.com/login", "http://example.org/login", false}, + // Different subdomains, same schemes. + {"https://sub1.example.com/login", "https://sub2.example.org/login", + false}, + }; + + PasswordForm form = MakeSimpleForm(); + for (const auto& test_case : kTestData) { + SCOPED_TRACE(testing::Message("#test_case = ") << (&test_case - kTestData)); + manager()->main_frame_url_ = GURL(test_case.old_origin); + form.origin = GURL(test_case.new_origin); + EXPECT_EQ( + test_case.result, + manager()->ShouldBlockPasswordForSameOriginButDifferentScheme(form)); + } +} + +// Tests whether two submissions to the same origin but different schemes +// result in only saving the first submission, which has a secure scheme. +TEST_F(PasswordManagerTest, AttemptedSavePasswordSameOriginInsecureScheme) { + PasswordForm secure_form(MakeSimpleForm()); + secure_form.origin = GURL("https://example.com/login"); + secure_form.action = GURL("https://example.com/login"); + secure_form.signon_realm = secure_form.origin.spec(); + + PasswordForm insecure_form(MakeSimpleForm()); + insecure_form.username_value = ASCIIToUTF16("compromised_user"); + insecure_form.password_value = ASCIIToUTF16("C0mpr0m1s3d_P4ss"); + insecure_form.origin = GURL("http://example.com/home"); + insecure_form.action = GURL("http://example.com/home"); + insecure_form.signon_realm = insecure_form.origin.spec(); + + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); + + EXPECT_CALL(client_, IsSavingAndFillingEnabledForCurrentPage()) + .WillRepeatedly(Return(true)); + + EXPECT_CALL(client_, GetMainFrameURL()) + .WillRepeatedly(ReturnRef(secure_form.origin)); + + // Parse, render and submit the secure form. + std::vector<PasswordForm> observed = {secure_form}; + manager()->OnPasswordFormsParsed(&driver_, observed); + manager()->OnPasswordFormsRendered(&driver_, observed, true); + OnPasswordFormSubmitted(secure_form); + + // Make sure |PromptUserToSaveOrUpdatePassword| gets called, and the resulting + // form manager is saved. + std::unique_ptr<PasswordFormManager> form_manager_to_save; + EXPECT_CALL(client_, + PromptUserToSaveOrUpdatePasswordPtr( + _, CredentialSourceType::CREDENTIAL_SOURCE_PASSWORD_MANAGER)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + + EXPECT_CALL(client_, GetMainFrameURL()) + .WillRepeatedly(ReturnRef(insecure_form.origin)); + + // Parse, render and submit the insecure form. + observed = {insecure_form}; + manager()->OnPasswordFormsParsed(&driver_, observed); + manager()->OnPasswordFormsRendered(&driver_, observed, true); + OnPasswordFormSubmitted(insecure_form); + + // Expect no further calls to |ProptUserToSaveOrUpdatePassword| due to + // insecure origin. + EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_, _)).Times(0); + + // Trigger call to |ProvisionalSavePassword| by rendering a page without + // forms. + observed.clear(); + manager()->OnPasswordFormsParsed(&driver_, observed); + manager()->OnPasswordFormsRendered(&driver_, observed, true); + + // Make sure that the form saved by the user is indeed the secure form. + ASSERT_TRUE(form_manager_to_save); + EXPECT_THAT(form_manager_to_save->pending_credentials(), + FormMatches(secure_form)); +} + // Create a form with both a new and current password element. Let the current // password value be non-empty and the new password value be empty and submit // the form. While normally saving the new password is preferred (on change
diff --git a/components/startup_metric_utils/OWNERS b/components/startup_metric_utils/OWNERS index 221025c9..711005f 100644 --- a/components/startup_metric_utils/OWNERS +++ b/components/startup_metric_utils/OWNERS
@@ -1,2 +1,4 @@ fdoray@chromium.org + +# To increase bus factor but prefer above OWNERS :). gab@chromium.org
diff --git a/components/task_scheduler_util/browser/initialization.cc b/components/task_scheduler_util/browser/initialization.cc index 3f1624b9..70b28773 100644 --- a/components/task_scheduler_util/browser/initialization.cc +++ b/components/task_scheduler_util/browser/initialization.cc
@@ -60,7 +60,7 @@ size_t BrowserWorkerPoolIndexForTraits(const base::TaskTraits& traits) { const bool is_background = traits.priority() == base::TaskPriority::BACKGROUND; - if (traits.with_file_io()) + if (traits.may_block() || traits.with_base_sync_primitives()) return is_background ? BACKGROUND_FILE_IO : FOREGROUND_FILE_IO; return is_background ? BACKGROUND : FOREGROUND; }
diff --git a/content/DEPS b/content/DEPS index ce566ff..3d29bf1 100644 --- a/content/DEPS +++ b/content/DEPS
@@ -36,7 +36,6 @@ "+mojo/common", "+mojo/edk/embedder", "+mojo/edk/js", - "+mojo/edk/test", "+mojo/message_pump", "+mojo/public", "+net",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 78d21f9..d6d917b 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -463,7 +463,7 @@ size_t DefaultBrowserWorkerPoolIndexForTraits(const base::TaskTraits& traits) { const bool is_background = traits.priority() == base::TaskPriority::BACKGROUND; - if (traits.with_file_io()) + if (traits.may_block() || traits.with_base_sync_primitives()) return is_background ? BACKGROUND_FILE_IO : FOREGROUND_FILE_IO; return is_background ? BACKGROUND : FOREGROUND; @@ -1698,7 +1698,8 @@ } mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport( - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); service_manager_context_.reset(new ServiceManagerContext); #if defined(OS_MACOSX)
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index ec4c476..9a41e0c 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -42,6 +42,8 @@ IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector, msg) IPC_MESSAGE_HANDLER(FrameHostMsg_ForwardInputEvent, OnForwardInputEvent) IPC_MESSAGE_HANDLER(FrameHostMsg_FrameRectChanged, OnFrameRectChanged) + IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateViewportIntersection, + OnUpdateViewportIntersection) IPC_MESSAGE_HANDLER(FrameHostMsg_VisibilityChanged, OnVisibilityChanged) IPC_MESSAGE_HANDLER(FrameHostMsg_SatisfySequence, OnSatisfySequence) IPC_MESSAGE_HANDLER(FrameHostMsg_RequireSequence, OnRequireSequence) @@ -288,6 +290,12 @@ SetRect(frame_rect); } +void CrossProcessFrameConnector::OnUpdateViewportIntersection( + const gfx::Rect& viewport_intersection) { + if (view_) + view_->UpdateViewportIntersection(viewport_intersection); +} + void CrossProcessFrameConnector::OnVisibilityChanged(bool visible) { if (!view_) return;
diff --git a/content/browser/frame_host/cross_process_frame_connector.h b/content/browser/frame_host/cross_process_frame_connector.h index 2b2160d1..6af5108 100644 --- a/content/browser/frame_host/cross_process_frame_connector.h +++ b/content/browser/frame_host/cross_process_frame_connector.h
@@ -144,6 +144,7 @@ // Handlers for messages received from the parent frame. void OnForwardInputEvent(const blink::WebInputEvent* event); void OnFrameRectChanged(const gfx::Rect& frame_rect); + void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection); void OnVisibilityChanged(bool visible); void OnSatisfySequence(const cc::SurfaceSequence& sequence); void OnRequireSequence(const cc::SurfaceId& id,
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc index ac8340ef..0c6bc7df 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -336,6 +336,13 @@ } } +void RenderWidgetHostViewChildFrame::UpdateViewportIntersection( + const gfx::Rect& viewport_intersection) { + if (host_) + host_->Send(new ViewMsg_SetViewportIntersection(host_->GetRoutingID(), + viewport_intersection)); +} + void RenderWidgetHostViewChildFrame::GestureEventAck( const blink::WebGestureEvent& event, InputEventAckState ack_result) {
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h index 9af289d..4c228e4 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.h +++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -194,6 +194,8 @@ void RegisterFrameSinkId(); void UnregisterFrameSinkId(); + void UpdateViewportIntersection(const gfx::Rect& viewport_intersection); + protected: friend class RenderWidgetHostView; friend class RenderWidgetHostViewChildFrameTest;
diff --git a/content/browser/loader/DEPS b/content/browser/loader/DEPS index 58169f05..8a128b3 100644 --- a/content/browser/loader/DEPS +++ b/content/browser/loader/DEPS
@@ -345,6 +345,7 @@ "upload_progress_tracker\.(cc|h)": [ "-content", "+content/browser/loader/upload_progress_tracker.h", + "+content/common/content_export.h", ], "url_loader_factory_impl\.(cc|h)": [ "-content",
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index d55bc0f9..7503da6 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc
@@ -34,6 +34,7 @@ #include "ipc/ipc_message_macros.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" +#include "net/base/upload_progress.h" #include "net/url_request/redirect_info.h" using base::TimeDelta; @@ -553,13 +554,13 @@ inlining_helper_->RecordHistogram(elapsed_time); } -void AsyncResourceHandler::SendUploadProgress(int64_t current_position, - int64_t total_size) { +void AsyncResourceHandler::SendUploadProgress( + const net::UploadProgress& progress) { ResourceMessageFilter* filter = GetFilter(); if (!filter) return; filter->Send(new ResourceMsg_UploadProgress( - GetRequestID(), current_position, total_size)); + GetRequestID(), progress.position(), progress.size())); } } // namespace content
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h index fb69ec7..dbf3b035 100644 --- a/content/browser/loader/async_resource_handler.h +++ b/content/browser/loader/async_resource_handler.h
@@ -20,6 +20,7 @@ namespace net { class URLRequest; +class UploadProgress; } namespace content { @@ -67,7 +68,7 @@ int CalculateEncodedDataLengthToReport(); int CalculateEncodedBodyLengthToReport(); void RecordHistogram(); - void SendUploadProgress(int64_t current_position, int64_t total_size); + void SendUploadProgress(const net::UploadProgress& progress); scoped_refptr<ResourceBuffer> buffer_; ResourceDispatcherHostImpl* rdh_;
diff --git a/content/browser/loader/upload_progress_tracker.cc b/content/browser/loader/upload_progress_tracker.cc index 790bea4..6633e61 100644 --- a/content/browser/loader/upload_progress_tracker.cc +++ b/content/browser/loader/upload_progress_tracker.cc
@@ -18,11 +18,12 @@ UploadProgressTracker::UploadProgressTracker( const tracked_objects::Location& location, UploadProgressReportCallback report_progress, - net::URLRequest* request) + net::URLRequest* request, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) : request_(request), report_progress_(std::move(report_progress)) { - DCHECK(request_); DCHECK(report_progress_); + progress_timer_.SetTaskRunner(std::move(task_runner)); progress_timer_.Start(location, kUploadProgressInterval, this, &UploadProgressTracker::ReportUploadProgressIfNeeded); } @@ -39,22 +40,33 @@ progress_timer_.Stop(); } +base::TimeTicks UploadProgressTracker::GetCurrentTime() const { + return base::TimeTicks::Now(); +} + +net::UploadProgress UploadProgressTracker::GetUploadProgress() const { + return request_->GetUploadProgress(); +} + void UploadProgressTracker::ReportUploadProgressIfNeeded() { if (waiting_for_upload_progress_ack_) return; - net::UploadProgress progress = request_->GetUploadProgress(); + net::UploadProgress progress = GetUploadProgress(); if (!progress.size()) - return; // Nothing to upload. + return; // Nothing to upload, or in the chunked upload mode. - if (progress.position() == last_upload_position_) - return; // No progress made since last time. + // No progress made since last time, or the progress was reset by a redirect + // or a retry. + if (progress.position() <= last_upload_position_) + return; const uint64_t kHalfPercentIncrements = 200; const base::TimeDelta kOneSecond = base::TimeDelta::FromMilliseconds(1000); uint64_t amt_since_last = progress.position() - last_upload_position_; - base::TimeDelta time_since_last = base::TimeTicks::Now() - last_upload_ticks_; + base::TimeTicks now = GetCurrentTime(); + base::TimeDelta time_since_last = now - last_upload_ticks_; bool is_finished = (progress.size() == progress.position()); bool enough_new_progress = @@ -62,9 +74,9 @@ bool too_much_time_passed = time_since_last > kOneSecond; if (is_finished || enough_new_progress || too_much_time_passed) { - report_progress_.Run(progress.position(), progress.size()); + report_progress_.Run(progress); waiting_for_upload_progress_ack_ = true; - last_upload_ticks_ = base::TimeTicks::Now(); + last_upload_ticks_ = now; last_upload_position_ = progress.position(); } }
diff --git a/content/browser/loader/upload_progress_tracker.h b/content/browser/loader/upload_progress_tracker.h index 4172490b..6840f5a6 100644 --- a/content/browser/loader/upload_progress_tracker.h +++ b/content/browser/loader/upload_progress_tracker.h
@@ -9,8 +9,17 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "content/common/content_export.h" +#include "net/base/upload_progress.h" + +namespace base { +class SingleThreadTaskRunner; +} namespace tracked_objects { class Location; @@ -24,20 +33,26 @@ // UploadProgressTracker watches the upload progress of a URL loading, and sends // the progress to the client in a suitable granularity and frequency. -class UploadProgressTracker final { +class CONTENT_EXPORT UploadProgressTracker { public: using UploadProgressReportCallback = - base::RepeatingCallback<void(int64_t, int64_t)>; + base::RepeatingCallback<void(const net::UploadProgress&)>; UploadProgressTracker(const tracked_objects::Location& location, UploadProgressReportCallback report_progress, - net::URLRequest* request); + net::URLRequest* request, + scoped_refptr<base::SingleThreadTaskRunner> + task_runner = base::ThreadTaskRunnerHandle::Get()); ~UploadProgressTracker(); void OnAckReceived(); void OnUploadCompleted(); private: + // Overridden by tests to use a fake time and progress. + virtual base::TimeTicks GetCurrentTime() const; + virtual net::UploadProgress GetUploadProgress() const; + void ReportUploadProgressIfNeeded(); net::URLRequest* request_; // Not owned.
diff --git a/content/browser/loader/upload_progress_tracker_unittest.cc b/content/browser/loader/upload_progress_tracker_unittest.cc new file mode 100644 index 0000000..508368d --- /dev/null +++ b/content/browser/loader/upload_progress_tracker_unittest.cc
@@ -0,0 +1,256 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/loader/upload_progress_tracker.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "base/test/test_simple_task_runner.h" +#include "net/base/upload_progress.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +class TestingUploadProgressTracker : public UploadProgressTracker { + public: + TestingUploadProgressTracker( + const tracked_objects::Location& location, + UploadProgressReportCallback report_callback, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : UploadProgressTracker(location, + std::move(report_callback), + nullptr, + std::move(task_runner)), + current_time_(base::TimeTicks::Now()) {} + + void set_upload_progress(const net::UploadProgress& upload_progress) { + upload_progress_ = upload_progress; + } + + void set_current_time(const base::TimeTicks& current_time) { + current_time_ = current_time; + } + + private: + // UploadProgressTracker overrides. + base::TimeTicks GetCurrentTime() const override { return current_time_; } + net::UploadProgress GetUploadProgress() const override { + return upload_progress_; + } + + base::TimeTicks current_time_; + net::UploadProgress upload_progress_; + + DISALLOW_COPY_AND_ASSIGN(TestingUploadProgressTracker); +}; + +} // namespace + +class UploadProgressTrackerTest : public ::testing::Test { + public: + UploadProgressTrackerTest() + : task_runner_(new base::TestSimpleTaskRunner), + upload_progress_tracker_( + FROM_HERE, + base::BindRepeating( + &UploadProgressTrackerTest::OnUploadProgressReported, + base::Unretained(this)), + task_runner_) {} + + private: + void OnUploadProgressReported(const net::UploadProgress& progress) { + ++report_count_; + reported_position_ = progress.position(); + reported_total_size_ = progress.size(); + } + + protected: + int report_count_ = 0; + int64_t reported_position_ = 0; + int64_t reported_total_size_ = 0; + + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + TestingUploadProgressTracker upload_progress_tracker_; + + DISALLOW_COPY_AND_ASSIGN(UploadProgressTrackerTest); +}; + +TEST_F(UploadProgressTrackerTest, NoACK) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(500, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.set_upload_progress(net::UploadProgress(750, 1000)); + + // The second timer task does nothing, since the first report didn't send the + // ACK. + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); +} + +TEST_F(UploadProgressTrackerTest, NoUpload) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(0, 0)); + + // UploadProgressTracker does nothing on the empty upload content. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(0, report_count_); +} + +TEST_F(UploadProgressTrackerTest, NoProgress) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(500, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.OnAckReceived(); + + // The second time doesn't call ReportUploadProgress since there's no + // progress. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); +} + +TEST_F(UploadProgressTrackerTest, Finished) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(999, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(999, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.OnAckReceived(); + upload_progress_tracker_.set_upload_progress(net::UploadProgress(1000, 1000)); + + // The second timer task calls ReportUploadProgress for reporting the + // completion. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(2, report_count_); + EXPECT_EQ(1000, reported_position_); + EXPECT_EQ(1000, reported_total_size_); +} + +TEST_F(UploadProgressTrackerTest, Progress) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(500, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.OnAckReceived(); + upload_progress_tracker_.set_upload_progress(net::UploadProgress(750, 1000)); + + // The second timer task calls ReportUploadProgress since the progress is + // big enough to report. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(2, report_count_); + EXPECT_EQ(750, reported_position_); + EXPECT_EQ(1000, reported_total_size_); +} + +TEST_F(UploadProgressTrackerTest, TimePassed) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(500, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.OnAckReceived(); + upload_progress_tracker_.set_upload_progress(net::UploadProgress(501, 1000)); + + // The second timer task doesn't call ReportUploadProgress since the progress + // is too small to report it. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + + upload_progress_tracker_.set_current_time(base::TimeTicks::Now() + + base::TimeDelta::FromSeconds(1)); + + // The third timer task calls ReportUploadProgress since it's been long time + // from the last report. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(2, report_count_); + EXPECT_EQ(501, reported_position_); + EXPECT_EQ(1000, reported_total_size_); +} + +TEST_F(UploadProgressTrackerTest, Rewound) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(500, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.OnAckReceived(); + upload_progress_tracker_.set_upload_progress(net::UploadProgress(250, 1000)); + + // The second timer task doesn't call ReportUploadProgress since the progress + // was rewound. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + + upload_progress_tracker_.set_current_time(base::TimeTicks::Now() + + base::TimeDelta::FromSeconds(1)); + + // Even after a good amount of time passed, the rewound progress should not be + // reported. + EXPECT_EQ(1, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); +} + +TEST_F(UploadProgressTrackerTest, Completed) { + upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000)); + + // The first timer task calls ReportUploadProgress. + EXPECT_EQ(0, report_count_); + task_runner_->RunPendingTasks(); + EXPECT_EQ(1, report_count_); + EXPECT_EQ(500, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + upload_progress_tracker_.set_upload_progress(net::UploadProgress(1000, 1000)); + + // OnUploadCompleted runs ReportUploadProgress even without Ack nor timer. + upload_progress_tracker_.OnUploadCompleted(); + EXPECT_EQ(2, report_count_); + EXPECT_EQ(1000, reported_position_); + EXPECT_EQ(1000, reported_total_size_); + + task_runner_->RunPendingTasks(); + EXPECT_EQ(2, report_count_); + EXPECT_FALSE(task_runner_->HasPendingTask()); +} + +} // namespace context
diff --git a/content/browser/resources/media/peer_connection_update_table.js b/content/browser/resources/media/peer_connection_update_table.js index f3475a8..d6795d5 100644 --- a/content/browser/resources/media/peer_connection_update_table.js +++ b/content/browser/resources/media/peer_connection_update_table.js
@@ -99,6 +99,15 @@ return; } + if (update.type === 'onIceCandidate' || + update.type === 'addIceCandidate') { + // extract ICE candidate type from the field following typ. + var candidateType = update.value.match( + /(?: typ )(host|srflx|relay)/)[1]; + if (candidateType) { + type += ' (' + candidateType + ')'; + } + } row.innerHTML += '<td><details><summary>' + type + '</summary></details></td>'; @@ -106,6 +115,14 @@ var details = row.cells[1].childNodes[0]; details.appendChild(valueContainer); + // Highlight ICE failures and failure callbacks. + if ((update.type === 'iceConnectionStateChange' && + update.value === 'ICEConnectionStateFailed') || + update.type.indexOf('OnFailure') !== -1 || + update.type === 'addIceCandidateFailed') { + valueContainer.parentElement.classList.add('update-log-failure'); + } + var value = update.value; // map internal names and values to names and events from the // specification. This is a display change which shall not
diff --git a/content/browser/resources/media/webrtc_internals.css b/content/browser/resources/media/webrtc_internals.css index cf6f31a..b8111e19 100644 --- a/content/browser/resources/media/webrtc_internals.css +++ b/content/browser/resources/media/webrtc_internals.css
@@ -14,6 +14,10 @@ overflow: auto; } +.update-log-failure { + background-color: #be2026; +} + .ssrc-info-block { color: #999; font-size: 0.8em;
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 7cf6e74..aa9b94f 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -477,6 +477,7 @@ std::unique_ptr<EmbeddedWorkerStartParams> params, mojom::ServiceWorkerEventDispatcherRequest dispatcher_request, const StatusCallback& callback) { + restart_count_++; if (!context_) { callback.Run(SERVICE_WORKER_ERROR_ABORT); // |this| may be destroyed by the callback. @@ -597,6 +598,7 @@ embedded_worker_id_(embedded_worker_id), status_(EmbeddedWorkerStatus::STOPPED), starting_phase_(NOT_STARTING), + restart_count_(0), thread_id_(kInvalidEmbeddedWorkerThreadId), devtools_attached_(false), network_accessed_for_script_(false),
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h index 3152613..2054db8 100644 --- a/content/browser/service_worker/embedded_worker_instance.h +++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -136,6 +136,7 @@ DCHECK_EQ(EmbeddedWorkerStatus::STARTING, status()); return starting_phase_; } + int restart_count() const { return restart_count_; } int process_id() const; int thread_id() const { return thread_id_; } // This should be called only when the worker instance has a valid process, @@ -296,6 +297,7 @@ EmbeddedWorkerStatus status_; StartingPhase starting_phase_; + int restart_count_; // Current running information. std::unique_ptr<EmbeddedWorkerInstance::WorkerProcessHandle> process_handle_;
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index c0e32ce..e0574c1 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -36,6 +36,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/browser_side_navigation_policy.h" +#include "content/public/common/child_process_host.h" #include "content/public/common/content_client.h" #include "content/public/common/origin_util.h" #include "ipc/ipc_message_macros.h" @@ -1087,6 +1088,15 @@ base::debug::ScopedCrashKey scope_provider_host_pid( "swdh_set_hosted_version_host_pid", base::IntToString(provider_host->process_id())); + if (version->embedded_worker()->process_id() != + ChildProcessHost::kInvalidUniqueID) { + base::debug::ScopedCrashKey scope_is_new_process( + "swdh_set_hosted_version_is_new_process", + version->embedded_worker()->is_new_process() ? "true" : "false"); + } + base::debug::ScopedCrashKey scope_worker_restart_count( + "swdh_set_hosted_version_restart_count", + base::IntToString(version->embedded_worker()->restart_count())); bad_message::ReceivedBadMessage( this, bad_message::SWDH_SET_HOSTED_VERSION_PROCESS_MISMATCH); return;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index d2c4660..2666ba2 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -433,7 +433,8 @@ if (!IsInBrowserProcess()) { // Don't double-initialize IPC support in single-process mode. - mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(GetIOTaskRunner())); + mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport( + GetIOTaskRunner(), mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); InitializeMojoIPCChannel(); } std::string service_request_token;
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 5eb31e75d..c2d8c47 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -1315,6 +1315,11 @@ // position of a child's ancestor has changed). IPC_MESSAGE_ROUTED1(FrameHostMsg_FrameRectChanged, gfx::Rect /* frame_rect */) +// Sent by a parent frame to update its child's viewport intersection rect for +// use by the IntersectionObserver API. +IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdateViewportIntersection, + gfx::Rect /* viewport_intersection */) + // Informs the child that the frame has changed visibility. IPC_MESSAGE_ROUTED1(FrameHostMsg_VisibilityChanged, bool /* visible */)
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 3c9d75e..7bf0b14b 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -608,6 +608,10 @@ IPC_MESSAGE_ROUTED1(ViewMsg_HandleCompositorProto, std::vector<uint8_t> /* proto */) +// Sets the viewport intersection on the widget for an out-of-process iframe. +IPC_MESSAGE_ROUTED1(ViewMsg_SetViewportIntersection, + gfx::Rect /* viewport_intersection */) + // ----------------------------------------------------------------------------- // Messages sent from the renderer to the browser.
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index fed88d5..83679237 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -237,8 +237,9 @@ // Initialize mojo firstly to enable Blink initialization to use it. InitializeMojo(); test_io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); - ipc_support_.reset( - new mojo::edk::test::ScopedIPCSupport(test_io_thread_->task_runner())); + ipc_support_.reset(new mojo::edk::ScopedIPCSupport( + test_io_thread_->task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); // Blink needs to be initialized before calling CreateContentRendererClient() // because it uses blink internally.
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h index 2e8a521..a14e4ec 100644 --- a/content/public/test/render_view_test.h +++ b/content/public/test/render_view_test.h
@@ -19,7 +19,7 @@ #include "content/public/common/main_function_params.h" #include "content/public/common/page_state.h" #include "content/public/test/mock_render_thread.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/web/WebFrame.h" @@ -210,7 +210,7 @@ // For Mojo. std::unique_ptr<base::TestIOThread> test_io_thread_; - std::unique_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support_; + std::unique_ptr<mojo::edk::ScopedIPCSupport> ipc_support_; #if defined(OS_MACOSX) std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool_;
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc index 211ecdfa..e9251c3 100644 --- a/content/public/test/test_browser_thread_bundle.cc +++ b/content/public/test/test_browser_thread_bundle.cc
@@ -17,11 +17,13 @@ : TestBrowserThreadBundle(DEFAULT) {} TestBrowserThreadBundle::TestBrowserThreadBundle(int options) - : options_(options), threads_started_(false) { + : options_(options), threads_created_(false) { Init(); } TestBrowserThreadBundle::~TestBrowserThreadBundle() { + DCHECK(threads_created_); + // To avoid memory leaks, we must ensure that any tasks posted to the blocking // pool via PostTaskAndReply are able to reply back to the originating thread. // Thus we must flush the blocking pool while the browser threads still exist. @@ -65,23 +67,34 @@ void TestBrowserThreadBundle::Init() { // Check for conflicting options can't have two IO threads. CHECK(!(options_ & IO_MAINLOOP) || !(options_ & REAL_IO_THREAD)); - // There must be a thread to start to use DONT_START_THREADS - CHECK((options_ & ~IO_MAINLOOP) != DONT_START_THREADS); + // There must be a thread to start to use DONT_CREATE_THREADS + CHECK((options_ & ~IO_MAINLOOP) != DONT_CREATE_THREADS); + // Create the UI thread. In production, this work is done in + // BrowserMainLoop::MainMessageLoopStart(). if (options_ & IO_MAINLOOP) { message_loop_.reset(new base::MessageLoopForIO()); } else { message_loop_.reset(new base::MessageLoopForUI()); } - task_scheduler_.reset( - new base::test::ScopedTaskScheduler(message_loop_.get())); - ui_thread_.reset( new TestBrowserThread(BrowserThread::UI, message_loop_.get())); + if (!(options_ & DONT_CREATE_THREADS)) + CreateThreads(); +} + +// This method mimics the work done in BrowserMainLoop::CreateThreads(). +void TestBrowserThreadBundle::CreateThreads() { + DCHECK(!threads_created_); + + task_scheduler_.reset( + new base::test::ScopedTaskScheduler(message_loop_.get())); + if (options_ & REAL_DB_THREAD) { db_thread_.reset(new TestBrowserThread(BrowserThread::DB)); + db_thread_->Start(); } else { db_thread_.reset( new TestBrowserThread(BrowserThread::DB, message_loop_.get())); @@ -89,6 +102,7 @@ if (options_ & REAL_FILE_THREAD) { file_thread_.reset(new TestBrowserThread(BrowserThread::FILE)); + file_thread_->Start(); } else { file_thread_.reset( new TestBrowserThread(BrowserThread::FILE, message_loop_.get())); @@ -103,28 +117,13 @@ if (options_ & REAL_IO_THREAD) { io_thread_.reset(new TestBrowserThread(BrowserThread::IO)); + io_thread_->StartIOThread(); } else { io_thread_.reset( new TestBrowserThread(BrowserThread::IO, message_loop_.get())); } - if (!(options_ & DONT_START_THREADS)) - Start(); -} - -void TestBrowserThreadBundle::Start() { - DCHECK(!threads_started_); - - if (options_ & REAL_DB_THREAD) - db_thread_->Start(); - - if (options_ & REAL_FILE_THREAD) - file_thread_->Start(); - - if (options_ & REAL_IO_THREAD) - io_thread_->StartIOThread(); - - threads_started_ = true; + threads_created_ = true; } } // namespace content
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h index 0138a723..4a6b030 100644 --- a/content/public/test/test_browser_thread_bundle.h +++ b/content/public/test/test_browser_thread_bundle.h
@@ -26,13 +26,11 @@ // REAL_IO_THREAD. // // For some tests it is important to emulate real browser startup. During real -// browser startup some initialization is done (e.g. creation of thread objects) -// between creating the main thread message loop, which is bound to the existing -// main thread, and starting the other threads. Passing DONT_START_THREADS to -// constructor will delay staring these other threads until the test explicitly -// calls Start(). +// browser startup, the main MessageLoop is created before other threads. +// Passing DONT_CREATE_THREADS to constructor will delay creating other threads +// until the test explicitly calls CreateThreads(). // -// DONT_START_THREADS should only be used when the options specify at least +// DONT_CREATE_THREADS should only be used when the options specify at least // one real thread other than the main thread. #ifndef CONTENT_PUBLIC_TEST_TEST_BROWSER_THREAD_BUNDLE_H_ @@ -64,15 +62,15 @@ REAL_DB_THREAD = 0x02, REAL_FILE_THREAD = 0x08, REAL_IO_THREAD = 0x10, - DONT_START_THREADS = 0x20, + DONT_CREATE_THREADS = 0x20, }; TestBrowserThreadBundle(); explicit TestBrowserThreadBundle(int options); - // Start the real threads; should only be called from other classes if the - // DONT_START_THREADS option was used when the bundle was created. - void Start(); + // Creates threads; should only be called from other classes if the + // DONT_CREATE_THREADS option was used when the bundle was created. + void CreateThreads(); ~TestBrowserThreadBundle(); @@ -90,7 +88,7 @@ std::unique_ptr<TestBrowserThread> io_thread_; int options_; - bool threads_started_; + bool threads_created_; DISALLOW_COPY_AND_ASSIGN(TestBrowserThreadBundle); };
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index b268ad01..abfdbfe 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -701,8 +701,8 @@ "//third_party/opus", "//third_party/webrtc/api:libjingle_peerconnection", "//third_party/webrtc/api:rtc_stats_api", + "//third_party/webrtc/api:video_frame_api", "//third_party/webrtc/base:rtc_base", - "//third_party/webrtc/common_video", "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/media:rtc_media_base", "//third_party/webrtc/modules/audio_device",
diff --git a/content/renderer/media/gpu/rtc_video_decoder.cc b/content/renderer/media/gpu/rtc_video_decoder.cc index 929ab57..63239737 100644 --- a/content/renderer/media/gpu/rtc_video_decoder.cc +++ b/content/renderer/media/gpu/rtc_video_decoder.cc
@@ -18,10 +18,10 @@ #include "media/base/bind_to_current_loop.h" #include "media/renderers/gpu_video_accelerator_factories.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/webrtc/api/video/video_frame.h" #include "third_party/webrtc/base/bind.h" #include "third_party/webrtc/base/refcount.h" #include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h" -#include "third_party/webrtc/video_frame.h" #if defined(OS_WIN) #include "base/command_line.h"
diff --git a/content/renderer/media/media_stream_video_source.cc b/content/renderer/media/media_stream_video_source.cc index c95f429..759e621 100644 --- a/content/renderer/media/media_stream_video_source.cc +++ b/content/renderer/media/media_stream_video_source.cc
@@ -106,7 +106,10 @@ } } for (const auto& constraint_set : constraints.advanced()) { - if (constraint_set.aspectRatio.hasMax()) { + // Advanced constraint sets with max aspect ratio 0 are unsatisfiable and + // must be ignored. + if (constraint_set.aspectRatio.hasMax() && + constraint_set.aspectRatio.max() > 0) { *max_aspect_ratio = constraint_set.aspectRatio.max(); break; }
diff --git a/content/renderer/media/media_stream_video_source_unittest.cc b/content/renderer/media/media_stream_video_source_unittest.cc index bfb572d..dfeea8e 100644 --- a/content/renderer/media/media_stream_video_source_unittest.cc +++ b/content/renderer/media/media_stream_video_source_unittest.cc
@@ -782,4 +782,24 @@ sink.DisconnectFromTrack(); } +// Test that an optional constraint with an invalid aspect ratio is ignored. +TEST_F(MediaStreamVideoSourceTest, InvalidOptionalAspectRatioIgnored) { + MockConstraintFactory factory; + factory.AddAdvanced().aspectRatio.setMax(0.0); + blink::WebMediaStreamTrack track = + CreateTrack("123", factory.CreateWebMediaConstraints()); + mock_source()->CompleteGetSupportedFormats(); + EXPECT_EQ(0, NumberOfFailedConstraintsCallbacks()); +} + +// Test that setting an invalid mandatory aspect ratio fails. +TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryAspectRatioFails) { + MockConstraintFactory factory; + factory.basic().aspectRatio.setMax(0.0); + blink::WebMediaStreamTrack track = + CreateTrack("123", factory.CreateWebMediaConstraints()); + mock_source()->CompleteGetSupportedFormats(); + EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks()); +} + } // namespace content
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc index d5bdd1c..84daf7e 100644 --- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc +++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -21,7 +21,7 @@ #include "third_party/libyuv/include/libyuv/convert_from.h" #include "third_party/libyuv/include/libyuv/scale.h" #include "third_party/skia/include/core/SkSurface.h" -#include "third_party/webrtc/common_video/rotation.h" +#include "third_party/webrtc/api/video/video_rotation.h" namespace content {
diff --git a/content/renderer/media/webrtc/webrtc_video_frame_adapter.h b/content/renderer/media/webrtc/webrtc_video_frame_adapter.h index fadd508..47b4518 100644 --- a/content/renderer/media/webrtc/webrtc_video_frame_adapter.h +++ b/content/renderer/media/webrtc/webrtc_video_frame_adapter.h
@@ -9,7 +9,7 @@ #include "base/callback.h" #include "media/base/video_frame.h" -#include "third_party/webrtc/common_video/include/video_frame_buffer.h" +#include "third_party/webrtc/api/video/video_frame_buffer.h" namespace content { // Thin adapter from media::VideoFrame to webrtc::VideoFrameBuffer. This
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index c318049c..fe58b65b 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -30,6 +30,7 @@ #include "ipc/ipc_message_macros.h" #include "third_party/WebKit/public/platform/URLConversion.h" #include "third_party/WebKit/public/platform/WebFeaturePolicy.h" +#include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" @@ -492,6 +493,12 @@ Send(new FrameHostMsg_FrameRectChanged(routing_id_, rect)); } +void RenderFrameProxy::updateRemoteViewportIntersection( + const blink::WebRect& viewportIntersection) { + Send(new FrameHostMsg_UpdateViewportIntersection( + routing_id_, gfx::Rect(viewportIntersection))); +} + void RenderFrameProxy::visibilityChanged(bool visible) { Send(new FrameHostMsg_VisibilityChanged(routing_id_, visible)); }
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index e7f2e54..3de7d667 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -131,6 +131,8 @@ bool should_replace_current_entry) override; void forwardInputEvent(const blink::WebInputEvent* event) override; void frameRectsChanged(const blink::WebRect& frame_rect) override; + void updateRemoteViewportIntersection( + const blink::WebRect& viewportIntersection) override; void visibilityChanged(bool visible) override; void setHasReceivedUserGesture() override; void didChangeOpener(blink::WebFrame* opener) override;
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc index e837e4f..180e34fe 100644 --- a/content/renderer/render_process_impl.cc +++ b/content/renderer/render_process_impl.cc
@@ -120,7 +120,7 @@ size_t DefaultRendererWorkerPoolIndexForTraits(const base::TaskTraits& traits) { const bool is_background = traits.priority() == base::TaskPriority::BACKGROUND; - if (traits.with_file_io()) + if (traits.may_block() || traits.with_base_sync_primitives()) return is_background ? BACKGROUND_FILE_IO : FOREGROUND_FILE_IO; return is_background ? BACKGROUND : FOREGROUND;
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc index dcdc702..af28029 100644 --- a/content/renderer/render_thread_impl_browsertest.cc +++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -44,7 +44,6 @@ #include "ipc/ipc.mojom.h" #include "ipc/ipc_channel_mojo.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h" #include "ui/gfx/buffer_format_util.h" @@ -179,7 +178,6 @@ base::ThreadTaskRunnerHandle::Get(); InitializeMojo(); - ipc_support_.reset(new mojo::edk::test::ScopedIPCSupport(io_task_runner)); shell_context_.reset(new TestServiceManagerContext); child_connection_.reset(new ChildConnection( mojom::kRendererServiceName, "test", mojo::edk::GenerateRandomToken(), @@ -241,7 +239,6 @@ std::unique_ptr<ContentRendererClient> content_renderer_client_; std::unique_ptr<TestBrowserThreadBundle> browser_threads_; - std::unique_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support_; std::unique_ptr<TestServiceManagerContext> shell_context_; std::unique_ptr<ChildConnection> child_connection_; std::unique_ptr<IPC::ChannelProxy> channel_;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index d72800f..a38ef25 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -619,6 +619,8 @@ IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection) IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck) IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects) + IPC_MESSAGE_HANDLER(ViewMsg_SetViewportIntersection, + OnSetViewportIntersection) IPC_MESSAGE_HANDLER(ViewMsg_WaitForNextFrameForTests, OnWaitNextFrameForTests) IPC_MESSAGE_HANDLER(InputMsg_RequestCompositionUpdate, @@ -1652,6 +1654,15 @@ window_screen_rect_ = window_screen_rect; } +void RenderWidget::OnSetViewportIntersection( + const gfx::Rect& viewport_intersection) { + if (GetWebWidget() && GetWebWidget()->isWebFrameWidget()) { + DCHECK(popup_type_ == WebPopupType::WebPopupTypeNone); + static_cast<WebFrameWidget*>(GetWebWidget()) + ->setRemoteViewportIntersection(viewport_intersection); + } +} + void RenderWidget::OnHandleCompositorProto(const std::vector<uint8_t>& proto) { if (compositor_) compositor_->OnHandleCompositorProto(proto);
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 745c913..e6390ede 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -510,6 +510,7 @@ void OnUpdateScreenRects(const gfx::Rect& view_screen_rect, const gfx::Rect& window_screen_rect); void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect); + void OnSetViewportIntersection(const gfx::Rect& viewport_intersection); void OnHandleCompositorProto(const std::vector<uint8_t>& proto); // Real data that is dragged is not included at DragEnter time. void OnDragTargetDragEnter(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 4a6a2b6..8e5bce0 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -249,7 +249,6 @@ "//media/capture", "//media/capture/mojo:image_capture", "//mojo/edk/system", - "//mojo/edk/test:test_support", "//net:test_support", "//services/service_manager/public/cpp", "//skia", @@ -718,7 +717,6 @@ "//media/audio:test_support", "//media/base:test_support", "//mojo/edk/system", - "//mojo/edk/test:test_support", "//mojo/public/cpp/bindings", "//mojo/public/js", "//net:test_support", @@ -1129,6 +1127,7 @@ "../browser/loader/test_url_loader_client.h", "../browser/loader/throttling_resource_handler_unittest.cc", "../browser/loader/upload_data_stream_builder_unittest.cc", + "../browser/loader/upload_progress_tracker_unittest.cc", "../browser/loader/url_loader_factory_impl_unittest.cc", "../browser/mach_broker_mac_unittest.cc", "../browser/media/audible_metrics_unittest.cc", @@ -1451,7 +1450,7 @@ "//media/capture/mojo:capture_types", "//media/midi:midi", "//media/midi:mojo", - "//mojo/edk/test:test_support", + "//mojo/edk/system", "//mojo/public/cpp/bindings", "//net:extras", "//net:test_support",
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 48e8177..9dba4daf 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -1111,6 +1111,7 @@ 'fyi_only': True, # Run this on the optional tryservers. 'run_on_optional': True, + 'os_types': ['win', 'linux'], }, ], },
diff --git a/content/test/run_all_unittests.cc b/content/test/run_all_unittests.cc index 7efb88b..02d678c2 100644 --- a/content/test/run_all_unittests.cc +++ b/content/test/run_all_unittests.cc
@@ -9,16 +9,15 @@ #include "build/build_config.h" #include "content/public/test/unittest_test_suite.h" #include "content/test/content_test_suite.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" int main(int argc, char** argv) { content::UnitTestTestSuite test_suite( new content::ContentTestSuite(argc, argv)); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - std::unique_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support; - ipc_support.reset( - new mojo::edk::test::ScopedIPCSupport(test_io_thread.task_runner())); - + mojo::edk::ScopedIPCSupport ipc_support( + test_io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); return base::LaunchUnitTests( argc, argv, base::Bind(&content::UnitTestTestSuite::Run, base::Unretained(&test_suite)));
diff --git a/device/vr/vr_service_impl.cc b/device/vr/vr_service_impl.cc index f8003706..9d0fb36 100644 --- a/device/vr/vr_service_impl.cc +++ b/device/vr/vr_service_impl.cc
@@ -17,6 +17,10 @@ VRServiceImpl::VRServiceImpl() : listening_for_activate_(false) {} VRServiceImpl::~VRServiceImpl() { + // Destroy VRDisplay before calling RemoveService below. RemoveService might + // implicitly trigger destory VRDevice which VRDisplay needs to access in its + // dtor. + displays_.clear(); VRDeviceManager::GetInstance()->RemoveService(this); }
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index af2ed165..bf50a92 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -210,7 +210,6 @@ "//extensions/renderer:unit_tests", "//extensions/shell:unit_tests", "//extensions/utility:unit_tests", - "//mojo/edk/test:test_support", "//ui/gl:test_support", ]
diff --git a/extensions/test/DEPS b/extensions/test/DEPS index 2e42e816..186feed 100644 --- a/extensions/test/DEPS +++ b/extensions/test/DEPS
@@ -1,5 +1,4 @@ include_rules = [ "+content/public", - "+mojo/edk/test", "+ui/gl", ]
diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc index 96480f6..8b72ef8 100644 --- a/extensions/test/extensions_unittests_main.cc +++ b/extensions/test/extensions_unittests_main.cc
@@ -16,7 +16,6 @@ #include "extensions/common/constants.h" #include "extensions/common/extension_paths.h" #include "extensions/test/test_extensions_client.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gl/test/gl_surface_test_support.h" #include "url/url_util.h" @@ -100,10 +99,6 @@ int main(int argc, char** argv) { content::UnitTestTestSuite test_suite(new ExtensionsTestSuite(argc, argv)); - - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); - return base::LaunchUnitTests(argc, argv, base::Bind(&content::UnitTestTestSuite::Run,
diff --git a/google_apis/gcm/engine/connection_event_tracker.cc b/google_apis/gcm/engine/connection_event_tracker.cc index 0ebd798..50a5ecdcc 100644 --- a/google_apis/gcm/engine/connection_event_tracker.cc +++ b/google_apis/gcm/engine/connection_event_tracker.cc
@@ -66,8 +66,8 @@ void ConnectionEventTracker::ConnectionLoginFailed() { // A login failure would have originally been marked as a successful // connection, so now that it failed, that needs to be updated. - // TODO(harkness): Add back DCHECK which was removed. See - // https://crbug.com/673706. + DCHECK_EQ(current_event_.type(), + mcs_proto::ClientEvent::SUCCESSFUL_CONNECTION); current_event_.set_type(mcs_proto::ClientEvent::FAILED_CONNECTION); current_event_.clear_time_connection_established_ms();
diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc index 153e5bc..2d459f2 100644 --- a/google_apis/gcm/engine/connection_factory_impl.cc +++ b/google_apis/gcm/engine/connection_factory_impl.cc
@@ -66,7 +66,7 @@ connecting_(false), waiting_for_backoff_(false), waiting_for_network_online_(false), - logging_in_(false), + handshake_in_progress_(false), recorder_(recorder), listener_(NULL), weak_ptr_factory_(this) { @@ -131,7 +131,7 @@ void ConnectionFactoryImpl::ConnectWithBackoff() { // If a canary managed to connect while a backoff expiration was pending, // just cleanup the internal state. - if (connecting_ || logging_in_ || IsEndpointReachable()) { + if (connecting_ || handshake_in_progress_ || IsEndpointReachable()) { waiting_for_backoff_ = false; return; } @@ -167,8 +167,8 @@ std::string ConnectionFactoryImpl::GetConnectionStateString() const { if (IsEndpointReachable()) return "CONNECTED"; - if (logging_in_) - return "LOGGING IN"; + if (handshake_in_progress_) + return "HANDSHAKE IN PROGRESS"; if (connecting_) return "CONNECTING"; if (waiting_for_backoff_) @@ -209,7 +209,7 @@ // connection. } - if (logging_in_) + if (reason == LOGIN_FAILURE) event_tracker_.ConnectionLoginFailed(); event_tracker_.EndConnectionAttempt(); @@ -233,9 +233,9 @@ // effect if we're already in the process of connecting. ConnectImpl(); return; - } else if (logging_in_) { - // Failures prior to login completion just reuse the existing backoff entry. - logging_in_ = false; + } else if (handshake_in_progress_) { + // Failures prior to handshake completion reuse the existing backoff entry. + handshake_in_progress_ = false; backoff_entry_->InformOfRequest(false); } else if (reason == LOGIN_FAILURE || ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { @@ -412,7 +412,7 @@ last_successful_endpoint_ = next_endpoint_; next_endpoint_ = 0; connecting_ = false; - logging_in_ = true; + handshake_in_progress_ = true; DVLOG(1) << "MCS endpoint socket connection success, starting login."; InitHandler(); } @@ -434,7 +434,7 @@ last_login_time_ = NowTicks(); previous_backoff_.swap(backoff_entry_); backoff_entry_->Reset(); - logging_in_ = false; + handshake_in_progress_ = false; event_tracker_.ConnectionAttemptSucceeded();
diff --git a/google_apis/gcm/engine/connection_factory_impl.h b/google_apis/gcm/engine/connection_factory_impl.h index 1af8aac0..14836ef 100644 --- a/google_apis/gcm/engine/connection_factory_impl.h +++ b/google_apis/gcm/engine/connection_factory_impl.h
@@ -184,10 +184,10 @@ // client is informed of a valid connection type. bool waiting_for_network_online_; - // Whether login successfully completed after the connection was established. - // If a connection reset happens while attempting to log in, the current - // backoff entry is reused (after incrementing with a new failure). - bool logging_in_; + // Whether handshake is in progress after the connection was established. If + // a connection reset happens while attempting to complete the handshake, the + // current backoff entry is reused (after incrementing with a new failure). + bool handshake_in_progress_; // The time of the last login completion. Used for calculating whether to // restore a previous backoff entry and for measuring uptime.
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc index 6c28e708..047f408 100644 --- a/headless/app/headless_shell.cc +++ b/headless/app/headless_shell.cc
@@ -75,6 +75,8 @@ HeadlessBrowserContext::Builder context_builder = browser_->CreateBrowserContextBuilder(); + // TODO(eseckler): These switches should also affect BrowserContexts that + // are created via DevTools later. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDeterministicFetch)) { deterministic_dispatcher_.reset( @@ -98,6 +100,7 @@ })); } browser_context_ = context_builder.Build(); + browser_->SetDefaultBrowserContext(browser_context_); HeadlessWebContents::Builder builder( browser_context_->CreateWebContentsBuilder());
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc index 876be95..93d6918 100644 --- a/headless/lib/browser/headless_browser_impl.cc +++ b/headless/lib/browser/headless_browser_impl.cc
@@ -54,6 +54,7 @@ : on_start_callback_(on_start_callback), options_(std::move(options)), browser_main_parts_(nullptr), + default_browser_context_(nullptr), weak_ptr_factory_(this) {} HeadlessBrowserImpl::~HeadlessBrowserImpl() {} @@ -158,6 +159,19 @@ auto it = browser_contexts_.find(browser_context->Id()); DCHECK(it != browser_contexts_.end()); browser_contexts_.erase(it); + if (default_browser_context_ == browser_context) + SetDefaultBrowserContext(nullptr); +} + +void HeadlessBrowserImpl::SetDefaultBrowserContext( + HeadlessBrowserContext* browser_context) { + DCHECK(!browser_context || + this == HeadlessBrowserContextImpl::From(browser_context)->browser()); + default_browser_context_ = browser_context; +} + +HeadlessBrowserContext* HeadlessBrowserImpl::GetDefaultBrowserContext() { + return default_browser_context_; } base::WeakPtr<HeadlessBrowserImpl> HeadlessBrowserImpl::GetWeakPtr() {
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h index 74a4b6c..f37dff1d 100644 --- a/headless/lib/browser/headless_browser_impl.h +++ b/headless/lib/browser/headless_browser_impl.h
@@ -51,6 +51,9 @@ const std::string& devtools_agent_host_id) override; HeadlessBrowserContext* GetBrowserContextForId( const std::string& id) override; + void SetDefaultBrowserContext( + HeadlessBrowserContext* browser_context) override; + HeadlessBrowserContext* GetDefaultBrowserContext() override; void set_browser_main_parts(HeadlessBrowserMainParts* browser_main_parts); HeadlessBrowserMainParts* browser_main_parts() const; @@ -82,6 +85,7 @@ std::unordered_map<std::string, std::unique_ptr<HeadlessBrowserContextImpl>> browser_contexts_; + HeadlessBrowserContext* default_browser_context_; // Not owned. base::WeakPtrFactory<HeadlessBrowserImpl> weak_ptr_factory_;
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.cc b/headless/lib/browser/headless_devtools_manager_delegate.cc index 0c82f334a..4144038 100644 --- a/headless/lib/browser/headless_devtools_manager_delegate.cc +++ b/headless/lib/browser/headless_devtools_manager_delegate.cc
@@ -20,9 +20,57 @@ namespace headless { +namespace { +const char kIdParam[] = "id"; +const char kResultParam[] = "result"; +const char kErrorParam[] = "error"; +const char kErrorCodeParam[] = "code"; +const char kErrorMessageParam[] = "message"; + +// JSON RPC 2.0 spec: http://www.jsonrpc.org/specification#error_object +enum Error { + kErrorInvalidParam = -32602, + kErrorServerError = -32000 +}; + +std::unique_ptr<base::DictionaryValue> CreateSuccessResponse( + int command_id, + std::unique_ptr<base::Value> result) { + if (!result) + result.reset(new base::DictionaryValue()); + + std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue()); + response->SetInteger(kIdParam, command_id); + response->Set(kResultParam, std::move(result)); + return response; +} + +std::unique_ptr<base::DictionaryValue> CreateErrorResponse( + int command_id, + int error_code, + const std::string& error_message) { + std::unique_ptr<base::DictionaryValue> error_object( + new base::DictionaryValue()); + error_object->SetInteger(kErrorCodeParam, error_code); + error_object->SetString(kErrorMessageParam, error_message); + + std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue()); + response->Set(kErrorParam, std::move(error_object)); + return response; +} + +std::unique_ptr<base::DictionaryValue> CreateInvalidParamResponse( + int command_id, + const std::string& param) { + return CreateErrorResponse( + command_id, kErrorInvalidParam, + base::StringPrintf("Missing or invalid '%s' parameter", param.c_str())); +} +} // namespace + HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate( base::WeakPtr<HeadlessBrowserImpl> browser) - : browser_(std::move(browser)), default_browser_context_(nullptr) { + : browser_(std::move(browser)) { command_map_["Target.createTarget"] = &HeadlessDevToolsManagerDelegate::CreateTarget; command_map_["Target.closeTarget"] = @@ -55,19 +103,15 @@ if (find_it == command_map_.end()) return nullptr; CommandMemberFnPtr command_fn_ptr = find_it->second; - std::unique_ptr<base::Value> cmd_result(((this)->*command_fn_ptr)(params)); - if (!cmd_result) - return nullptr; - - std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); - result->SetInteger("id", id); - result->Set("result", std::move(cmd_result)); - return result.release(); + std::unique_ptr<base::DictionaryValue> cmd_result( + ((this)->*command_fn_ptr)(id, params)); + return cmd_result.release(); } std::string HeadlessDevToolsManagerDelegate::GetDiscoveryPageHTML() { - return ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE).as_string(); + return ResourceBundle::GetSharedInstance() + .GetRawDataResource(IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE) + .as_string(); } std::string HeadlessDevToolsManagerDelegate::GetFrontendResource( @@ -75,7 +119,9 @@ return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); } -std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CreateTarget( +std::unique_ptr<base::DictionaryValue> +HeadlessDevToolsManagerDelegate::CreateTarget( + int command_id, const base::DictionaryValue* params) { std::string url; std::string browser_context_id; @@ -86,15 +132,20 @@ params->GetInteger("width", &width); params->GetInteger("height", &height); - // TODO(alexclarke): Should we fail when user passes incorrect id? HeadlessBrowserContext* context = browser_->GetBrowserContextForId(browser_context_id); - if (!context) { - if (!default_browser_context_) { - default_browser_context_ = - browser_->CreateBrowserContextBuilder().Build(); + if (!browser_context_id.empty()) { + context = browser_->GetBrowserContextForId(browser_context_id); + if (!context) + return CreateInvalidParamResponse(command_id, "browserContextId"); + } else { + context = browser_->GetDefaultBrowserContext(); + if (!context) { + return CreateErrorResponse(command_id, kErrorServerError, + "You specified no |browserContextId|, but " + "there is no default browser context set on " + "HeadlessBrowser"); } - context = default_browser_context_; } HeadlessWebContentsImpl* web_contents_impl = @@ -103,18 +154,21 @@ .SetWindowSize(gfx::Size(width, height)) .Build()); - return target::CreateTargetResult::Builder() - .SetTargetId(web_contents_impl->GetDevToolsAgentHostId()) - .Build() - ->Serialize(); + std::unique_ptr<base::Value> result( + target::CreateTargetResult::Builder() + .SetTargetId(web_contents_impl->GetDevToolsAgentHostId()) + .Build() + ->Serialize()); + return CreateSuccessResponse(command_id, std::move(result)); } -std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CloseTarget( +std::unique_ptr<base::DictionaryValue> +HeadlessDevToolsManagerDelegate::CloseTarget( + int command_id, const base::DictionaryValue* params) { std::string target_id; - if (!params->GetString("targetId", &target_id)) { - return nullptr; - } + if (!params->GetString("targetId", &target_id)) + return CreateInvalidParamResponse(command_id, "targetId"); HeadlessWebContents* web_contents = browser_->GetWebContentsForDevToolsAgentHostId(target_id); bool success = false; @@ -122,46 +176,51 @@ web_contents->Close(); success = true; } - return target::CloseTargetResult::Builder() - .SetSuccess(success) - .Build() - ->Serialize(); + std::unique_ptr<base::Value> result(target::CloseTargetResult::Builder() + .SetSuccess(success) + .Build() + ->Serialize()); + return CreateSuccessResponse(command_id, std::move(result)); } -std::unique_ptr<base::Value> +std::unique_ptr<base::DictionaryValue> HeadlessDevToolsManagerDelegate::CreateBrowserContext( + int command_id, const base::DictionaryValue* params) { HeadlessBrowserContext* browser_context = browser_->CreateBrowserContextBuilder().Build(); - std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); - return target::CreateBrowserContextResult::Builder() - .SetBrowserContextId(browser_context->Id()) - .Build() - ->Serialize(); + std::unique_ptr<base::Value> result( + target::CreateBrowserContextResult::Builder() + .SetBrowserContextId(browser_context->Id()) + .Build() + ->Serialize()); + return CreateSuccessResponse(command_id, std::move(result)); } -std::unique_ptr<base::Value> +std::unique_ptr<base::DictionaryValue> HeadlessDevToolsManagerDelegate::DisposeBrowserContext( + int command_id, const base::DictionaryValue* params) { std::string browser_context_id; - if (!params->GetString("browserContextId", &browser_context_id)) { - return nullptr; - } + if (!params->GetString("browserContextId", &browser_context_id)) + return CreateInvalidParamResponse(command_id, "browserContextId"); HeadlessBrowserContext* context = browser_->GetBrowserContextForId(browser_context_id); bool success = false; - if (context && context != default_browser_context_ && + if (context && context != browser_->GetDefaultBrowserContext() && context->GetAllWebContents().empty()) { success = true; context->Close(); } - return target::DisposeBrowserContextResult::Builder() - .SetSuccess(success) - .Build() - ->Serialize(); + std::unique_ptr<base::Value> result( + target::DisposeBrowserContextResult::Builder() + .SetSuccess(success) + .Build() + ->Serialize()); + return CreateSuccessResponse(command_id, std::move(result)); } } // namespace headless
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.h b/headless/lib/browser/headless_devtools_manager_delegate.h index 3b800d53..c891e82 100644 --- a/headless/lib/browser/headless_devtools_manager_delegate.h +++ b/headless/lib/browser/headless_devtools_manager_delegate.h
@@ -16,7 +16,6 @@ namespace headless { class HeadlessBrowserImpl; -class HeadlessBrowserContext; class HeadlessDevToolsManagerDelegate : public content::DevToolsManagerDelegate { @@ -32,22 +31,26 @@ std::string GetFrontendResource(const std::string& path) override; private: - std::unique_ptr<base::Value> CreateTarget( + std::unique_ptr<base::DictionaryValue> CreateTarget( + int command_id, const base::DictionaryValue* params); - std::unique_ptr<base::Value> CloseTarget(const base::DictionaryValue* params); - std::unique_ptr<base::Value> CreateBrowserContext( + std::unique_ptr<base::DictionaryValue> CloseTarget( + int command_id, const base::DictionaryValue* params); - std::unique_ptr<base::Value> DisposeBrowserContext( + std::unique_ptr<base::DictionaryValue> CreateBrowserContext( + int command_id, + const base::DictionaryValue* params); + std::unique_ptr<base::DictionaryValue> DisposeBrowserContext( + int command_id, const base::DictionaryValue* params); base::WeakPtr<HeadlessBrowserImpl> browser_; - using CommandMemberFnPtr = std::unique_ptr<base::Value> ( - HeadlessDevToolsManagerDelegate::*)(const base::DictionaryValue* params); + using CommandMemberFnPtr = std::unique_ptr<base::DictionaryValue> ( + HeadlessDevToolsManagerDelegate::*)(int command_id, + const base::DictionaryValue* params); std::map<std::string, CommandMemberFnPtr> command_map_; - - HeadlessBrowserContext* default_browser_context_; }; } // namespace headless
diff --git a/headless/public/headless_browser.h b/headless/public/headless_browser.h index 021e910..c3043f00 100644 --- a/headless/public/headless_browser.h +++ b/headless/public/headless_browser.h
@@ -56,6 +56,12 @@ virtual HeadlessBrowserContext* GetBrowserContextForId( const std::string& id) = 0; + // Allows setting and getting the browser context that DevTools will create + // new targets in by default. + virtual void SetDefaultBrowserContext( + HeadlessBrowserContext* browser_context) = 0; + virtual HeadlessBrowserContext* GetDefaultBrowserContext() = 0; + // Returns a task runner for submitting work to the browser file thread. virtual scoped_refptr<base::SingleThreadTaskRunner> BrowserFileThread() const = 0;
diff --git a/headless/test/headless_browser_test.cc b/headless/test/headless_browser_test.cc index 3e1f0f2..53e2db2 100644 --- a/headless/test/headless_browser_test.cc +++ b/headless/test/headless_browser_test.cc
@@ -184,7 +184,8 @@ } HeadlessAsyncDevTooledBrowserTest::HeadlessAsyncDevTooledBrowserTest() - : web_contents_(nullptr), + : browser_context_(nullptr), + web_contents_(nullptr), devtools_client_(HeadlessDevToolsClient::Create()), render_process_exited_(false) {} @@ -209,6 +210,7 @@ void HeadlessAsyncDevTooledBrowserTest::RunTest() { browser_context_ = browser()->CreateBrowserContextBuilder().Build(); + browser()->SetDefaultBrowserContext(browser_context_); web_contents_ = browser_context_->CreateWebContentsBuilder().Build(); web_contents_->AddObserver(this);
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 5b0bda09..21abdeef5 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -135,6 +135,7 @@ #import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h" #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h" +#import "ios/third_party/material_roboto_font_loader_ios/src/src/MDCTypographyAdditions/MDFRobotoFontLoader+MDCTypographyAdditions.h" #include "ios/web/net/request_tracker_factory_impl.h" #include "ios/web/net/request_tracker_impl.h" #include "ios/web/net/web_http_protocol_handler_delegate.h" @@ -230,12 +231,6 @@ } // namespace -// TODO(crbug.com/673904): Remove once MDFRobotoFontLoader declares it directly. -// MDFRobotoFontLoader implicitly implements MDCTypographyFontLoading but can't -// declare it until MDC is public. -@interface MDFRobotoFontLoader (MDCTypography)<MDCTypographyFontLoading> -@end - @interface MainController ()<BrowserStateStorageSwitching, BrowsingDataRemovalControllerDelegate, PrefObserverDelegate,
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 0ca0279..0ca1db6 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1203,6 +1203,9 @@ <message name="IDS_IOS_SETTING_ON" desc="Generic status label displayed in Settings to show that a setting is currently turned on. [Length: 5em] [iOS only]"> On </message> + <message name="IDS_IOS_TOGGLE_SETTING_SWITCH_ACCESSIBILITY_HINT" desc="Action hint for any switch in settings. This is spoken by VoiceOver. [iOS only]"> + Double tap to toggle setting + </message> <message name="IDS_IOS_SHARE_EMAIL_COMPLETE" desc="Message shown when email share has been sent. [Length: Unknown. Keep it short.] [iOS only]"> Mail sent. </message>
diff --git a/ios/chrome/browser/payments/OWNERS b/ios/chrome/browser/payments/OWNERS index ca512d20e..4cfb56d 100644 --- a/ios/chrome/browser/payments/OWNERS +++ b/ios/chrome/browser/payments/OWNERS
@@ -1 +1,2 @@ -jdonnelly@chromium.org +lpromero@chromium.org +mahmadi@chromium.org
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 113c3f26..3509d68 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -3914,7 +3914,6 @@ switch (command) { case IDC_BACK: - // TODO(crbug.com/677160): Remove |canGoBack| check. if ([_model currentTab].canGoBack) { [[_model currentTab] goBack]; } @@ -3958,7 +3957,6 @@ [self searchFindInPage]; break; case IDC_FORWARD: - // TODO(crbug.com/677160): Remove |canGoForward| check. if ([_model currentTab].canGoForward) { [[_model currentTab] goForward]; }
diff --git a/ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.mm b/ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.mm index cd6f56b8..b427959b 100644 --- a/ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.mm +++ b/ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.mm
@@ -5,8 +5,10 @@ #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#include "ios/chrome/grit/ios_strings.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h" +#include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -31,7 +33,6 @@ if (self) { self.cellClass = [CollectionViewSwitchCell class]; self.enabled = YES; - self.accessibilityTraits |= UIAccessibilityTraitButton; } return self; } @@ -74,6 +75,8 @@ _switchView = [[UISwitch alloc] initWithFrame:CGRectZero]; _switchView.translatesAutoresizingMaskIntoConstraints = NO; _switchView.onTintColor = [[MDCPalette cr_bluePalette] tint500]; + _switchView.accessibilityHint = l10n_util::GetNSString( + IDS_IOS_TOGGLE_SETTING_SWITCH_ACCESSIBILITY_HINT); [self.contentView addSubview:_switchView]; // Set up the constraints. @@ -138,7 +141,11 @@ } - (NSString*)accessibilityHint { - return _switchView.accessibilityHint; + if (_switchView.isEnabled) { + return _switchView.accessibilityHint; + } else { + return @""; + } } - (NSString*)accessibilityLabel { @@ -146,7 +153,11 @@ } - (NSString*)accessibilityValue { - return _switchView.accessibilityValue; + if (_switchView.on) { + return l10n_util::GetNSString(IDS_IOS_SETTING_ON); + } else { + return l10n_util::GetNSString(IDS_IOS_SETTING_OFF); + } } @end
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h index 4a2da9834..c8c9779 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h
@@ -30,7 +30,7 @@ // Update the match type icon with the supplied image ID and adjust its position // based on the current size of the row. -- (void)updateLeftImage:(int)imageID; +- (void)updateLeadingImage:(int)imageID; @end
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm index 71f2f21..9d066dc 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm
@@ -17,6 +17,7 @@ const CGFloat kLeadingPaddingIpad = 164; const CGFloat kLeadingPaddingIpadCompact = 71; const CGFloat kAppendButtonTrailingMargin = 4; +const CGFloat kAppendButtonSize = 48.0; } @interface OmniboxPopupMaterialRow () { @@ -78,7 +79,7 @@ [self updatePhysicalWebImage]; [self addSubview:_physicalWebButton]; - // Left icon is only displayed on iPad. + // Leading icon is only displayed on iPad. if (IsIPadIdiom()) { _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; _imageView.userInteractionEnabled = NO; @@ -110,19 +111,16 @@ kImageDimensionLength); _imageView.frame = LayoutRectGetRect(imageViewLayout); - CGFloat appendButtonDimensionLength = CGRectGetHeight(self.bounds); - DCHECK_GT(appendButtonDimensionLength, 40); - LayoutRect rightAccessoryLayout = - LayoutRectMake(CGRectGetWidth(self.bounds) - appendButtonDimensionLength - - kAppendButtonTrailingMargin, - CGRectGetWidth(self.bounds), - floor((_rowHeight - appendButtonDimensionLength) / 2), - appendButtonDimensionLength, appendButtonDimensionLength); - _appendButton.frame = LayoutRectGetRect(rightAccessoryLayout); - _physicalWebButton.frame = LayoutRectGetRect(rightAccessoryLayout); + LayoutRect trailingAccessoryLayout = LayoutRectMake( + CGRectGetWidth(self.bounds) - kAppendButtonSize - + kAppendButtonTrailingMargin, + CGRectGetWidth(self.bounds), floor((_rowHeight - kAppendButtonSize) / 2), + kAppendButtonSize, kAppendButtonSize); + _appendButton.frame = LayoutRectGetRect(trailingAccessoryLayout); + _physicalWebButton.frame = LayoutRectGetRect(trailingAccessoryLayout); } -- (void)updateLeftImage:(int)imageID { +- (void)updateLeadingImage:(int)imageID { _imageView.image = NativeImage(imageID); // Adjust the vertical position based on the current size of the row.
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm index f408e9c2..732a94f 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm
@@ -370,11 +370,12 @@ } [textLabel setNeedsDisplay]; - // The left image (e.g. magnifying glass, star, clock) is only shown on iPad. + // The leading image (e.g. magnifying glass, star, clock) is only shown on + // iPad. if (IsIPadIdiom()) { int imageId = GetIconForAutocompleteMatchType( match.type, _popupView->IsStarredMatch(match), _incognito); - [row updateLeftImage:imageId]; + [row updateLeadingImage:imageId]; } // Show append button for search history/search suggestions/voice search as
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 35ebc135..0d97812 100644 --- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
@@ -186,8 +186,7 @@ if (authenticatedIdentity) { title = [authenticatedIdentity userFullName]; if (!title) { - // TODO(crbug.com/656994): Figure how to handle unnamed account. - title = @"Unnamed account"; + title = [authenticatedIdentity userEmail]; } } self.title = title;
diff --git a/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm b/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm index e3d070c..d8191ee5 100644 --- a/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm +++ b/ios/chrome/browser/ui/settings/cells/sync_switch_item.mm
@@ -5,8 +5,10 @@ #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#include "ios/chrome/grit/ios_strings.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h" +#include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -38,7 +40,6 @@ if (self) { self.cellClass = [SyncSwitchCell class]; self.enabled = YES; - self.accessibilityTraits |= UIAccessibilityTraitButton; } return self; } @@ -96,6 +97,8 @@ _switchView = [[UISwitch alloc] initWithFrame:CGRectZero]; _switchView.translatesAutoresizingMaskIntoConstraints = NO; _switchView.onTintColor = [[MDCPalette cr_bluePalette] tint500]; + _switchView.accessibilityHint = l10n_util::GetNSString( + IDS_IOS_TOGGLE_SETTING_SWITCH_ACCESSIBILITY_HINT); [self.contentView addSubview:_switchView]; [self setConstraints]; @@ -179,7 +182,11 @@ } - (NSString*)accessibilityHint { - return _switchView.accessibilityHint; + if (_switchView.isEnabled) { + return _switchView.accessibilityHint; + } else { + return @""; + } } - (NSString*)accessibilityLabel { @@ -191,7 +198,11 @@ } - (NSString*)accessibilityValue { - return _switchView.accessibilityValue; + if (_switchView.on) { + return l10n_util::GetNSString(IDS_IOS_SETTING_ON); + } else { + return l10n_util::GetNSString(IDS_IOS_SETTING_OFF); + } } @end
diff --git a/ios/chrome/share_extension/share_extension_view.mm b/ios/chrome/share_extension/share_extension_view.mm index 1e0f73c8..a072574 100644 --- a/ios/chrome/share_extension/share_extension_view.mm +++ b/ios/chrome/share_extension/share_extension_view.mm
@@ -60,9 +60,10 @@ // Keep strong references of the views that need to be updated. @property(nonatomic, strong) UILabel* titleLabel; @property(nonatomic, strong) UILabel* URLLabel; +@property(nonatomic, strong) UIView* titleURLContainer; @property(nonatomic, strong) UIButton* readingListButton; @property(nonatomic, strong) UIImageView* screenshotView; -@property(nonatomic, strong) UIStackView* itemStack; +@property(nonatomic, strong) UIView* itemView; // View creation helpers. // Returns a view containing the shared items (title, URL, screenshot). This @@ -99,9 +100,10 @@ @synthesize titleLabel = _titleLabel; @synthesize URLLabel = _URLLabel; +@synthesize titleURLContainer = _titleURLContainer; @synthesize readingListButton = _readingListButton; @synthesize screenshotView = _screenshotView; -@synthesize itemStack = _itemStack; +@synthesize itemView = _itemView; #pragma mark - Lifecycle @@ -179,15 +181,17 @@ // Screenshot view. Image will be filled by |setScreenshot:| when available. _screenshotView = [[UIImageView alloc] initWithFrame:CGRectZero]; - [_screenshotView.widthAnchor - constraintLessThanOrEqualToConstant:kScreenshotSize] - .active = YES; + [_screenshotView setTranslatesAutoresizingMaskIntoConstraints:NO]; + NSLayoutConstraint* imageWidthConstraint = + [_screenshotView.widthAnchor constraintEqualToConstant:0]; + imageWidthConstraint.priority = UILayoutPriorityDefaultHigh; + imageWidthConstraint.active = YES; + [_screenshotView.heightAnchor constraintEqualToAnchor:_screenshotView.widthAnchor] .active = YES; [_screenshotView setContentMode:UIViewContentModeScaleAspectFill]; [_screenshotView setClipsToBounds:YES]; - [_screenshotView setHidden:YES]; // |_screenshotView| should take as much space as needed. Lower compression // resistance of the other elements. @@ -203,52 +207,58 @@ setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; - UIStackView* titleURLStack = [[UIStackView alloc] - initWithArrangedSubviews:@[ _titleLabel, _URLLabel ]]; - [titleURLStack setAxis:UILayoutConstraintAxisVertical]; + _titleURLContainer = [[UIView alloc] initWithFrame:CGRectZero]; + [_titleURLContainer setTranslatesAutoresizingMaskIntoConstraints:NO]; - UIView* titleURLContainer = [[UIView alloc] initWithFrame:CGRectZero]; - [titleURLContainer setTranslatesAutoresizingMaskIntoConstraints:NO]; - [titleURLContainer addSubview:titleURLStack]; - [[titleURLStack topAnchor] - constraintEqualToAnchor:[titleURLContainer topAnchor] - constant:kShareExtensionPadding] - .active = YES; - [[titleURLStack bottomAnchor] - constraintEqualToAnchor:[titleURLContainer bottomAnchor] - constant:-kShareExtensionPadding] - .active = YES; + [_titleURLContainer addSubview:_titleLabel]; + [_titleURLContainer addSubview:_URLLabel]; - [titleURLStack.centerYAnchor - constraintEqualToAnchor:titleURLContainer.centerYAnchor] - .active = YES; - [titleURLStack.centerXAnchor - constraintEqualToAnchor:titleURLContainer.centerXAnchor] - .active = YES; - [titleURLStack.widthAnchor - constraintEqualToAnchor:titleURLContainer.widthAnchor] - .active = YES; - [titleURLStack - setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh - forAxis:UILayoutConstraintAxisVertical]; + _itemView = [[UIView alloc] init]; + [_itemView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [_itemView addSubview:_titleURLContainer]; + [_itemView addSubview:_screenshotView]; - _itemStack = - [[UIStackView alloc] initWithArrangedSubviews:@[ titleURLContainer ]]; - [_itemStack setAxis:UILayoutConstraintAxisHorizontal]; - [_itemStack setLayoutMargins:UIEdgeInsetsMake(kShareExtensionPadding, - kShareExtensionPadding, - kShareExtensionPadding, - kShareExtensionPadding)]; - [_itemStack setLayoutMarginsRelativeArrangement:YES]; - [_itemStack setSpacing:kShareExtensionPadding]; + [NSLayoutConstraint activateConstraints:@[ + [_titleLabel.topAnchor + constraintEqualToAnchor:_titleURLContainer.topAnchor], + [_URLLabel.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor], + [_URLLabel.bottomAnchor + constraintEqualToAnchor:_titleURLContainer.bottomAnchor], + [_titleLabel.trailingAnchor + constraintEqualToAnchor:_titleURLContainer.trailingAnchor], + [_URLLabel.trailingAnchor + constraintEqualToAnchor:_titleURLContainer.trailingAnchor], + [_titleLabel.leadingAnchor + constraintEqualToAnchor:_titleURLContainer.leadingAnchor], + [_URLLabel.leadingAnchor + constraintEqualToAnchor:_titleURLContainer.leadingAnchor], + [_titleURLContainer.centerYAnchor + constraintEqualToAnchor:_itemView.centerYAnchor], + [_itemView.heightAnchor + constraintGreaterThanOrEqualToAnchor:_titleURLContainer.heightAnchor + multiplier:1 + constant:2 * kShareExtensionPadding], + [_titleURLContainer.leadingAnchor + constraintEqualToAnchor:_itemView.leadingAnchor + constant:kShareExtensionPadding], + [_screenshotView.trailingAnchor + constraintEqualToAnchor:_itemView.trailingAnchor + constant:-kShareExtensionPadding], + [_itemView.heightAnchor + constraintGreaterThanOrEqualToAnchor:_screenshotView.heightAnchor + multiplier:1 + constant:2 * kShareExtensionPadding], + [_screenshotView.centerYAnchor + constraintEqualToAnchor:_itemView.centerYAnchor], + ]]; - [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; - [_URLLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; - [_screenshotView setTranslatesAutoresizingMaskIntoConstraints:NO]; - [titleURLStack setTranslatesAutoresizingMaskIntoConstraints:NO]; - [_itemStack setTranslatesAutoresizingMaskIntoConstraints:NO]; + NSLayoutConstraint* titleURLScreenshotConstraint = + [_titleURLContainer.trailingAnchor + constraintEqualToAnchor:_screenshotView.leadingAnchor]; + titleURLScreenshotConstraint.priority = UILayoutPriorityDefaultHigh; + titleURLScreenshotConstraint.active = YES; - return _itemStack; + return _itemView; } - (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect { @@ -414,9 +424,13 @@ } - (void)setScreenshot:(UIImage*)screenshot { - [[self screenshotView] setHidden:NO]; + [self.screenshotView.widthAnchor constraintEqualToConstant:kScreenshotSize] + .active = YES; + [self.titleURLContainer.trailingAnchor + constraintEqualToAnchor:self.screenshotView.leadingAnchor + constant:-kShareExtensionPadding] + .active = YES; [[self screenshotView] setImage:screenshot]; - [[self itemStack] addArrangedSubview:[self screenshotView]]; } @end
diff --git a/ios/clean/chrome/browser/ui/presenters/BUILD.gn b/ios/clean/chrome/browser/ui/presenters/BUILD.gn index 99e39183..3a89a33 100644 --- a/ios/clean/chrome/browser/ui/presenters/BUILD.gn +++ b/ios/clean/chrome/browser/ui/presenters/BUILD.gn
@@ -10,4 +10,8 @@ ] configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//ios/clean/chrome/browser/ui/commands", + ] }
diff --git a/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.h b/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.h index 402c92a7..d4d1347 100644 --- a/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.h +++ b/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.h
@@ -11,14 +11,21 @@ #import <UIKit/UIKit.h> +@protocol ToolbarCommands; + // A presentation controller for presenting a "menu" interface: a (usually) // rectangular presentation that covers part of the window, and which doesn't // obscure the presenting view. The presenting view remains in the view -// hierarchy. If the presenting view controller confroms to the -// MenuPresentationDelegate protocol, that protocol will be used to determine +// hierarchy. +// The presented view controller (that is, the view controller that runs the +// menu) should set the size of its view in -loadView or -viewDidLoad. +// If the presenting view controller conforms to the MenuPresentationDelegate +// protocol, that protocol will be used to determine the region the menu +// appears in; otherwise it will appear in the center of the presenting view // the region the menu appears in. Otherwise a default rectangular area is -// used. +// controller's view. @interface MenuPresentationController : UIPresentationController +@property(nonatomic, assign) id<ToolbarCommands> toolbarCommandHandler; @end #endif // IOS_CLEAN_CHROME_BROWSER_UI_PRESENTERS_MENU_PRESENTATION_CONTROLLER_H_
diff --git a/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.mm b/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.mm index 39635293..ebba798 100644 --- a/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.mm +++ b/ios/clean/chrome/browser/ui/presenters/menu_presentation_controller.mm
@@ -10,6 +10,7 @@ #import <QuartzCore/QuartzCore.h> +#include "ios/clean/chrome/browser/ui/commands/toolbar_commands.h" #include "ios/clean/chrome/browser/ui/presenters/menu_presentation_delegate.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -19,11 +20,14 @@ @interface MenuPresentationController () @property(nonatomic, weak) id<MenuPresentationDelegate> presentationDelegate; @property(nonatomic, assign) CGRect presentationFrame; +@property(nonatomic, strong) UITapGestureRecognizer* dismissRecognizer; @end @implementation MenuPresentationController @synthesize presentationDelegate = _presentationDelegate; @synthesize presentationFrame = _presentationFrame; +@synthesize toolbarCommandHandler = _toolbarCommandHandler; +@synthesize dismissRecognizer = _dismissRecognizer; #pragma mark - UIPresentationDelegate @@ -34,9 +38,12 @@ self.presentationFrame = [self.presentationDelegate frameForMenuPresentation:self]; } else { - // Placeholder default frame: something rectangular, 50 points in and - // down. - self.presentationFrame = CGRectMake(50, 50, 250, 300); + // Placeholder default frame: centered in the presenting view. + CGSize menuSize = self.presentedView.frame.size; + self.presentationFrame.size = menuSize; + self.presentationFrame.origin = CGPointMake( + (self.containerView.bounds.size.width - menuSize.width) / 2.0, + (self.containerView.bounds.size.height - menuSize.height) / 2.0); } } return self.presentationFrame; @@ -46,10 +53,19 @@ self.presentedView.layer.borderWidth = 1.0; self.presentedView.layer.shadowRadius = 1.0; self.presentedView.layer.borderColor = [UIColor blackColor].CGColor; + + self.dismissRecognizer = + [[UITapGestureRecognizer alloc] initWithTarget:self + action:@selector(tapToDismiss:)]; + [self.containerView addGestureRecognizer:self.dismissRecognizer]; } #pragma mark - Private methods. +- (void)tapToDismiss:(UIGestureRecognizer*)recognizer { + [self.toolbarCommandHandler closeToolsMenu]; +} + // Checks if the presenting view controller conforms to // MenuPresentationDelegate and, if so, sets that view controller as the // presentation delegate. This can't be done at init time, becuase the
diff --git a/ios/clean/chrome/browser/ui/strip/strip_container_view_controller.mm b/ios/clean/chrome/browser/ui/strip/strip_container_view_controller.mm index b9a05c2..af22de3b 100644 --- a/ios/clean/chrome/browser/ui/strip/strip_container_view_controller.mm +++ b/ios/clean/chrome/browser/ui/strip/strip_container_view_controller.mm
@@ -8,8 +8,8 @@ #import "ios/clean/chrome/browser/ui/strip/strip_container_view_controller.h" -#import "ios/clean/chrome/browser/ui/actions/tab_strip_actions.h" #import "ios/clean/chrome/browser/ui/ui_types.h" +#import "ios/clean/chrome/browser/ui/actions/tab_strip_actions.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h b/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h index 60e1191f..03a2bf46 100644 --- a/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h +++ b/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h
@@ -11,6 +11,7 @@ #import <UIKit/UIKit.h> +#import "ios/clean/chrome/browser/ui/animators/zoom_transition_delegate.h" #import "ios/clean/chrome/browser/ui/presenters/menu_presentation_delegate.h" // Base class for a view controller that contains a content view (generally @@ -18,7 +19,7 @@ // view, each managed by their own view controllers. // Subclasses manage the specific layout of these view controllers. @interface TabContainerViewController - : UIViewController<MenuPresentationDelegate> + : UIViewController<MenuPresentationDelegate, ZoomTransitionDelegate> // View controller showing the main content for the tab. If there is no // toolbar view controller set, the contents of this view controller will
diff --git a/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.mm b/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.mm index c494582..1246121 100644 --- a/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.mm +++ b/ios/clean/chrome/browser/ui/tab/tab_container_view_controller.mm
@@ -8,6 +8,7 @@ #import "ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h" +#import "base/mac/foundation_util.h" #import "ios/clean/chrome/browser/ui/ui_types.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -127,8 +128,47 @@ #pragma mark - MenuPresentationDelegate - (CGRect)frameForMenuPresentation:(UIPresentationController*)presentation { - // Placeholder. - return CGRectMake(50, 50, 250, 300); + CGSize menuSize = presentation.presentedView.frame.size; + CGRect menuRect; + menuRect.size = menuSize; + + CGRect menuOriginRect = [self rectForZoomWithKey:@"" inView:self.view]; + if (CGRectIsNull(menuOriginRect)) { + menuRect.origin = CGPointMake(50, 50); + return menuRect; + } + // Calculate which corner of the menu the origin rect is in. This is + // determined by comparing frames, and thus is RTL-independent. + if (CGRectGetMinX(menuOriginRect) - CGRectGetMinX(self.view.bounds) < + CGRectGetMaxX(self.view.bounds) - CGRectGetMaxX(menuOriginRect)) { + // Origin rect is closer to the left edge of |self.view| than to the right. + menuRect.origin.x = CGRectGetMinX(menuOriginRect); + } else { + // Origin rect is closer to the right edge of |self.view| than to the left. + menuRect.origin.x = CGRectGetMaxX(menuOriginRect) - menuSize.width; + } + + if (CGRectGetMinY(menuOriginRect) - CGRectGetMinY(self.view.bounds) < + CGRectGetMaxY(self.view.bounds) - CGRectGetMaxY(menuOriginRect)) { + // Origin rect is closer to the top edge of |self.view| than to the bottom. + menuRect.origin.y = CGRectGetMinY(menuOriginRect); + } else { + // Origin rect is closer to the bottom edge of |self.view| than to the top. + menuRect.origin.y = CGRectGetMaxY(menuOriginRect) - menuSize.height; + } + + return menuRect; +} + +#pragma mark - ZoomTransitionDelegate + +- (CGRect)rectForZoomWithKey:(NSObject*)key inView:(UIView*)view { + UIViewController<ZoomTransitionDelegate>* delegate = + base::mac::ObjCCast<UIViewController<ZoomTransitionDelegate>>( + self.toolbarViewController); + if (delegate) + return [delegate rectForZoomWithKey:key inView:view]; + return CGRectNull; } #pragma mark - UIResponder
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm index 6f2a9e7..aba4969d 100644 --- a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm +++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
@@ -49,6 +49,7 @@ - (void)showToolsMenu { ToolsCoordinator* toolsCoordinator = [[ToolsCoordinator alloc] init]; + toolsCoordinator.toolbarCommandHandler = self; [self addChildCoordinator:toolsCoordinator]; [toolsCoordinator start]; self.toolsMenuCoordinator = toolsCoordinator;
diff --git a/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm b/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm index 4272d9a..99d8d9c 100644 --- a/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm +++ b/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
@@ -17,25 +17,62 @@ #error "This file requires ARC support." #endif +namespace { +const CGFloat kMenuWidth = 250; +const CGFloat kMenuItemHeight = 44; +} + +// Placeholder model for menu item configuration. +@interface MenuItem : NSObject +@property(nonatomic, copy) NSString* title; +@property(nonatomic) SEL action; +@end + +@implementation MenuItem +@synthesize title = _title; +@synthesize action = _action; +@end + +@interface MenuViewController () +@property(nonatomic, readonly) NSArray<MenuItem*>* menuItems; +@end + @implementation MenuViewController +@synthesize menuItems = _menuItems; + +- (instancetype)init { + if ((self = [super init])) { + _menuItems = @[ + [[MenuItem alloc] init], [[MenuItem alloc] init], [[MenuItem alloc] init], + [[MenuItem alloc] init] + ]; + + _menuItems[0].title = @"New Tab"; + + _menuItems[1].title = @"Find in Page…"; + + _menuItems[2].title = @"Request Desktop Site"; + + _menuItems[3].title = @"Settings"; + _menuItems[3].action = @selector(showSettings:); + } + return self; +} + +- (void)loadView { + CGRect frame; + frame.size = CGSizeMake(kMenuWidth, kMenuItemHeight * _menuItems.count); + frame.origin = CGPointZero; + self.view = [[UIView alloc] initWithFrame:frame]; + self.view.backgroundColor = [UIColor whiteColor]; + self.view.autoresizingMask = UIViewAutoresizingNone; +} - (void)viewDidLoad { - self.view.backgroundColor = [UIColor whiteColor]; - struct MenuItem { - NSString* title; - SEL action; - }; - MenuItem menuItems[] = { - {@"New Tab", nullptr}, - {@"Find in Page…", nullptr}, - {@"Request Desktop Site", nullptr}, - {@"Settings", @selector(showSettings:)}, - }; NSMutableArray<UIButton*>* buttons = - [[NSMutableArray alloc] initWithCapacity:arraysize(menuItems)]; + [[NSMutableArray alloc] initWithCapacity:_menuItems.count]; - for (size_t i = 0; i < arraysize(menuItems); ++i) { - const MenuItem& item = menuItems[i]; + for (MenuItem* item in _menuItems) { UIButton* menuButton = [UIButton buttonWithType:UIButtonTypeSystem]; menuButton.translatesAutoresizingMaskIntoConstraints = NO; [menuButton setTitle:item.title forState:UIControlStateNormal];
diff --git a/ios/clean/chrome/browser/ui/tools/tools_coordinator.h b/ios/clean/chrome/browser/ui/tools/tools_coordinator.h index 9230705..a6eed0b 100644 --- a/ios/clean/chrome/browser/ui/tools/tools_coordinator.h +++ b/ios/clean/chrome/browser/ui/tools/tools_coordinator.h
@@ -13,9 +13,12 @@ #import "ios/clean/chrome/browser/browser_coordinator.h" +@protocol ToolbarCommands; + // Coordinator that shows an inteface for the user to select a // tool or action to use. @interface ToolsCoordinator : BrowserCoordinator +@property(nonatomic, assign) id<ToolbarCommands> toolbarCommandHandler; @end #endif // IOS_CLEAN_CHROME_BROWSER_UI_TOOLS_TOOLS_COORDINATOR_H_
diff --git a/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm b/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm index 50946fd..3d01ac2 100644 --- a/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm
@@ -21,6 +21,7 @@ @end @implementation ToolsCoordinator +@synthesize toolbarCommandHandler = _toolbarCommandHandler; @synthesize menuViewController = _menuViewController; #pragma mark - BrowserCoordinator @@ -67,6 +68,7 @@ [[MenuPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting]; + menuPresentation.toolbarCommandHandler = self.toolbarCommandHandler; return menuPresentation; }
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm index d155fbcc..b5e59fc 100644 --- a/ios/web/app/web_main_loop.mm +++ b/ios/web/app/web_main_loop.mm
@@ -78,7 +78,7 @@ size_t DefaultBrowserWorkerPoolIndexForTraits(const base::TaskTraits& traits) { const bool is_background = traits.priority() == base::TaskPriority::BACKGROUND; - if (traits.with_file_io()) + if (traits.may_block() || traits.with_base_sync_primitives()) return is_background ? BACKGROUND_FILE_IO : FOREGROUND_FILE_IO; return is_background ? BACKGROUND : FOREGROUND;
diff --git a/ios/web/net/request_tracker_impl.h b/ios/web/net/request_tracker_impl.h index e1695a6..582d615 100644 --- a/ios/web/net/request_tracker_impl.h +++ b/ios/web/net/request_tracker_impl.h
@@ -284,9 +284,6 @@ // |load_success| indicates if the page successfully loaded. void StopPageLoad(const GURL& url, bool load_success); - // Cancels all the requests in |live_requests_|. - void CancelRequests(); - #pragma mark Private Consumer API // Private methods that call into delegate methods. @@ -343,8 +340,6 @@ // progress, and thus requests corresponding to old navigation events are not // in it. std::map<const void*, TrackerCounts*> counts_by_request_; - // All the live requests associated with the tracker. - std::set<net::URLRequest*> live_requests_; // A list of all the TrackerCounts, including the finished ones. std::vector<std::unique_ptr<TrackerCounts>> counts_; // The system shall never allow the page load estimate to go back.
diff --git a/ios/web/net/request_tracker_impl.mm b/ios/web/net/request_tracker_impl.mm index bc0986f9..99939ca 100644 --- a/ios/web/net/request_tracker_impl.mm +++ b/ios/web/net/request_tracker_impl.mm
@@ -405,7 +405,6 @@ base::Bind( [](RequestTrackerImpl* tracker) { tracker->is_closing_ = true; - tracker->CancelRequests(); }, base::RetainedRef(this))); @@ -1240,21 +1239,6 @@ [urls componentsJoinedByString:@"\n"]]; } -void RequestTrackerImpl::CancelRequests() { - DCHECK_CURRENTLY_ON(web::WebThread::IO); - std::set<net::URLRequest*>::iterator it; - // TODO(droger): When canceling the request, we should in theory make sure - // that the NSURLProtocol client method |didFailWithError| is called, - // otherwise the iOS system may wait indefinitely for the request to complete. - // However, as we currently only cancel the requests when closing a tab, the - // requests are all canceled by the system shortly after and nothing bad - // happens. - for (it = live_requests_.begin(); it != live_requests_.end(); ++it) - (*it)->Cancel(); - - live_requests_.clear(); -} - void RequestTrackerImpl::SetCertificatePolicyCacheForTest( web::CertificatePolicyCache* cache) { policy_cache_ = cache;
diff --git a/ios/web/shell/test/context_menu_egtest.mm b/ios/web/shell/test/context_menu_egtest.mm index 9b10422..cc1d25b 100644 --- a/ios/web/shell/test/context_menu_egtest.mm +++ b/ios/web/shell/test/context_menu_egtest.mm
@@ -33,7 +33,7 @@ @implementation ContextMenuTestCase -// TODO(crbug.com/675015): Re-enable this test on device. +// TODO(crbug.com/675399): Re-enable this test on device. #if TARGET_IPHONE_SIMULATOR #define MAYBE_testContextMenu testContextMenu #else @@ -75,7 +75,7 @@ [[EarlGrey selectElementWithMatcher:copyItem] assertWithMatcher:grey_nil()]; } -// TODO(crbug.com/675015): Re-enable this test on device. +// TODO(crbug.com/675399): Re-enable this test on device. #if TARGET_IPHONE_SIMULATOR #define MAYBE_testContextMenuWebkitTouchCalloutNone \ testContextMenuWebkitTouchCalloutNone @@ -112,7 +112,7 @@ [[EarlGrey selectElementWithMatcher:copyItem] assertWithMatcher:grey_nil()]; } -// TODO(crbug.com/675015): Re-enable this test on device. +// TODO(crbug.com/675399): Re-enable this test on device. #if TARGET_IPHONE_SIMULATOR #define MAYBE_testContextMenuWebkitTouchCalloutNoneFromAncestor \ testContextMenuWebkitTouchCalloutNoneFromAncestor @@ -151,7 +151,7 @@ [[EarlGrey selectElementWithMatcher:copyItem] assertWithMatcher:grey_nil()]; } -// TODO(crbug.com/675015): Re-enable this test on device. +// TODO(crbug.com/675399): Re-enable this test on device. #if TARGET_IPHONE_SIMULATOR #define MAYBE_testContextMenuWebkitTouchCalloutOverride \ testContextMenuWebkitTouchCalloutOverride
diff --git a/ipc/ipc_mojo_bootstrap_unittest.cc b/ipc/ipc_mojo_bootstrap_unittest.cc index b0a4709..b036faca 100644 --- a/ipc/ipc_mojo_bootstrap_unittest.cc +++ b/ipc/ipc_mojo_bootstrap_unittest.cc
@@ -18,7 +18,6 @@ #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/test/mojo_test_base.h" #include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/edk/test/scoped_ipc_support.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h"
diff --git a/ipc/ipc_mojo_perftest.cc b/ipc/ipc_mojo_perftest.cc index 4c0990a9..5358b6a 100644 --- a/ipc/ipc_mojo_perftest.cc +++ b/ipc/ipc_mojo_perftest.cc
@@ -20,7 +20,6 @@ #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/test/mojo_test_base.h" #include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/message_pipe.h"
diff --git a/ipc/run_all_perftests.cc b/ipc/run_all_perftests.cc index 1e3d91f..b22c912 100644 --- a/ipc/run_all_perftests.cc +++ b/ipc/run_all_perftests.cc
@@ -8,7 +8,7 @@ #include "base/test/perf_test_suite.h" #include "base/test/test_io_thread.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "mojo/edk/test/test_support_impl.h" int main(int argc, char** argv) { @@ -16,7 +16,9 @@ mojo::edk::Init(); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + test_io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); mojo::test::TestSupport::Init(new mojo::edk::test::TestSupportImpl()); return test.Run();
diff --git a/ipc/run_all_unittests.cc b/ipc/run_all_unittests.cc index 5646c67..cd62e45 100644 --- a/ipc/run_all_unittests.cc +++ b/ipc/run_all_unittests.cc
@@ -9,7 +9,7 @@ #include "base/test/test_suite.h" #include "build/build_config.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #if defined(OS_MACOSX) && !defined(OS_IOS) #include "base/mac/mach_port_broker.h" @@ -19,10 +19,9 @@ base::TestSuite test_suite(argc, argv); mojo::edk::Init(); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - // Leak this because its destructor calls mojo::edk::ShutdownIPCSupport which - // really does nothing in the new EDK but does depend on the current message - // loop, which is destructed inside base::LaunchUnitTests. - new mojo::edk::test::ScopedIPCSupport(test_io_thread.task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + test_io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); #if defined(OS_MACOSX) && !defined(OS_IOS) base::MachPortBroker mach_broker("mojo_test");
diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn index 67a7376e..c652e517 100644 --- a/mojo/edk/embedder/BUILD.gn +++ b/mojo/edk/embedder/BUILD.gn
@@ -15,7 +15,6 @@ "platform_channel_pair.h", "platform_handle.h", "platform_handle_utils.h", - "process_delegate.h", "scoped_platform_handle.h", ] @@ -54,7 +53,6 @@ defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] public_deps = [ - ":delegates", ":headers", ":platform", "//base", @@ -121,25 +119,6 @@ } } -source_set("delegates") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - ":embedder", - "//mojo/edk/system", - ] - - sources = [ - "process_delegate.h", - ] - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - public_deps = [ - "//mojo/public/cpp/system", - ] -} - source_set("embedder_unittests") { testonly = true
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 5cf70e5..41d48d4dc2 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc
@@ -18,8 +18,8 @@ #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/entrypoints.h" #include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/process_delegate.h" #include "mojo/edk/system/core.h" +#include "mojo/edk/system/node_controller.h" #if !defined(OS_NACL) #include "crypto/random.h" @@ -34,7 +34,6 @@ namespace internal { Core* g_core; -ProcessDelegate* g_process_delegate; Core* GetCore() { return g_core; } @@ -83,14 +82,12 @@ ScopedMessagePipeHandle ConnectToPeerProcess(ScopedPlatformHandle pipe, const std::string& peer_token) { - CHECK(internal::g_process_delegate); DCHECK(pipe.is_valid()); DCHECK(!peer_token.empty()); return internal::g_core->ConnectToPeerProcess(std::move(pipe), peer_token); } void ClosePeerConnection(const std::string& peer_token) { - CHECK(internal::g_process_delegate); return internal::g_core->ClosePeerConnection(peer_token); } @@ -137,19 +134,18 @@ mojo_handle, shared_memory_handle, num_bytes, read_only); } -void InitIPCSupport(ProcessDelegate* process_delegate, - scoped_refptr<base::TaskRunner> io_thread_task_runner) { +void InitIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner) { CHECK(internal::g_core); internal::g_core->SetIOTaskRunner(io_thread_task_runner); - internal::g_process_delegate = process_delegate; } -void ShutdownIPCSupport() { - CHECK(internal::g_process_delegate); +scoped_refptr<base::TaskRunner> GetIOTaskRunner() { + return internal::g_core->GetNodeController()->io_task_runner(); +} + +void ShutdownIPCSupport(const base::Closure& callback) { CHECK(internal::g_core); - internal::g_core->RequestShutdown( - base::Bind(&ProcessDelegate::OnShutdownComplete, - base::Unretained(internal::g_process_delegate))); + internal::g_core->RequestShutdown(callback); } #if defined(OS_MACOSX) && !defined(OS_IOS) @@ -161,18 +157,15 @@ ScopedMessagePipeHandle CreateMessagePipe( ScopedPlatformHandle platform_handle) { - CHECK(internal::g_process_delegate); return internal::g_core->CreateMessagePipe(std::move(platform_handle)); } ScopedMessagePipeHandle CreateParentMessagePipe( const std::string& token, const std::string& child_token) { - CHECK(internal::g_process_delegate); return internal::g_core->CreateParentMessagePipe(token, child_token); } ScopedMessagePipeHandle CreateChildMessagePipe(const std::string& token) { - CHECK(internal::g_process_delegate); return internal::g_core->CreateChildMessagePipe(token); }
diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index e673aff2..c0672aa8 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h
@@ -27,8 +27,6 @@ namespace mojo { namespace edk { -class ProcessDelegate; - using ProcessErrorCallback = base::Callback<void(const std::string& error)>; // Basic configuration/initialization ------------------------------------------ @@ -150,22 +148,20 @@ // // This subsystem may be shut down using |ShutdownIPCSupport()|. None of the IPC // functions may be called after this is called. - -// Initializes a process of the given type; to be called after |Init()|. -// - |process_delegate| must be a process delegate of the appropriate type -// corresponding to |process_type|; its methods will be called on the same -// thread as Shutdown. -// - |process_delegate|, and |io_thread_task_runner| should live at least -// until |ShutdownIPCSupport()|'s callback has been run. +// +// |io_thread_task_runner| should live at least until |ShutdownIPCSupport()|'s +// callback has been run. MOJO_SYSTEM_IMPL_EXPORT void InitIPCSupport( - ProcessDelegate* process_delegate, scoped_refptr<base::TaskRunner> io_thread_task_runner); +// Retrieves the TaskRunner used for IPC I/O, as set by InitIPCSupport. +MOJO_SYSTEM_IMPL_EXPORT scoped_refptr<base::TaskRunner> GetIOTaskRunner(); + // Shuts down the subsystem initialized by |InitIPCSupport()|. It be called from // any thread and will attempt to complete shutdown on the I/O thread with which -// the system was initialized. Upon completion the ProcessDelegate's -// |OnShutdownComplete()| method is invoked. -MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport(); +// the system was initialized. Upon completion, |callback| is invoked on an +// arbitrary thread. +MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport(const base::Closure& callback); #if defined(OS_MACOSX) && !defined(OS_IOS) // Set the |base::PortProvider| for this process. Can be called on any thread,
diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc index 4521f80..f0fe440 100644 --- a/mojo/edk/embedder/embedder_unittest.cc +++ b/mojo/edk/embedder/embedder_unittest.cc
@@ -23,13 +23,13 @@ #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" +#include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/named_platform_handle.h" #include "mojo/edk/embedder/named_platform_handle_utils.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/test_embedder.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/test/mojo_test_base.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "mojo/public/c/system/core.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/message_pipe.h" @@ -595,7 +595,7 @@ // work. By the time the local message pipe has been observerd as closed, // that task will have been posted. Therefore, a task to create the client // connection should be handled after the channel is closed. - test::GetIoTaskRunner()->PostTaskAndReply( + GetIOTaskRunner()->PostTaskAndReply( FROM_HERE, base::Bind(&CreateClientHandleOnIoThread, named_handle, &client_handle), run_loop.QuitClosure());
diff --git a/mojo/edk/embedder/process_delegate.h b/mojo/edk/embedder/process_delegate.h deleted file mode 100644 index 144f4a3a..0000000 --- a/mojo/edk/embedder/process_delegate.h +++ /dev/null
@@ -1,31 +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 MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_ -#define MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_ - -#include "base/macros.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -// An interface for process delegates. -class MOJO_SYSTEM_IMPL_EXPORT ProcessDelegate { - public: - // Called when |ShutdownIPCSupport()| has completed work on the I/O thread. - virtual void OnShutdownComplete() = 0; - - protected: - ProcessDelegate() {} - virtual ~ProcessDelegate() {} - - private: - DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_
diff --git a/mojo/edk/embedder/scoped_ipc_support.cc b/mojo/edk/embedder/scoped_ipc_support.cc index 9c598b5..f67210a8 100644 --- a/mojo/edk/embedder/scoped_ipc_support.cc +++ b/mojo/edk/embedder/scoped_ipc_support.cc
@@ -4,57 +4,35 @@ #include "mojo/edk/embedder/scoped_ipc_support.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread_restrictions.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/process_delegate.h" namespace mojo { namespace edk { -namespace { -class IPCSupportInitializer : public mojo::edk::ProcessDelegate { - public: - IPCSupportInitializer() {} - ~IPCSupportInitializer() override {} - - void Init(scoped_refptr<base::TaskRunner> io_thread_task_runner) { - CHECK(!io_thread_task_runner_); - CHECK(io_thread_task_runner); - io_thread_task_runner_ = io_thread_task_runner; - - mojo::edk::InitIPCSupport(this, io_thread_task_runner_); - } - - void ShutDown() { - CHECK(io_thread_task_runner_); - mojo::edk::ShutdownIPCSupport(); - } - - private: - // mojo::edk::ProcessDelegate: - void OnShutdownComplete() override { - // TODO(rockot): We should ensure that IO runner shutdown is blocked until - // this is called. - } - - scoped_refptr<base::TaskRunner> io_thread_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(IPCSupportInitializer); -}; - -base::LazyInstance<IPCSupportInitializer>::Leaky ipc_support_initializer; - -} // namespace - ScopedIPCSupport::ScopedIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner) { - ipc_support_initializer.Get().Init(io_thread_task_runner); + scoped_refptr<base::TaskRunner> io_thread_task_runner, + ShutdownPolicy shutdown_policy) : shutdown_policy_(shutdown_policy) { + InitIPCSupport(io_thread_task_runner); } ScopedIPCSupport::~ScopedIPCSupport() { - ipc_support_initializer.Get().ShutDown(); + if (shutdown_policy_ == ShutdownPolicy::FAST) { + ShutdownIPCSupport(base::Bind(&base::DoNothing)); + return; + } + + base::WaitableEvent shutdown_event( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + ShutdownIPCSupport(base::Bind(&base::WaitableEvent::Signal, + base::Unretained(&shutdown_event))); + + base::ThreadRestrictions::ScopedAllowWait allow_io; + shutdown_event.Wait(); } } // namespace edk
diff --git a/mojo/edk/embedder/scoped_ipc_support.h b/mojo/edk/embedder/scoped_ipc_support.h index a3b32da3..22d8e50 100644 --- a/mojo/edk/embedder/scoped_ipc_support.h +++ b/mojo/edk/embedder/scoped_ipc_support.h
@@ -5,26 +5,110 @@ #ifndef MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ #define MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/task_runner.h" #include "mojo/edk/system/system_impl_export.h" +namespace base { +class TaskRunner; +} + namespace mojo { namespace edk { -// Performs any necessary Mojo initialization on construction, and shuts -// down Mojo on destruction. -// -// This should be instantiated once per process and retained as long as Mojo -// is needed. The TaskRunner passed to the constructor should outlive this -// object. +// A simple class that calls |InitIPCSupport()| on construction and +// |ShutdownIPCSupport()| on destruction, blocking the destructor on clean IPC +// shutdown completion. class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport { public: - ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner); + // ShutdownPolicy is a type for specifying the desired Mojo IPC support + // shutdown behavior used during ScopedIPCSupport destruction. + // + // What follows is a quick overview of why shutdown behavior is interesting + // and how you might decide which behavior is right for your use case. + // + // BACKGROUND + // ========== + // + // In order to facilitate efficient and reliable transfer of Mojo message pipe + // endpoints across process boundaries, the underlying model for a message + // pipe is actually a self-collapsing cycle of "ports." See + // //mojo/edk/system/ports for gritty implementation details. + // + // Ports are essentially globally unique identifiers used for system-wide + // message routing. Every message pipe consists of at least two such ports: + // the pipe's two concrete endpoints. + // + // When a message pipe endpoint is transferred over another message pipe, that + // endpoint's port (which subsequently exists only internally with no + // publicly-reachable handle) enters a transient proxying state for the + // remainder of its lifetime. Once sufficient information has been + // proagated throughout the system and this proxying port can be safely + // bypassed, it is garbage-collected. + // + // If a process is terminated while hosting any active proxy ports, this + // will necessarily break the message pipe(s) to which those ports belong. + // + // WHEN TO USE CLEAN SHUTDOWN + // ========================== + // + // Consider three processes, A, B, and C. Suppose A creates a message pipe, + // sending one end to B and the other to C. For some brief period of time, + // messages sent by B or C over this pipe may be proxied through A. + // + // If A is suddenly terminated, there may be no way for B's messages to reach + // C (and vice versa), since the message pipe state may not have been fully + // propagated to all concerned processes in the system. As such, both B and C + // may have no choice but to signal peer closure on their respective ends of + // the pipe, and thus the pipe may be broken despite a lack of intent by + // either B or C. + // + // This can also happen if A creates a pipe and passes one end to B, who then + // passes it along to C. B may temporarily proxy messages for this pipe + // between A and C, and B's sudden demise will in turn beget the pipe's + // own sudden demise. + // + // In situations where these sort of arrangements may occur, potentially + // proxying processes must ensure they are shut down cleanly in order to avoid + // flaky system behavior. + // + // WHEN TO USE FAST SHUTDOWN + // ========================= + // + // As a general rule of thumb, if your process never creates a message pipe + // where both ends are passed to other processes, or never forwards a pipe + // endpoint from one process to another, fast shutdown is safe. Satisfaction + // of these constraints can be difficult to prove though, so clean shutdown is + // a safe default choice. + // + // Content renderer processes are a good example of a case where fast shutdown + // is safe, because as a matter of security and stability, a renderer cannot + // be trusted to do any proxying on behalf of two other processes anyway. + // + // There are other practical scenarios where fast shutdown is safe even if + // the process may have live proxies. For example, content's browser process + // is treated as a sort of master process in the system, in the sense that if + // the browser is terminated, no other part of the system is expected to + // continue normal operation anyway. In this case the side-effects of fast + // shutdown are irrelevant, so fast shutdown is preferred. + enum class ShutdownPolicy { + // Clean shutdown. This causes the ScopedIPCSupport destructor to *block* + // the calling thread until clean shutdown is complete. See explanation + // above for details. + CLEAN, + + // Fast shutdown. In this case a cheap best-effort attempt is made to + // shut down the IPC system, but no effort is made to wait for its + // completion. See explanation above for details. + FAST, + }; + + ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner, + ShutdownPolicy shutdown_policy); ~ScopedIPCSupport(); private: + const ShutdownPolicy shutdown_policy_; + DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport); };
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index 9023fbd..c24458a 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn
@@ -78,7 +78,6 @@ public_deps = [ "//mojo/edk/embedder", - "//mojo/edk/embedder:delegates", "//mojo/edk/embedder:platform", "//mojo/edk/system/ports", "//mojo/public/c/system",
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index cfcb777..308c2879 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc
@@ -332,15 +332,7 @@ } void Core::RequestShutdown(const base::Closure& callback) { - base::Closure on_shutdown; - if (base::ThreadTaskRunnerHandle::IsSet()) { - on_shutdown = base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask), - base::ThreadTaskRunnerHandle::Get(), - FROM_HERE, callback); - } else { - on_shutdown = callback; - } - GetNodeController()->RequestShutdown(on_shutdown); + GetNodeController()->RequestShutdown(callback); } ScopedMessagePipeHandle Core::CreateMessagePipe(
diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn index ebacc64..a15456a 100644 --- a/mojo/edk/test/BUILD.gn +++ b/mojo/edk/test/BUILD.gn
@@ -9,8 +9,6 @@ sources = [ "mojo_test_base.cc", "mojo_test_base.h", - "scoped_ipc_support.cc", - "scoped_ipc_support.h", "test_utils.h", "test_utils_posix.cc", "test_utils_win.cc",
diff --git a/mojo/edk/test/run_all_perftests.cc b/mojo/edk/test/run_all_perftests.cc index 8f2511f..3ce3b47 100644 --- a/mojo/edk/test/run_all_perftests.cc +++ b/mojo/edk/test/run_all_perftests.cc
@@ -7,8 +7,8 @@ #include "base/test/perf_test_suite.h" #include "base/test/test_io_thread.h" #include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "mojo/edk/test/test_support_impl.h" #include "mojo/public/tests/test_support_private.h" @@ -17,7 +17,9 @@ mojo::edk::Init(); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + test_io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); mojo::test::TestSupport::Init(new mojo::edk::test::TestSupportImpl()); return test.Run();
diff --git a/mojo/edk/test/run_all_unittests.cc b/mojo/edk/test/run_all_unittests.cc index 0b0663b..a057825 100644 --- a/mojo/edk/test/run_all_unittests.cc +++ b/mojo/edk/test/run_all_unittests.cc
@@ -11,8 +11,8 @@ #include "base/test/test_io_thread.h" #include "base/test/test_suite.h" #include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "mojo/edk/test/test_support_impl.h" #include "mojo/public/tests/test_support_private.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,7 +40,9 @@ mojo::test::TestSupport::Init(new mojo::edk::test::TestSupportImpl()); base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + test_io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); return base::LaunchUnitTests( argc, argv, base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
diff --git a/mojo/edk/test/scoped_ipc_support.cc b/mojo/edk/test/scoped_ipc_support.cc deleted file mode 100644 index 588039a..0000000 --- a/mojo/edk/test/scoped_ipc_support.cc +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/test/scoped_ipc_support.h" - -#include "base/bind.h" -#include "base/run_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/edk/embedder/embedder.h" - -namespace mojo { -namespace edk { -namespace test { - -namespace { -base::TaskRunner* g_io_task_runner = nullptr; -} - -base::TaskRunner* GetIoTaskRunner() { - return g_io_task_runner; -} - -ScopedIPCSupport::ScopedIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner) - : shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED) { - g_io_task_runner = io_thread_task_runner.get(); - InitIPCSupport(this, io_thread_task_runner); -} - -ScopedIPCSupport::~ScopedIPCSupport() { - // ShutdownIPCSupport always runs OnShutdownComplete on the current - // ThreadTaskRunnerHandle if set. Otherwise it's run on the IPC thread. We - // account for both possibilities here to avoid unnecessarily starting a new - // MessageLoop or blocking the existing one. - // - // TODO(rockot): Clean this up. ShutdownIPCSupport should probably always call - // call OnShutdownComplete from the IPC thread. - ShutdownIPCSupport(); - if (base::ThreadTaskRunnerHandle::IsSet()) { - base::RunLoop run_loop; - shutdown_closure_ = base::Bind(IgnoreResult(&base::TaskRunner::PostTask), - base::ThreadTaskRunnerHandle::Get(), - FROM_HERE, run_loop.QuitClosure()); - run_loop.Run(); - } else { - shutdown_event_.Wait(); - } -} - -void ScopedIPCSupport::OnShutdownComplete() { - if (!shutdown_closure_.is_null()) - shutdown_closure_.Run(); - else - shutdown_event_.Signal(); -} - -} // namespace test -} // namespace edk -} // namespace mojo
diff --git a/mojo/edk/test/scoped_ipc_support.h b/mojo/edk/test/scoped_ipc_support.h deleted file mode 100644 index c2e5735..0000000 --- a/mojo/edk/test/scoped_ipc_support.h +++ /dev/null
@@ -1,43 +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 MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_ -#define MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_ - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/waitable_event.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/process_delegate.h" - -namespace mojo { -namespace edk { -namespace test { - -base::TaskRunner* GetIoTaskRunner(); - -// A simple class that calls |InitIPCSupport()| on construction and -// |ShutdownIPCSupport()| on destruction. -class ScopedIPCSupport : public ProcessDelegate { - public: - explicit ScopedIPCSupport( - scoped_refptr<base::TaskRunner> io_thread_task_runner); - ~ScopedIPCSupport() override; - - private: - // |ProcessDelegate| implementation: - // Note: Executed on the I/O thread. - void OnShutdownComplete() override; - - base::Closure shutdown_closure_; - base::WaitableEvent shutdown_event_; - - DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport); -}; - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index b2e75ae..3d4f8af 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -121,6 +121,7 @@ deps = [ "//base/test:test_support", + "//mojo/edk/system", "//mojo/edk/test:test_support", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system",
diff --git a/mojo/public/cpp/bindings/tests/e2e_perftest.cc b/mojo/public/cpp/bindings/tests/e2e_perftest.cc index 7b3954f..bc69e0f7 100644 --- a/mojo/public/cpp/bindings/tests/e2e_perftest.cc +++ b/mojo/public/cpp/bindings/tests/e2e_perftest.cc
@@ -13,8 +13,8 @@ #include "base/strings/stringprintf.h" #include "base/test/perf_time_logger.h" #include "base/threading/thread_task_runner_handle.h" +#include "mojo/edk/embedder/embedder.h" #include "mojo/edk/test/mojo_test_base.h" -#include "mojo/edk/test/scoped_ipc_support.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h" #include "testing/gtest/include/gtest/gtest.h" @@ -171,7 +171,7 @@ InterfaceRequest<test::EchoService> request; request.Bind(ScopedMessagePipeHandle(MessagePipeHandle(service_mp))); base::RunLoop run_loop; - edk::test::GetIoTaskRunner()->PostTask( + edk::GetIOTaskRunner()->PostTask( FROM_HERE, base::Bind(&CreateAndRunService, base::Passed(&request), base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask), @@ -195,7 +195,7 @@ MojoHandle client_mp, service_mp; CreateMessagePipe(&client_mp, &service_mp); WriteMessageWithHandles(mp, "hello", &service_mp, 1); - RunTestOnTaskRunner(edk::test::GetIoTaskRunner(), client_mp, + RunTestOnTaskRunner(edk::GetIOTaskRunner().get(), client_mp, "MultiProcessEchoIoThread"); END_CHILD() }
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc index 6842643..d94030c9 100644 --- a/net/cert/nss_cert_database.cc +++ b/net/cert/nss_cert_database.cc
@@ -176,15 +176,15 @@ } } -int NSSCertDatabase::ImportFromPKCS12(CryptoModule* module, +int NSSCertDatabase::ImportFromPKCS12(PK11SlotInfo* slot_info, const std::string& data, const base::string16& password, bool is_extractable, CertificateList* imported_certs) { DVLOG(1) << __func__ << " " - << PK11_GetModuleID(module->os_module_handle()) << ":" - << PK11_GetSlotID(module->os_module_handle()); - int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), + << PK11_GetModuleID(slot_info) << ":" + << PK11_GetSlotID(slot_info); + int result = psm::nsPKCS12Blob_Import(slot_info, data.data(), data.size(), password, is_extractable,
diff --git a/net/cert/nss_cert_database.h b/net/cert/nss_cert_database.h index 2ee859d..b168f8f19 100644 --- a/net/cert/nss_cert_database.h +++ b/net/cert/nss_cert_database.h
@@ -168,7 +168,7 @@ // Returns OK or a network error code such as ERR_PKCS12_IMPORT_BAD_PASSWORD // or ERR_PKCS12_IMPORT_ERROR. |imported_certs|, if non-NULL, returns a list // of certs that were imported. - int ImportFromPKCS12(CryptoModule* module, + int ImportFromPKCS12(PK11SlotInfo* slot_info, const std::string& data, const base::string16& password, bool is_extractable,
diff --git a/net/cert/nss_cert_database_unittest.cc b/net/cert/nss_cert_database_unittest.cc index 9832289..235ea44c 100644 --- a/net/cert/nss_cert_database_unittest.cc +++ b/net/cert/nss_cert_database_unittest.cc
@@ -68,7 +68,7 @@ PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */, crypto::ScopedPK11Slot( PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */)); - public_module_ = cert_db_->GetPublicModule(); + public_slot_ = cert_db_->GetPublicSlot(); // Test db should be empty at start of test. EXPECT_EQ(0U, ListCerts().size()); @@ -82,7 +82,7 @@ } protected: - CryptoModule* GetPublicModule() { return public_module_.get(); } + PK11SlotInfo* GetPublicSlot() { return public_slot_.get(); } static std::string ReadTestFile(const std::string& name) { std::string result; @@ -128,7 +128,7 @@ std::unique_ptr<NSSCertDatabase> cert_db_; const CertificateList empty_cert_list_; crypto::ScopedTestNSSDB test_nssdb_; - scoped_refptr<CryptoModule> public_module_; + crypto::ScopedPK11Slot public_slot_; }; TEST_F(CertDatabaseNSSTest, ListCertsSync) { @@ -160,7 +160,7 @@ std::string pkcs12_data = ReadTestFile("client.p12"); EXPECT_EQ(ERR_PKCS12_IMPORT_BAD_PASSWORD, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, base::string16(), true, // is_extractable @@ -174,7 +174,7 @@ std::string pkcs12_data = ReadTestFile("client.p12"); EXPECT_EQ(OK, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, ASCIIToUTF16("12345"), true, // is_extractable @@ -199,7 +199,7 @@ std::string pkcs12_data = ReadTestFile("client.p12"); EXPECT_EQ(OK, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, ASCIIToUTF16("12345"), true, // is_extractable @@ -209,7 +209,7 @@ // NSS has a SEC_ERROR_PKCS12_DUPLICATE_DATA error, but it doesn't look like // it's ever used. This test verifies that. EXPECT_EQ(OK, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, ASCIIToUTF16("12345"), true, // is_extractable @@ -221,7 +221,7 @@ std::string pkcs12_data = ReadTestFile("client.p12"); EXPECT_EQ(OK, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, ASCIIToUTF16("12345"), false, // is_extractable @@ -244,7 +244,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12OnlyMarkIncludedKey) { std::string pkcs12_data = ReadTestFile("client.p12"); EXPECT_EQ(OK, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, ASCIIToUTF16("12345"), true, // is_extractable @@ -256,7 +256,7 @@ // Now import a PKCS#12 file with just a certificate but no private key. pkcs12_data = ReadTestFile("client-nokey.p12"); EXPECT_EQ(OK, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, ASCIIToUTF16("12345"), false, // is_extractable @@ -276,7 +276,7 @@ std::string pkcs12_data = "Foobarbaz"; EXPECT_EQ(ERR_PKCS12_IMPORT_INVALID_FILE, - cert_db_->ImportFromPKCS12(GetPublicModule(), + cert_db_->ImportFromPKCS12(GetPublicSlot(), pkcs12_data, base::string16(), true, // is_extractable @@ -289,20 +289,24 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12EmptyPassword) { std::string pkcs12_data = ReadTestFile("client-empty-password.p12"); - EXPECT_EQ(OK, cert_db_->ImportFromPKCS12(GetPublicModule(), pkcs12_data, - base::string16(), - true, // is_extractable - NULL)); + EXPECT_EQ(OK, + cert_db_->ImportFromPKCS12(GetPublicSlot(), + pkcs12_data, + base::string16(), + true, // is_extractable + NULL)); EXPECT_EQ(1U, ListCerts().size()); } TEST_F(CertDatabaseNSSTest, ImportFromPKCS12NullPassword) { std::string pkcs12_data = ReadTestFile("client-null-password.p12"); - EXPECT_EQ(OK, cert_db_->ImportFromPKCS12(GetPublicModule(), pkcs12_data, - base::string16(), - true, // is_extractable - NULL)); + EXPECT_EQ(OK, + cert_db_->ImportFromPKCS12(GetPublicSlot(), + pkcs12_data, + base::string16(), + true, // is_extractable + NULL)); EXPECT_EQ(1U, ListCerts().size()); }
diff --git a/remoting/host/daemon_process_win.cc b/remoting/host/daemon_process_win.cc index 1d0649b..ee6a99a 100644 --- a/remoting/host/daemon_process_win.cc +++ b/remoting/host/daemon_process_win.cc
@@ -128,7 +128,8 @@ scoped_refptr<AutoThreadTaskRunner> io_task_runner, const base::Closure& stopped_callback) : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback), - ipc_support_(io_task_runner->task_runner()) {} + ipc_support_(io_task_runner->task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST) {} DaemonProcessWin::~DaemonProcessWin() { }
diff --git a/remoting/host/desktop_process_main.cc b/remoting/host/desktop_process_main.cc index 05743efd..e5b98fc 100644 --- a/remoting/host/desktop_process_main.cc +++ b/remoting/host/desktop_process_main.cc
@@ -52,7 +52,9 @@ AutoThread::CreateWithType("I/O thread", ui_task_runner, base::MessageLoop::TYPE_IO); - mojo::edk::ScopedIPCSupport ipc_support(io_task_runner->task_runner()); + mojo::edk::ScopedIPCSupport ipc_support( + io_task_runner->task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); mojo::edk::ScopedPlatformHandle parent_pipe = mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess( *command_line);
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index aca4bc9..abda2693 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -470,7 +470,8 @@ // AutoThreadTaskRunner should not be passed to it. Otherwise, the process may // never shut down cleanly. ipc_support_ = base::MakeUnique<mojo::edk::ScopedIPCSupport>( - context_->network_task_runner()->task_runner()); + context_->network_task_runner()->task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); mojo::edk::SetParentPipeHandle( mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess( *cmd_line));
diff --git a/remoting/host/security_key/remote_security_key_main.cc b/remoting/host/security_key/remote_security_key_main.cc index 1490b42..a84012c 100644 --- a/remoting/host/security_key/remote_security_key_main.cc +++ b/remoting/host/security_key/remote_security_key_main.cc
@@ -141,7 +141,9 @@ #endif mojo::edk::Init(); - mojo::edk::ScopedIPCSupport ipc_support(base::ThreadTaskRunnerHandle::Get()); + mojo::edk::ScopedIPCSupport ipc_support( + base::ThreadTaskRunnerHandle::Get(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); base::RunLoop run_loop;
diff --git a/remoting/host/security_key/security_key_auth_handler_win_unittest.cc b/remoting/host/security_key/security_key_auth_handler_win_unittest.cc index dbfe9250..58ad21c 100644 --- a/remoting/host/security_key/security_key_auth_handler_win_unittest.cc +++ b/remoting/host/security_key/security_key_auth_handler_win_unittest.cc
@@ -17,7 +17,7 @@ #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "remoting/host/host_mock_objects.h" #include "remoting/host/security_key/fake_security_key_ipc_client.h" #include "remoting/host/security_key/fake_security_key_ipc_server.h" @@ -88,7 +88,7 @@ // IPC tests require a valid MessageLoop to run. base::MessageLoopForIO message_loop_; - mojo::edk::test::ScopedIPCSupport ipc_support_; + mojo::edk::ScopedIPCSupport ipc_support_; // Used to allow |message_loop_| to run during tests. The instance is reset // after each stage of the tests has been completed. @@ -116,7 +116,8 @@ }; SecurityKeyAuthHandlerWinTest::SecurityKeyAuthHandlerWinTest() - : ipc_support_(message_loop_.task_runner()), + : ipc_support_(message_loop_.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST), run_loop_(new base::RunLoop()) { auth_handler_ = remoting::SecurityKeyAuthHandler::Create( &mock_client_session_details_,
diff --git a/remoting/host/security_key/security_key_ipc_client_unittest.cc b/remoting/host/security_key/security_key_ipc_client_unittest.cc index cf62fa31..ad9e5f3 100644 --- a/remoting/host/security_key/security_key_ipc_client_unittest.cc +++ b/remoting/host/security_key/security_key_ipc_client_unittest.cc
@@ -13,7 +13,7 @@ #include "base/run_loop.h" #include "ipc/ipc_channel.h" #include "mojo/edk/embedder/named_platform_handle_utils.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "remoting/host/security_key/fake_security_key_ipc_server.h" #include "remoting/host/security_key/security_key_ipc_constants.h" #include "testing/gtest/include/gtest/gtest.h" @@ -74,7 +74,7 @@ // IPC tests require a valid MessageLoop to run. base::MessageLoopForIO message_loop_; - mojo::edk::test::ScopedIPCSupport ipc_support_; + mojo::edk::ScopedIPCSupport ipc_support_; // Used to allow |message_loop_| to run during tests. The instance is reset // after each stage of the tests has been completed. @@ -110,7 +110,8 @@ }; SecurityKeyIpcClientTest::SecurityKeyIpcClientTest() - : ipc_support_(message_loop_.task_runner()), + : ipc_support_(message_loop_.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST), run_loop_(new base::RunLoop()), fake_ipc_server_( kTestConnectionId,
diff --git a/remoting/host/security_key/security_key_ipc_server_unittest.cc b/remoting/host/security_key/security_key_ipc_server_unittest.cc index 4d5eb47..075b27e 100644 --- a/remoting/host/security_key/security_key_ipc_server_unittest.cc +++ b/remoting/host/security_key/security_key_ipc_server_unittest.cc
@@ -16,7 +16,7 @@ #include "ipc/ipc_channel.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/named_platform_handle_utils.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "remoting/host/client_session_details.h" #include "remoting/host/security_key/fake_security_key_ipc_client.h" #include "remoting/host/security_key/security_key_ipc_constants.h" @@ -59,7 +59,7 @@ // IPC tests require a valid MessageLoop to run. base::MessageLoopForIO message_loop_; - mojo::edk::test::ScopedIPCSupport ipc_support_; + mojo::edk::ScopedIPCSupport ipc_support_; // Used to allow |message_loop_| to run during tests. The instance is reset // after each stage of the tests has been completed. @@ -82,7 +82,8 @@ }; SecurityKeyIpcServerTest::SecurityKeyIpcServerTest() - : ipc_support_(message_loop_.task_runner()), + : ipc_support_(message_loop_.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST), run_loop_(new base::RunLoop()) { #if defined(OS_WIN) EXPECT_TRUE(ProcessIdToSessionId(
diff --git a/services/service_manager/public/cpp/standalone_service/standalone_service.cc b/services/service_manager/public/cpp/standalone_service/standalone_service.cc index 2e49b73b..bd26da0 100644 --- a/services/service_manager/public/cpp/standalone_service/standalone_service.cc +++ b/services/service_manager/public/cpp/standalone_service/standalone_service.cc
@@ -11,7 +11,7 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/process_delegate.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "mojo/public/cpp/system/message_pipe.h" #include "services/service_manager/public/cpp/service_context.h" #include "services/service_manager/runner/common/client_util.h" @@ -54,41 +54,6 @@ } #endif -// Should be created and initialized on the main thread and kept alive as long -// a Service is running in the current process. -class ScopedAppContext : public mojo::edk::ProcessDelegate { - public: - ScopedAppContext() - : io_thread_("io_thread"), - wait_for_shutdown_event_( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED) { - mojo::edk::Init(); - io_thread_.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); - mojo::edk::InitIPCSupport(this, io_thread_.task_runner()); - mojo::edk::SetParentPipeHandleFromCommandLine(); - } - - ~ScopedAppContext() override { - mojo::edk::ShutdownIPCSupport(); - wait_for_shutdown_event_.Wait(); - } - - private: - // ProcessDelegate implementation. - void OnShutdownComplete() override { - wait_for_shutdown_event_.Signal(); - } - - base::Thread io_thread_; - - // Used to unblock the main thread on shutdown. - base::WaitableEvent wait_for_shutdown_event_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAppContext); -}; - } // namespace void RunStandaloneService(const StandaloneServiceCallback& callback) { @@ -112,7 +77,17 @@ sandbox = InitializeSandbox(); #endif - ScopedAppContext app_context; + mojo::edk::Init(); + + base::Thread io_thread("io_thread"); + io_thread.StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + + mojo::edk::ScopedIPCSupport ipc_support( + io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); + mojo::edk::SetParentPipeHandleFromCommandLine(); + callback.Run(GetServiceRequestFromCommandLine()); }
diff --git a/services/service_manager/runner/host/service_process_launcher_unittest.cc b/services/service_manager/runner/host/service_process_launcher_unittest.cc index 5fb3827..cb6fd54c 100644 --- a/services/service_manager/runner/host/service_process_launcher_unittest.cc +++ b/services/service_manager/runner/host/service_process_launcher_unittest.cc
@@ -17,7 +17,7 @@ #include "base/run_loop.h" #include "base/threading/thread.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/process_delegate.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "testing/gtest/include/gtest/gtest.h" namespace service_manager { @@ -40,16 +40,6 @@ callback.Run(); } -class ProcessDelegate : public mojo::edk::ProcessDelegate { - public: - ProcessDelegate() {} - ~ProcessDelegate() override {} - - private: - void OnShutdownComplete() override {} - DISALLOW_COPY_AND_ASSIGN(ProcessDelegate); -}; - class ServiceProcessLauncherDelegateImpl : public ServiceProcessLauncher::Delegate { public: @@ -94,8 +84,9 @@ options.message_loop_type = base::MessageLoop::TYPE_IO; io_thread.StartWithOptions(options); - ProcessDelegate delegate; - mojo::edk::InitIPCSupport(&delegate, io_thread.task_runner()); + auto ipc_support = base::MakeUnique<mojo::edk::ScopedIPCSupport>( + io_thread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); base::FilePath test_service_path = base::FilePath(kPackagesPath).AppendASCII(kTestServiceName) @@ -114,7 +105,8 @@ launcher.Join(); blocking_pool->Shutdown(); - mojo::edk::ShutdownIPCSupport(); + ipc_support.reset(); + EXPECT_EQ(1u, service_process_launcher_delegate.get_and_clear_adjust_count()); }
diff --git a/services/service_manager/standalone/context.cc b/services/service_manager/standalone/context.cc index 4ab116c..469af658 100644 --- a/services/service_manager/standalone/context.cc +++ b/services/service_manager/standalone/context.cc
@@ -149,7 +149,7 @@ init_edk_ = !init_params || init_params->init_edk; if (init_edk_) { - mojo::edk::InitIPCSupport(this, io_thread_->task_runner().get()); + mojo::edk::InitIPCSupport(io_thread_->task_runner().get()); #if defined(OS_MACOSX) mojo::edk::SetMachPortProvider(MachBroker::GetInstance()->port_provider()); #endif @@ -243,9 +243,11 @@ return; TRACE_EVENT0("service_manager", "Context::Shutdown"); - // Post a task in case OnShutdownComplete is called synchronously. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(mojo::edk::ShutdownIPCSupport)); + mojo::edk::ShutdownIPCSupport( + base::Bind(IgnoreResult(&base::TaskRunner::PostTask), + base::ThreadTaskRunnerHandle::Get(), FROM_HERE, + base::Bind(&Context::OnShutdownComplete, + base::Unretained(this)))); // We'll quit when we get OnShutdownComplete(). base::RunLoop().Run(); }
diff --git a/services/service_manager/standalone/context.h b/services/service_manager/standalone/context.h index 17f52b6..e9d9aa6e 100644 --- a/services/service_manager/standalone/context.h +++ b/services/service_manager/standalone/context.h
@@ -13,7 +13,6 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "base/values.h" -#include "mojo/edk/embedder/process_delegate.h" #include "services/service_manager/runner/host/service_process_launcher.h" #include "services/service_manager/service_manager.h" #include "services/service_manager/standalone/tracer.h" @@ -32,7 +31,7 @@ constexpr size_t kThreadPoolMaxThreads = 3; // The "global" context for the service manager's main process. -class Context : public mojo::edk::ProcessDelegate { +class Context { public: struct InitParams { InitParams(); @@ -46,7 +45,7 @@ }; Context(); - ~Context() override; + ~Context(); static void EnsureEmbedderIsInitialized(); @@ -63,8 +62,7 @@ ServiceManager* service_manager() { return service_manager_.get(); } private: - // mojo::edk::ProcessDelegate: - void OnShutdownComplete() override; + void OnShutdownComplete(); // Runs the app specified by |name|. void Run(const std::string& name);
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 889b4773..145cea5 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -6282,19 +6282,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:679e", - "os": "Mac-10.10" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -6626,19 +6613,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -6983,19 +6957,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:679e", - "os": "Mac-10.10" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -7355,19 +7316,6 @@ "use_xvfb": false }, { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { "override_compile_targets": [ "tab_capture_end2end_tests_run" ], @@ -7745,20 +7693,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -8107,20 +8041,6 @@ "use_xvfb": false }, { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { "override_compile_targets": [ "tab_capture_end2end_tests_run" ], @@ -8522,20 +8442,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -8935,24 +8841,6 @@ "use_xvfb": false }, { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12" - }, - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { "override_compile_targets": [ "tab_capture_end2end_tests_run" ], @@ -9385,20 +9273,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -9747,20 +9621,6 @@ "use_xvfb": false }, { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { "override_compile_targets": [ "tab_capture_end2end_tests_run" ], @@ -10214,19 +10074,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -10294,20 +10141,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "1002:6821", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [ @@ -10376,20 +10209,6 @@ }, "test": "gles2_conform_test", "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:0fe9", - "hidpi": "1", - "os": "Mac" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false } ], "isolated_scripts": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation index 750c2c4..8231a0f 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -30,9 +30,6 @@ # Encoded bytes received & encoded data length mismatch. crbug.com/551000 http/tests/inspector/network/network-datareceived.html [ Failure ] crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-datareceived.html [ Failure ] -# We don't set the right caching policy in the renderer when DevTools overrides the caching policy in reloads. -crbug.com/551000 http/tests/inspector-protocol/reload-memory-cache.html [ Failure ] -crbug.com/551000 virtual/mojo-loading/http/tests/inspector-protocol/reload-memory-cache.html [ Failure ] # Console error messages are wrongly ordered. crbug.com/551000 http/tests/inspector/console-resource-errors.html [ Failure ] crbug.com/551000 virtual/mojo-loading/http/tests/inspector/console-resource-errors.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process index dcdf36f..a440d4d 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process +++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -92,10 +92,6 @@ crbug.com/611232 virtual/mojo-loading/http/tests/security/contentSecurityPolicy/frame-src-child-frame-navigates-to-blocked-origin.html [ Timeout ] crbug.com/611232 http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed.html [ Failure ] -# https://crbug.com/615156 - Need to make IntersectionObserver work with OOPIFs. -crbug.com/615156 http/tests/intersection-observer/iframe-cross-origin.html [ Failure Timeout ] -crbug.com/615156 virtual/mojo-loading/http/tests/intersection-observer/iframe-cross-origin.html [ Failure Timeout ] - # https://crbug.com/616626 - allow_universal_access_from_file_urls doesn't work with --site-per-process. # https://crbug.com/665058 - EventSender drag-and-drop simulation doesn't support OOPIFs. crbug.com/665058 http/tests/local/drag-over-remote-content.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index 005ce90..5a52109 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -357,8 +357,6 @@ crbug.com/592183 usb/usbDevice.html [ Slow ] -crbug.com/658318 [ Win Debug ] fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html [ Slow ] - crbug.com/594189 virtual/spv2/fast/overflow/lots-of-sibling-inline-boxes.html [ Slow ] crbug.com/611442 imported/wpt/quirks-mode/hashless-hex-color.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour-expected.txt deleted file mode 100644 index ff59ab2..0000000 --- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour-expected.txt +++ /dev/null
@@ -1,172 +0,0 @@ -Check stepping-up and -down for time input fields from renderer. No cases of empty initial values. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -Hours, 1-12 -PASS stepUp("07:00", 1, null, null) is "08:00" -PASS stepDown("07:00", 1, null, null) is "06:00" -PASS stepUp("11:00", 1, null, null) is "00:00" -PASS stepDown("00:00", 1, null, null) is "11:00" -PASS stepUp("06:00", 7200, null, null) is "08:00" -PASS stepDown("06:00", 7200, null, null) is "04:00" -PASS stepUp("10:00", 7200, null, null) is "00:00" -PASS stepDown("00:00", 7200, null, null) is "10:00" -PASS stepUp("07:00", 7200, null, null) is "08:00" -PASS stepDown("07:00", 7200, null, null) is "06:00" -PASS stepUp("06:00", 3601, null, null) is "07:00" -PASS stepDown("06:00", 3601, null, null) is "05:00" -PASS stepUp("06:00", 0, null, null) is "07:00" -PASS stepDown("06:00", 0, null, null) is "05:00" -PASS stepUp("06:00", 86400, null, null) is "00:00" -PASS stepDown("06:00", 86400, null, null) is "00:00" -PASS stepUp("06:00", 36000, null, null) is "07:00" -PASS stepDown("06:00", 36000, null, null) is "05:00" -PASS stepUp("06:00", 7200, "01:00", null) is "07:00" -PASS stepDown("06:00", 7200, "01:00", null) is "05:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowUp"]) is "02:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowDown"]) is "00:00" -PASS getUserAgentShadowTextContent(input) is "12:00 AM" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"]) is "01:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"]) is "11:00" -PASS stepUp("17:00", 1, "17:00", "20:00") is "18:00" -PASS stepDown("17:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("17:00", 1, "15:00", "17:00") is "15:00" -PASS stepDown("17:00", 1, "15:00", "17:00") is "16:00" -PASS stepUp("15:00", 1, "17:00", "20:00") is "17:00" -PASS stepDown("15:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepDown("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepUp("12:00", 1, "12:00", "15:00") is "13:00" -PASS stepDown("12:00", 1, "12:00", "15:00") is "23:00" -PASS stepUp("15:00", 1, "12:00", "15:00") is "16:00" -PASS stepDown("15:00", 1, "12:00", "15:00") is "14:00" -PASS stepUp("12:00", 1, "10:00", "12:00") is "13:00" -PASS stepDown("12:00", 1, "10:00", "12:00") is "23:00" -PASS stepUp("00:00", 1, "00:00", "03:00") is "01:00" -PASS stepDown("00:00", 1, "00:00", "03:00") is "11:00" -PASS stepUp("15:00", 1, "10:00", "15:00") is "16:00" -PASS stepDown("10:00", 1, "10:00", "15:00") is "09:00" -PASS stepUp("17:00", 7200, "17:00", "20:00") is "19:00" -PASS stepDown("17:00", 7200, "17:00", "20:00") is "19:00" -PASS stepUp("17:00", 7200, "17:00", "18:00") is "17:00" -PASS stepDown("17:00", 7200, "17:00", "18:00") is "17:00" -Hours, 0-11 -PASS stepUp("11:00", 1, null, null) is "00:00" -PASS getUserAgentShadowTextContent(input) is "00:00 AM" -PASS stepDown("00:00", 1, null, null) is "11:00" -PASS getUserAgentShadowTextContent(input) is "11:00 AM" -PASS stepUp("23:00", 1, null, null) is "12:00" -PASS getUserAgentShadowTextContent(input) is "00:00 PM" -PASS stepDown("12:00", 1, null, null) is "23:00" -PASS getUserAgentShadowTextContent(input) is "11:00 PM" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowUp"]) is "00:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowDown"]) is "10:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"]) is "01:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"]) is "11:00" -PASS stepUp("17:00", 1, "17:00", "20:00") is "18:00" -PASS stepDown("17:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("17:00", 1, "15:00", "17:00") is "15:00" -PASS stepDown("17:00", 1, "15:00", "17:00") is "16:00" -PASS stepUp("15:00", 1, "17:00", "20:00") is "17:00" -PASS stepDown("15:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepDown("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepUp("12:00", 1, "12:00", "15:00") is "13:00" -PASS stepDown("12:00", 1, "12:00", "15:00") is "15:00" -PASS stepUp("15:00", 1, "12:00", "15:00") is "12:00" -PASS stepDown("15:00", 1, "12:00", "15:00") is "14:00" -PASS stepUp("12:00", 1, "10:00", "12:00") is "13:00" -PASS stepDown("12:00", 1, "10:00", "12:00") is "23:00" -PASS stepUp("00:00", 1, "00:00", "03:00") is "01:00" -PASS stepDown("00:00", 1, "00:00", "03:00") is "03:00" -PASS stepUp("15:00", 1, "10:00", "15:00") is "16:00" -PASS stepDown("10:00", 1, "10:00", "15:00") is "09:00" -PASS stepUp("20:00", 7200, "17:00", "20:00") is "17:00" -PASS stepDown("20:00", 7200, "17:00", "20:00") is "19:00" -Hours, 0-23 -PASS stepUp("07:00", 1, null, null) is "08:00" -PASS stepDown("07:00", 1, null, null) is "06:00" -PASS stepUp("23:00", 1, null, null) is "00:00" -PASS stepDown("00:00", 1, null, null) is "23:00" -PASS stepUp("06:00", 7200, null, null) is "08:00" -PASS stepDown("06:00", 7200, null, null) is "04:00" -PASS stepUp("22:00", 7200, null, null) is "00:00" -PASS stepDown("00:00", 7200, null, null) is "22:00" -PASS stepUp("07:00", 7200, null, null) is "08:00" -PASS stepDown("07:00", 7200, null, null) is "06:00" -PASS stepUp("06:00", 3601, null, null) is "07:00" -PASS stepDown("06:00", 3601, null, null) is "05:00" -PASS stepUp("06:00", 0, null, null) is "07:00" -PASS stepDown("06:00", 0, null, null) is "05:00" -PASS stepUp("06:00", 86400, null, null) is "00:00" -PASS stepDown("06:00", 86400, null, null) is "00:00" -PASS stepUp("06:00", 36000, null, null) is "07:00" -PASS stepDown("06:00", 36000, null, null) is "05:00" -PASS stepUp("06:00", 7200, "01:00", null) is "07:00" -PASS stepDown("06:00", 7200, "01:00", null) is "05:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowUp"]) is "00:00" -PASS getUserAgentShadowTextContent(input) is "00:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowDown"]) is "22:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"]) is "01:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"]) is "23:00" -PASS stepUp("17:00", 1, "17:00", "20:00") is "18:00" -PASS stepDown("17:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("17:00", 1, "15:00", "17:00") is "15:00" -PASS stepDown("17:00", 1, "15:00", "17:00") is "16:00" -PASS stepUp("15:00", 1, "17:00", "20:00") is "17:00" -PASS stepDown("15:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepDown("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepUp("00:00", 1, "00:00", "03:00") is "01:00" -PASS stepDown("00:00", 1, "00:00", "03:00") is "03:00" -PASS stepUp("03:00", 1, "00:00", "03:00") is "00:00" -PASS stepDown("03:00", 1, "00:00", "03:00") is "02:00" -PASS stepUp("12:00", 1, "10:00", "12:00") is "10:00" -PASS stepDown("12:00", 1, "10:00", "12:00") is "11:00" -PASS stepUp("00:00", 1, "00:00", "03:00") is "01:00" -PASS stepDown("00:00", 1, "00:00", "03:00") is "03:00" -PASS stepUp("15:00", 1, "10:00", "15:00") is "10:00" -PASS stepDown("10:00", 1, "10:00", "15:00") is "15:00" -PASS stepUp("20:00", 7200, "17:00", "20:00") is "17:00" -PASS stepDown("20:00", 7200, "17:00", "20:00") is "19:00" -Hours, 1-24 -PASS stepUp("11:00", 1, null, null) is "12:00" -PASS getUserAgentShadowTextContent(input) is "12:00" -PASS stepDown("00:00", 1, null, null) is "23:00" -PASS getUserAgentShadowTextContent(input) is "23:00" -PASS stepUp("23:00", 1, null, null) is "00:00" -PASS getUserAgentShadowTextContent(input) is "24:00" -PASS stepDown("12:00", 1, null, null) is "11:00" -PASS getUserAgentShadowTextContent(input) is "11:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowUp"]) is "02:00" -PASS test("06:00", 7200, null, null, ["Delete", "ArrowDown"]) is "00:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"]) is "01:00" -PASS test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"]) is "23:00" -PASS stepUp("17:00", 1, "17:00", "20:00") is "18:00" -PASS stepDown("17:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("17:00", 1, "15:00", "17:00") is "15:00" -PASS stepDown("17:00", 1, "15:00", "17:00") is "16:00" -PASS stepUp("15:00", 1, "17:00", "20:00") is "17:00" -PASS stepDown("15:00", 1, "17:00", "20:00") is "20:00" -PASS stepUp("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepDown("15:00", 1, "13:00", "13:00") is "13:00" -PASS stepUp("00:00", 1, "00:00", "03:00") is "01:00" -PASS stepDown("00:00", 1, "00:00", "03:00") is "23:00" -PASS stepUp("03:00", 1, "00:00", "03:00") is "04:00" -PASS stepDown("03:00", 1, "00:00", "03:00") is "02:00" -PASS stepUp("12:00", 1, "10:00", "12:00") is "10:00" -PASS stepDown("12:00", 1, "10:00", "12:00") is "11:00" -PASS stepUp("00:00", 1, "00:00", "03:00") is "01:00" -PASS stepDown("00:00", 1, "00:00", "03:00") is "23:00" -PASS stepUp("15:00", 1, "10:00", "15:00") is "10:00" -PASS stepDown("10:00", 1, "10:00", "15:00") is "15:00" -PASS stepUp("17:00", 7200, "17:00", "20:00") is "19:00" -PASS stepDown("17:00", 7200, "17:00", "20:00") is "19:00" -PASS stepUp("17:00", 7200, "17:00", "18:00") is "17:00" -PASS stepDown("17:00", 7200, "17:00", "18:00") is "17:00" - -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html index 84fd85a3..e37bae8 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html +++ b/third_party/WebKit/LayoutTests/fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer-hour.html
@@ -1,237 +1,248 @@ <!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> <script src="../resources/common.js"></script> </head> <body> <script> -description('Check stepping-up and -down for time input fields from renderer. No cases of empty initial values.'); -if (!window.internals) - testFailed('This test requires window.internals.'); - +// We use a single INPUT element for multiple testcases to improve test performance. var input = document.createElement('input'); +input.type = 'time'; document.body.appendChild(input); - -function keyDown(key, modifiers) -{ - if (!window.eventSender) - return; - eventSender.keyDown(key, modifiers); -} +input.focus(); function setDateTimeFormat(pattern) { - getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern); - input.value = ''; // Updates the element for new format + getElementByPseudoId(internals.youngestShadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern); + input.value = ''; // Updates the element for new format } function maybeUpdateAttribute(name, value) { - if (value) { - if (input.getAttribute(name) != value) - input.setAttribute(name, value); - } else { - if (input.hasAttribute(name)) - input.removeAttribute(name); - } + if (value) { + if (input.getAttribute(name) !== value) + input.setAttribute(name, value); + } else { + if (input.hasAttribute(name)) + input.removeAttribute(name); + } } -function setInputAttributes(value, min, max, step) { - input.value = value; - maybeUpdateAttribute('min', min); - maybeUpdateAttribute('max', max); - maybeUpdateAttribute('step', step); +function assert_input_value_with_limits(initial, step, min, max, keySequence, expected, expectedDisplayValue) { + input.value = initial; + maybeUpdateAttribute('min', min); + maybeUpdateAttribute('max', max); + maybeUpdateAttribute('step', step); + + keySequence.forEach(key => { eventSender.keyDown(key); }); + + assert_equals(input.value, expected); + if (expectedDisplayValue) + assert_equals(getUserAgentShadowTextContent(input), expectedDisplayValue); } -function test(value, step, min, max, keySequence) { - setInputAttributes(value, min, max, step); - for (var i = 0; i < keySequence.length; i++) - keyDown(keySequence[i]); - return input.value; +function assert_input_value_with_limits_after_up(initial, step, min, max, expected, expectedDisplayValue) { + assert_input_value_with_limits(initial, step, min, max, ['ArrowUp'], expected, expectedDisplayValue); } -function stepUp(value, step, min, max) { - return test(value, step, min, max, ['ArrowUp']); +function assert_input_value_with_limits_after_down(initial, step, min, max, expected, expectedDisplayValue) { + assert_input_value_with_limits(initial, step, min, max, ['ArrowDown'], expected, expectedDisplayValue); } -function stepDown(value, step, min, max) { - return test(value, step, min, max, ['ArrowDown']); +function assert_input_value_with_limits_after_deleteup(initial, step, min, max, expected, expectedDisplayValue) { + assert_input_value_with_limits(initial, step, min, max, ['Delete', 'ArrowUp'], expected, expectedDisplayValue); } -input.type = 'time'; -input.focus(); +function assert_input_value_with_limits_after_deletedown(initial, step, min, max, expected, expectedDisplayValue) { + assert_input_value_with_limits(initial, step, min, max, ['Delete', 'ArrowDown'], expected, expectedDisplayValue); +} -debug('Hours, 1-12'); -shouldBeEqualToString('stepUp("07:00", 1, null, null)', '08:00'); -shouldBeEqualToString('stepDown("07:00", 1, null, null)', '06:00'); -shouldBeEqualToString('stepUp("11:00", 1, null, null)', '00:00'); -shouldBeEqualToString('stepDown("00:00", 1, null, null)', '11:00'); -shouldBeEqualToString('stepUp("06:00", 7200, null, null)', '08:00'); -shouldBeEqualToString('stepDown("06:00", 7200, null, null)', '04:00'); -shouldBeEqualToString('stepUp("10:00", 7200, null, null)', '00:00'); -shouldBeEqualToString('stepDown("00:00", 7200, null, null)', '10:00'); -shouldBeEqualToString('stepUp("07:00", 7200, null, null)', '08:00'); -shouldBeEqualToString('stepDown("07:00", 7200, null, null)', '06:00'); -shouldBeEqualToString('stepUp("06:00", 3601, null, null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 3601, null, null)', '05:00'); -shouldBeEqualToString('stepUp("06:00", 0, null, null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 0, null, null)', '05:00'); -shouldBeEqualToString('stepUp("06:00", 86400, null, null)', '00:00'); -shouldBeEqualToString('stepDown("06:00", 86400, null, null)', '00:00'); -shouldBeEqualToString('stepUp("06:00", 36000, null, null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 36000, null, null)', '05:00'); -shouldBeEqualToString('stepUp("06:00", 7200, "01:00", null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 7200, "01:00", null)', '05:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowUp"])', '02:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowDown"])', '00:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '12:00 AM'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"])', '01:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"])', '11:00'); -shouldBeEqualToString('stepUp("17:00", 1, "17:00", "20:00")', '18:00'); -shouldBeEqualToString('stepDown("17:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("17:00", 1, "15:00", "17:00")', '15:00'); -shouldBeEqualToString('stepDown("17:00", 1, "15:00", "17:00")', '16:00'); -shouldBeEqualToString('stepUp("15:00", 1, "17:00", "20:00")', '17:00'); -shouldBeEqualToString('stepDown("15:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepDown("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepUp("12:00", 1, "12:00", "15:00")', '13:00'); -shouldBeEqualToString('stepDown("12:00", 1, "12:00", "15:00")', '23:00'); -shouldBeEqualToString('stepUp("15:00", 1, "12:00", "15:00")', '16:00'); -shouldBeEqualToString('stepDown("15:00", 1, "12:00", "15:00")', '14:00'); -shouldBeEqualToString('stepUp("12:00", 1, "10:00", "12:00")', '13:00'); -shouldBeEqualToString('stepDown("12:00", 1, "10:00", "12:00")', '23:00'); -shouldBeEqualToString('stepUp("00:00", 1, "00:00", "03:00")', '01:00'); -shouldBeEqualToString('stepDown("00:00", 1, "00:00", "03:00")', '11:00'); -shouldBeEqualToString('stepUp("15:00", 1, "10:00", "15:00")', '16:00'); -shouldBeEqualToString('stepDown("10:00", 1, "10:00", "15:00")', '09:00'); -shouldBeEqualToString('stepUp("17:00", 7200, "17:00", "20:00")', '19:00'); -shouldBeEqualToString('stepDown("17:00", 7200, "17:00", "20:00")', '19:00'); -shouldBeEqualToString('stepUp("17:00", 7200, "17:00", "18:00")', '17:00'); -shouldBeEqualToString('stepDown("17:00", 7200, "17:00", "18:00")', '17:00'); +function assert_input_value_after_up(initial, step, expected, expectedDisplayValue) { + assert_input_value_with_limits(initial, step, null, null, ['ArrowUp'], expected, expectedDisplayValue); +} -debug('Hours, 0-11'); -setDateTimeFormat('KK:mm a'); -shouldBeEqualToString('stepUp("11:00", 1, null, null)', '00:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '00:00 AM'); -shouldBeEqualToString('stepDown("00:00", 1, null, null)', '11:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '11:00 AM'); -shouldBeEqualToString('stepUp("23:00", 1, null, null)', '12:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '00:00 PM'); -shouldBeEqualToString('stepDown("12:00", 1, null, null)', '23:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '11:00 PM'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowUp"])', '00:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowDown"])', '10:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"])', '01:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"])', '11:00'); -shouldBeEqualToString('stepUp("17:00", 1, "17:00", "20:00")', '18:00'); -shouldBeEqualToString('stepDown("17:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("17:00", 1, "15:00", "17:00")', '15:00'); -shouldBeEqualToString('stepDown("17:00", 1, "15:00", "17:00")', '16:00'); -shouldBeEqualToString('stepUp("15:00", 1, "17:00", "20:00")', '17:00'); -shouldBeEqualToString('stepDown("15:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepDown("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepUp("12:00", 1, "12:00", "15:00")', '13:00'); -shouldBeEqualToString('stepDown("12:00", 1, "12:00", "15:00")', '15:00'); -shouldBeEqualToString('stepUp("15:00", 1, "12:00", "15:00")', '12:00'); -shouldBeEqualToString('stepDown("15:00", 1, "12:00", "15:00")', '14:00'); -shouldBeEqualToString('stepUp("12:00", 1, "10:00", "12:00")', '13:00'); -shouldBeEqualToString('stepDown("12:00", 1, "10:00", "12:00")', '23:00'); -shouldBeEqualToString('stepUp("00:00", 1, "00:00", "03:00")', '01:00'); -shouldBeEqualToString('stepDown("00:00", 1, "00:00", "03:00")', '03:00'); -shouldBeEqualToString('stepUp("15:00", 1, "10:00", "15:00")', '16:00'); -shouldBeEqualToString('stepDown("10:00", 1, "10:00", "15:00")', '09:00'); -shouldBeEqualToString('stepUp("20:00", 7200, "17:00", "20:00")', '17:00'); -shouldBeEqualToString('stepDown("20:00", 7200, "17:00", "20:00")', '19:00'); +function assert_input_value_after_down(initial, step, expected, expectedDisplayValue) { + assert_input_value_with_limits(initial, step, null, null, ['ArrowDown'], expected, expectedDisplayValue); +} -debug('Hours, 0-23'); -setDateTimeFormat('HH:mm'); -shouldBeEqualToString('stepUp("07:00", 1, null, null)', '08:00'); -shouldBeEqualToString('stepDown("07:00", 1, null, null)', '06:00'); -shouldBeEqualToString('stepUp("23:00", 1, null, null)', '00:00'); -shouldBeEqualToString('stepDown("00:00", 1, null, null)', '23:00'); -shouldBeEqualToString('stepUp("06:00", 7200, null, null)', '08:00'); -shouldBeEqualToString('stepDown("06:00", 7200, null, null)', '04:00'); -shouldBeEqualToString('stepUp("22:00", 7200, null, null)', '00:00'); -shouldBeEqualToString('stepDown("00:00", 7200, null, null)', '22:00'); -shouldBeEqualToString('stepUp("07:00", 7200, null, null)', '08:00'); -shouldBeEqualToString('stepDown("07:00", 7200, null, null)', '06:00'); -shouldBeEqualToString('stepUp("06:00", 3601, null, null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 3601, null, null)', '05:00'); -shouldBeEqualToString('stepUp("06:00", 0, null, null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 0, null, null)', '05:00'); -shouldBeEqualToString('stepUp("06:00", 86400, null, null)', '00:00'); -shouldBeEqualToString('stepDown("06:00", 86400, null, null)', '00:00'); -shouldBeEqualToString('stepUp("06:00", 36000, null, null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 36000, null, null)', '05:00'); -shouldBeEqualToString('stepUp("06:00", 7200, "01:00", null)', '07:00'); -shouldBeEqualToString('stepDown("06:00", 7200, "01:00", null)', '05:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowUp"])', '00:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '00:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowDown"])', '22:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"])', '01:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"])', '23:00'); -shouldBeEqualToString('stepUp("17:00", 1, "17:00", "20:00")', '18:00'); -shouldBeEqualToString('stepDown("17:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("17:00", 1, "15:00", "17:00")', '15:00'); -shouldBeEqualToString('stepDown("17:00", 1, "15:00", "17:00")', '16:00'); -shouldBeEqualToString('stepUp("15:00", 1, "17:00", "20:00")', '17:00'); -shouldBeEqualToString('stepDown("15:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepDown("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepUp("00:00", 1, "00:00", "03:00")', '01:00'); -shouldBeEqualToString('stepDown("00:00", 1, "00:00", "03:00")', '03:00'); -shouldBeEqualToString('stepUp("03:00", 1, "00:00", "03:00")', '00:00'); -shouldBeEqualToString('stepDown("03:00", 1, "00:00", "03:00")', '02:00'); -shouldBeEqualToString('stepUp("12:00", 1, "10:00", "12:00")', '10:00'); -shouldBeEqualToString('stepDown("12:00", 1, "10:00", "12:00")', '11:00'); -shouldBeEqualToString('stepUp("00:00", 1, "00:00", "03:00")', '01:00'); -shouldBeEqualToString('stepDown("00:00", 1, "00:00", "03:00")', '03:00'); -shouldBeEqualToString('stepUp("15:00", 1, "10:00", "15:00")', '10:00'); -shouldBeEqualToString('stepDown("10:00", 1, "10:00", "15:00")', '15:00'); -shouldBeEqualToString('stepUp("20:00", 7200, "17:00", "20:00")', '17:00'); -shouldBeEqualToString('stepDown("20:00", 7200, "17:00", "20:00")', '19:00'); +// Hours, 1-12 +test(() => { + assert_exists(window, 'internals'); + assert_exists(window, 'eventSender'); -debug('Hours, 1-24'); -setDateTimeFormat('kk:mm'); -shouldBeEqualToString('stepUp("11:00", 1, null, null)', '12:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '12:00'); -shouldBeEqualToString('stepDown("00:00", 1, null, null)', '23:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '23:00'); -shouldBeEqualToString('stepUp("23:00", 1, null, null)', '00:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '24:00'); -shouldBeEqualToString('stepDown("12:00", 1, null, null)', '11:00'); -shouldBeEqualToString('getUserAgentShadowTextContent(input)', '11:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowUp"])', '02:00'); -shouldBeEqualToString('test("06:00", 7200, null, null, ["Delete", "ArrowDown"])', '00:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowUp"])', '01:00'); -shouldBeEqualToString('test("06:00", 7200, "01:00", null, ["Delete", "ArrowDown"])', '23:00'); -shouldBeEqualToString('stepUp("17:00", 1, "17:00", "20:00")', '18:00'); -shouldBeEqualToString('stepDown("17:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("17:00", 1, "15:00", "17:00")', '15:00'); -shouldBeEqualToString('stepDown("17:00", 1, "15:00", "17:00")', '16:00'); -shouldBeEqualToString('stepUp("15:00", 1, "17:00", "20:00")', '17:00'); -shouldBeEqualToString('stepDown("15:00", 1, "17:00", "20:00")', '20:00'); -shouldBeEqualToString('stepUp("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepDown("15:00", 1, "13:00", "13:00")', '13:00'); -shouldBeEqualToString('stepUp("00:00", 1, "00:00", "03:00")', '01:00'); -shouldBeEqualToString('stepDown("00:00", 1, "00:00", "03:00")', '23:00'); -shouldBeEqualToString('stepUp("03:00", 1, "00:00", "03:00")', '04:00'); -shouldBeEqualToString('stepDown("03:00", 1, "00:00", "03:00")', '02:00'); -shouldBeEqualToString('stepUp("12:00", 1, "10:00", "12:00")', '10:00'); -shouldBeEqualToString('stepDown("12:00", 1, "10:00", "12:00")', '11:00'); -shouldBeEqualToString('stepUp("00:00", 1, "00:00", "03:00")', '01:00'); -shouldBeEqualToString('stepDown("00:00", 1, "00:00", "03:00")', '23:00'); -shouldBeEqualToString('stepUp("15:00", 1, "10:00", "15:00")', '10:00'); -shouldBeEqualToString('stepDown("10:00", 1, "10:00", "15:00")', '15:00'); -shouldBeEqualToString('stepUp("17:00", 7200, "17:00", "20:00")', '19:00'); -shouldBeEqualToString('stepDown("17:00", 7200, "17:00", "20:00")', '19:00'); -shouldBeEqualToString('stepUp("17:00", 7200, "17:00", "18:00")', '17:00'); -shouldBeEqualToString('stepDown("17:00", 7200, "17:00", "18:00")', '17:00'); + assert_input_value_after_up('07:00', 1, '08:00'); + assert_input_value_after_down('07:00', 1, '06:00'); + assert_input_value_after_up('11:00', 1, '00:00'); + assert_input_value_after_down('00:00', 1, '11:00'); + assert_input_value_after_up('06:00', 7200, '08:00'); + assert_input_value_after_down('06:00', 7200, '04:00'); + assert_input_value_after_up('10:00', 7200, '00:00'); + assert_input_value_after_down('00:00', 7200, '10:00'); + assert_input_value_after_up('07:00', 7200, '08:00'); + assert_input_value_after_down('07:00', 7200, '06:00'); + assert_input_value_after_up('06:00', 3601, '07:00'); + assert_input_value_after_down('06:00', 3601, '05:00'); + assert_input_value_after_up('06:00', 0, '07:00'); + assert_input_value_after_down('06:00', 0, '05:00'); + assert_input_value_after_up('06:00', 86400, '00:00'); + assert_input_value_after_down('06:00', 86400, '00:00'); + assert_input_value_after_up('06:00', 36000, '07:00'); + assert_input_value_after_down('06:00', 36000, '05:00'); + assert_input_value_with_limits_after_up('06:00', 7200, '01:00', null, '07:00'); + assert_input_value_with_limits_after_down('06:00', 7200, '01:00', null, '05:00'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '02:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '00:00', '12:00 AM'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '11:00'); + assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00'); + assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00'); + assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00'); + assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00'); + assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_up('12:00', 1, '12:00', '15:00', '13:00'); + assert_input_value_with_limits_after_down('12:00', 1, '12:00', '15:00', '23:00'); + assert_input_value_with_limits_after_up('15:00', 1, '12:00', '15:00', '16:00'); + assert_input_value_with_limits_after_down('15:00', 1, '12:00', '15:00', '14:00'); + assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '13:00'); + assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '23:00'); + assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00'); + assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '11:00'); + assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '16:00'); + assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '09:00'); + assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '20:00', '19:00'); + assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '20:00', '19:00'); + assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '18:00', '17:00'); + assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '18:00', '17:00'); +}, 'Hours, 1-12'); -setDateTimeFormat(''); -debug(''); -document.body.removeChild(input); +// Hours, 0-11 +test(() => { + assert_exists(window, 'internals'); + assert_exists(window, 'eventSender'); + setDateTimeFormat('KK:mm a'); + + assert_input_value_after_up('11:00', 1, '00:00', '00:00 AM'); + assert_input_value_after_down('00:00', 1, '11:00', '11:00 AM'); + assert_input_value_after_up('23:00', 1, '12:00', '00:00 PM'); + assert_input_value_after_down('12:00', 1, '23:00', '11:00 PM'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '00:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '10:00'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '11:00'); + assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00'); + assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00'); + assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00'); + assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00'); + assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_up('12:00', 1, '12:00', '15:00', '13:00'); + assert_input_value_with_limits_after_down('12:00', 1, '12:00', '15:00', '15:00'); + assert_input_value_with_limits_after_up('15:00', 1, '12:00', '15:00', '12:00'); + assert_input_value_with_limits_after_down('15:00', 1, '12:00', '15:00', '14:00'); + assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '13:00'); + assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '23:00'); + assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00'); + assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '03:00'); + assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '16:00'); + assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '09:00'); + assert_input_value_with_limits_after_up('20:00', 7200, '17:00', '20:00', '17:00'); + assert_input_value_with_limits_after_down('20:00', 7200, '17:00', '20:00', '19:00'); +}, 'Hours, 0-11'); + +// Hours, 0-23 +test(() => { + assert_exists(window, 'internals'); + assert_exists(window, 'eventSender'); + setDateTimeFormat('HH:mm'); + + assert_input_value_after_up('07:00', 1, '08:00'); + assert_input_value_after_down('07:00', 1, '06:00'); + assert_input_value_after_up('23:00', 1, '00:00'); + assert_input_value_after_down('00:00', 1, '23:00'); + assert_input_value_after_up('06:00', 7200, '08:00'); + assert_input_value_after_down('06:00', 7200, '04:00'); + assert_input_value_after_up('22:00', 7200, '00:00'); + assert_input_value_after_down('00:00', 7200, '22:00'); + assert_input_value_after_up('07:00', 7200, '08:00'); + assert_input_value_after_down('07:00', 7200, '06:00'); + assert_input_value_after_up('06:00', 3601, '07:00'); + assert_input_value_after_down('06:00', 3601, '05:00'); + assert_input_value_after_up('06:00', 0, '07:00'); + assert_input_value_after_down('06:00', 0, '05:00'); + assert_input_value_after_up('06:00', 86400, '00:00'); + assert_input_value_after_down('06:00', 86400, '00:00'); + assert_input_value_after_up('06:00', 36000, '07:00'); + assert_input_value_after_down('06:00', 36000, '05:00'); + assert_input_value_with_limits_after_up('06:00', 7200, '01:00', null, '07:00'); + assert_input_value_with_limits_after_down('06:00', 7200, '01:00', null, '05:00'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '00:00', '00:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '22:00'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '23:00'); + assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00'); + assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00'); + assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00'); + assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00'); + assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00'); + assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '03:00'); + assert_input_value_with_limits_after_up('03:00', 1, '00:00', '03:00', '00:00'); + assert_input_value_with_limits_after_down('03:00', 1, '00:00', '03:00', '02:00'); + assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '10:00'); + assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '11:00'); + assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00'); + assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '03:00'); + assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '10:00'); + assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '15:00'); + assert_input_value_with_limits_after_up('20:00', 7200, '17:00', '20:00', '17:00'); + assert_input_value_with_limits_after_down('20:00', 7200, '17:00', '20:00', '19:00'); +}, 'Hours, 0-23'); + +// Hours, 1-24 +test(() => { + assert_exists(window, 'internals'); + assert_exists(window, 'eventSender'); + setDateTimeFormat('kk:mm'); + + assert_input_value_after_up('11:00', 1, '12:00', '12:00'); + assert_input_value_after_down('00:00', 1, '23:00', '23:00'); + assert_input_value_after_up('23:00', 1, '00:00', '24:00'); + assert_input_value_after_down('12:00', 1, '11:00', '11:00'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '02:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '00:00'); + assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00'); + assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '23:00'); + assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00'); + assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00'); + assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00'); + assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00'); + assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00'); + assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00'); + assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00'); + assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '23:00'); + assert_input_value_with_limits_after_up('03:00', 1, '00:00', '03:00', '04:00'); + assert_input_value_with_limits_after_down('03:00', 1, '00:00', '03:00', '02:00'); + assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '10:00'); + assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '11:00'); + assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00'); + assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '23:00'); + assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '10:00'); + assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '15:00'); + assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '20:00', '19:00'); + assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '20:00', '19:00'); + assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '18:00', '17:00'); + assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '18:00', '17:00'); +}, 'Hours, 1-24'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/parser/inselect-tokenization.html b/third_party/WebKit/LayoutTests/fast/parser/inselect-tokenization.html new file mode 100644 index 0000000..997cfbd --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/parser/inselect-tokenization.html
@@ -0,0 +1,106 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<body> +<script> + /************************************************************************ + * Helper functions! + */ + function createFrame(markup) { + var i = document.createElement('iframe'); + i.srcdoc = markup; + return i; + } + + function appendAndWaitForLoad(test, frame) { + return new Promise((resolve, reject) => { + frame.onload = test.step_func(_ => { + frame.onload = null; + resolve(); + }); + document.body.appendChild(frame); + }); + } + + function assert_select(test, frame, value) { + var select = frame.contentDocument.querySelector('select'); + assert_equals(select.value, value, 'select'); + } + + function assert_element_innerText(test, frame, name, value) { + var el = frame.contentDocument.querySelector(name); + if (value === null || value === undefined) + assert_equals(el, null, name); + else + assert_equals(el.innerText, value, name); + } + + /************************************************************************ + * The actual tests! + */ + var tests = [ + // <input>, <keygen>, and <textarea> close <select>, so <plaintext> works. + ]; + + var elementsToIgnore = [ + "iframe", + "noembed", + "noframes", + "noscript", + "plaintext", + "style", + "xmp", + ]; + + elementsToIgnore.forEach(el => { + tests.push( + { + markup: `<form><select><option><${el}>1<element></element>`, + select: "1", + innerText: null, + name: el + }, { + markup: `<form><select><option>1<${el}>2<element></element>`, + select: "12", + innerText: null, + name: el + }, { + markup: `<form><select><option>1<${el}>2<element></element>3`, + select: "123", + innerText: null, + name: el + }); + if (el != "iframe") { + tests.push( + { + markup: `<form><select><option>1<input><${el}>2<element></element>`, + select: "1", + innerText: "2<element></element>", + name: el + }, { + markup: `<form><select><option>1<keygen><${el}>2<element></element>`, + select: "1", + innerText: "2<element></element>", + name: el + }, { + markup: `<form><select><option>1<textarea></textarea><${el}>2<element></element>`, + select: "1", + innerText: "2<element></element>", + name: el + }); + } + }); + + + tests.forEach(test => { + async_test(t => { + var i = createFrame(test.markup); + + appendAndWaitForLoad(t, i) + .then(t.step_func_done(_ => { + assert_select(t, i, test.select); + assert_element_innerText(t, i, test.name, test.innerText); + })); + }, test.markup); + }); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/option.html b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/option.html new file mode 100644 index 0000000..925e8a5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/option.html
@@ -0,0 +1,52 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/helper.js"></script> +<body> +<script> + + var tests = [ + ` + <form action="/security/resources/postmessage-post.php" method="post"> + <input type="submit"> + <select name="dangling"><option> + `, + ` + <div> + <form action="/security/resources/postmessage-post.php" method="post"> + <input type="submit"> + <select name="dangling"><option> + `, + ` + <form action="/security/resources/postmessage-post.php" method="post" id="form"> + <input type="submit"> + </form> + <select name="dangling" form="form"><option> + `, + ` + <form action="/security/resources/postmessage-post.php" method="post"> + <input type="submit"> + <select name="dangling"><option label="yay"> + `, + ` + <div> + <form action="/security/resources/postmessage-post.php" method="post"> + <input type="submit"> + <select name="dangling"><option label="yay"> + `, + ` + <form action="/security/resources/postmessage-post.php" method="post" id="form"> + <input type="submit"> + </form> + <select name="dangling" form="form"><option label="yay"> + ` + ]; + + tests.forEach(markup => { + async_test(t => { + var i = createFrame(`${markup}sekrit<element attribute></element>`); + assert_no_submission(t, i); + }, markup.replace(/[\n\r]/g, '')); + }); +</script> +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/resources/helper.js b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/resources/helper.js new file mode 100644 index 0000000..7d5ad6d --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/resources/helper.js
@@ -0,0 +1,37 @@ +function assert_no_message_from_frame(test, frame) { + window.addEventListener("message", test.step_func(e => { + assert_not_equals(e.source, frame.contentWindow); + })); +} + +function appendAndSubmit(test, frame) { + return new Promise((resolve, reject) => { + frame.onload = test.step_func(_ => { + frame.onload = null; + frame.contentDocument.querySelector('form').addEventListener("error", _ => { + resolve("error"); + }); + frame.contentDocument.querySelector('form').addEventListener("submit", _ => { + resolve("submit"); + }); + frame.contentDocument.querySelector('[type=submit]').click(); + }); + document.body.appendChild(frame); + }); +} + +function assert_no_submission(test, frame) { + assert_no_message_from_frame(test, frame); + + appendAndSubmit(test, frame) + .then(test.step_func_done(result => { + assert_equals(result, "error"); + frame.remove(); + })); +} + +function createFrame(markup) { + var i = document.createElement('iframe'); + i.srcdoc = `${markup}sekrit`; + return i; +}
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/textarea.html b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/textarea.html new file mode 100644 index 0000000..27558821 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/textarea.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/helper.js"></script> +<body> +<script> + + var tests = [ + ` + <form action="/security/resources/postmessage-post.php" method="post"> + <input type="submit"> + <textarea name="dangling"> + `, + ` + <div> + <form action="/security/resources/postmessage-post.php" method="post"> + <input type="submit"> + <textarea name="dangling"> + `, + ` + <form action="/security/resources/postmessage-post.php" method="post" id="form"> + <input type="submit"> + </form> + <textarea name="dangling" form="form"> + ` + ]; + + tests.forEach(markup => { + async_test(t => { + var i = createFrame(`${markup}sekrit<element attribute></element>`); + assert_no_submission(t, i); + }, markup.replace(/[\n\r]/g, '')); + }); +</script> +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/resources/postmessage-post.php b/third_party/WebKit/LayoutTests/http/tests/security/resources/postmessage-post.php new file mode 100644 index 0000000..5f2c3f4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/resources/postmessage-post.php
@@ -0,0 +1,5 @@ +<script> +top.postMessage(<?php + echo json_encode($_POST); +?>, "*"); +</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp index a5d8814..36bdec18 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -195,6 +195,15 @@ case v8::Isolate::kFunctionConstructorReturnedUndefined: blinkFeature = UseCounter::V8FunctionConstructorReturnedUndefined; break; + case v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy: + blinkFeature = UseCounter::V8AssigmentExpressionLHSIsCallInSloppy; + break; + case v8::Isolate::kAssigmentExpressionLHSIsCallInStrict: + blinkFeature = UseCounter::V8AssigmentExpressionLHSIsCallInStrict; + break; + case v8::Isolate::kPromiseConstructorReturnedUndefined: + blinkFeature = UseCounter::V8PromiseConstructorReturnedUndefined; + break; default: // This can happen if V8 has added counters that this version of Blink // does not know about. It's harmless.
diff --git a/third_party/WebKit/Source/core/dom/CSSSelectorWatch.cpp b/third_party/WebKit/Source/core/dom/CSSSelectorWatch.cpp index e7e1182..2570be9c 100644 --- a/third_party/WebKit/Source/core/dom/CSSSelectorWatch.cpp +++ b/third_party/WebKit/Source/core/dom/CSSSelectorWatch.cpp
@@ -76,13 +76,13 @@ m_callbackSelectorChangeTimer.startOneShot(0, BLINK_FROM_HERE); return; } - if (host()->frame()) { + if (supplementable()->frame()) { Vector<String> addedSelectors; Vector<String> removedSelectors; copyToVector(m_addedSelectors, addedSelectors); copyToVector(m_removedSelectors, removedSelectors); - host()->frame()->loader().client()->selectorMatchChanged(addedSelectors, - removedSelectors); + supplementable()->frame()->loader().client()->selectorMatchChanged( + addedSelectors, removedSelectors); } m_addedSelectors.clear(); m_removedSelectors.clear(); @@ -164,7 +164,7 @@ m_watchedCallbackSelectors.push_back( StyleRule::create(std::move(selectorList), callbackPropertySet)); } - host()->styleEngine().watchedSelectorsChanged(); + supplementable()->styleEngine().watchedSelectorsChanged(); } DEFINE_TRACE(CSSSelectorWatch) {
diff --git a/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp b/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp index 3abaf1db..850185e 100644 --- a/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp
@@ -72,8 +72,8 @@ : Supplement<Document>(document) {} void DocumentParserTiming::notifyDocumentParserTimingChanged() { - if (host()->loader()) - host()->loader()->didChangePerformanceTiming(); + if (supplementable()->loader()) + supplementable()->loader()->didChangePerformanceTiming(); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 19b5a0a..dff9ec6c 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -52,6 +52,8 @@ #include "core/frame/Location.h" #include "core/frame/PageScaleConstraintsSet.h" #include "core/frame/PerformanceMonitor.h" +#include "core/frame/RemoteFrame.h" +#include "core/frame/RemoteFrameView.h" #include "core/frame/Settings.h" #include "core/frame/VisualViewport.h" #include "core/html/HTMLFrameElement.h" @@ -109,6 +111,7 @@ #include "platform/geometry/DoubleRect.h" #include "platform/geometry/FloatRect.h" #include "platform/geometry/LayoutRect.h" +#include "platform/geometry/TransformState.h" #include "platform/graphics/GraphicsContext.h" #include "platform/graphics/GraphicsLayer.h" #include "platform/graphics/GraphicsLayerDebugInfo.h" @@ -4931,4 +4934,62 @@ return reasons; } +void FrameView::setViewportIntersectionFromParent( + const IntRect& viewportIntersection) { + if (m_remoteViewportIntersection != viewportIntersection) { + m_remoteViewportIntersection = viewportIntersection; + scheduleAnimation(); + } +} + +IntRect FrameView::remoteViewportIntersection() { + IntRect intersection(m_remoteViewportIntersection); + intersection.move(scrollOffsetInt()); + return intersection; +} + +void FrameView::mapQuadToAncestorFrameIncludingScrollOffset( + LayoutRect& rect, + const LayoutObject* descendant, + const LayoutView* ancestor, + MapCoordinatesFlags mode) { + FloatQuad mappedQuad = descendant->localToAncestorQuad( + FloatQuad(FloatRect(rect)), ancestor, mode); + rect = LayoutRect(mappedQuad.boundingBox()); + + // localToAncestorQuad accounts for scroll offset if it encounters a remote + // frame in the ancestor chain, otherwise it needs to be added explicitly. + if (frame().localFrameRoot() == frame().tree().top() || + (ancestor && + ancestor->frame()->localFrameRoot() == frame().localFrameRoot())) { + FrameView* ancestorView = + (ancestor ? ancestor->frameView() + : toLocalFrame(frame().tree().top())->view()); + LayoutSize scrollPosition = LayoutSize(ancestorView->getScrollOffset()); + rect.move(-scrollPosition); + } +} + +bool FrameView::mapToVisualRectInTopFrameSpace(LayoutRect& rect) { + // This is the top-level frame, so no mapping necessary. + if (m_frame->isMainFrame()) + return true; + + LayoutRect viewportIntersectionRect(remoteViewportIntersection()); + rect.intersect(viewportIntersectionRect); + if (rect.isEmpty()) + return false; + return true; +} + +void FrameView::applyTransformForTopFrameSpace(TransformState& transformState) { + // This is the top-level frame, so no mapping necessary. + if (m_frame->isMainFrame()) + return; + + LayoutRect viewportIntersectionRect(remoteViewportIntersection()); + transformState.move( + LayoutSize(-viewportIntersectionRect.x(), -viewportIntersectionRect.y())); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h index fb210b8..983b3282 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.h +++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -31,6 +31,7 @@ #include "core/frame/FrameViewAutoSizeInfo.h" #include "core/frame/LayoutSubtreeRootList.h" #include "core/frame/RootFrameViewport.h" +#include "core/layout/MapCoordinatesFlags.h" #include "core/layout/ScrollAnchor.h" #include "core/paint/FirstMeaningfulPaintDetector.h" #include "core/paint/ObjectPaintProperties.h" @@ -87,6 +88,7 @@ class Page; class ScrollingCoordinator; class TracedValue; +class TransformState; struct AnnotatedRegionValue; struct CompositedSelection; @@ -795,6 +797,28 @@ bool hasVisibleSlowRepaintViewportConstrainedObjects() const; + // Called on a view for a LocalFrame with a RemoteFrame parent. This makes + // viewport intersection available that accounts for remote ancestor frames + // and their respective scroll positions, clips, etc. + void setViewportIntersectionFromParent(const IntRect&); + IntRect remoteViewportIntersection(); + + // This method uses localToAncestorQuad to map a rect into an ancestor's + // coordinate space, while guaranteeing that the top-level scroll offset + // is accounted for. This is needed because LayoutView::mapLocalToAncestor() + // implicitly includes the ancestor frame's scroll offset when there is + // a remote frame in the ancestor chain, but does not include it when + // there are only local frames in the frame tree. + void mapQuadToAncestorFrameIncludingScrollOffset( + LayoutRect&, + const LayoutObject* descendant, + const LayoutView* ancestor, + MapCoordinatesFlags mode); + + bool mapToVisualRectInTopFrameSpace(LayoutRect&); + + void applyTransformForTopFrameSpace(TransformState&); + protected: // Scroll the content via the compositor. bool scrollContentsFastPath(const IntSize& scrollDelta); @@ -1145,6 +1169,8 @@ Member<ElementVisibilityObserver> m_visibilityObserver; + IntRect m_remoteViewportIntersection; + // For testing. struct ObjectPaintInvalidation { String name;
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp index 652f833..1c5816e4f 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -137,15 +137,6 @@ client()->forwardInputEvent(event); } -void RemoteFrame::frameRectsChanged(const IntRect& frameRect) { - client()->frameRectsChanged(frameRect); -} - -void RemoteFrame::visibilityChanged(bool visible) { - if (client()) - client()->visibilityChanged(visible); -} - void RemoteFrame::setView(RemoteFrameView* view) { // Oilpan: as RemoteFrameView performs no finalization actions, // no explicit dispose() of it needed here. (cf. FrameView::dispose().)
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h index 412ec72e8..bf3a09a 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.h +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -13,7 +13,6 @@ namespace blink { class Event; -class IntRect; class LocalFrame; class RemoteFrameClient; class RemoteFrameView; @@ -48,10 +47,6 @@ // process. See http://crbug.com/339659. void forwardInputEvent(Event*); - void frameRectsChanged(const IntRect& frameRect); - - void visibilityChanged(bool visible); - void setWebLayer(WebLayer*); WebLayer* webLayer() const { return m_webLayer; }
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameClient.h b/third_party/WebKit/Source/core/frame/RemoteFrameClient.h index d1badcc..d1cec960 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrameClient.h +++ b/third_party/WebKit/Source/core/frame/RemoteFrameClient.h
@@ -39,6 +39,9 @@ virtual void frameRectsChanged(const IntRect& frameRect) = 0; + virtual void updateRemoteViewportIntersection( + const IntRect& viewportIntersection) = 0; + virtual void advanceFocus(WebFocusType, LocalFrame* source) = 0; virtual void visibilityChanged(bool visible) = 0;
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp b/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp index d73ac0a..fb2ad9df 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp
@@ -4,9 +4,13 @@ #include "core/frame/RemoteFrameView.h" +#include "core/dom/IntersectionObserverEntry.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/frame/RemoteFrame.h" +#include "core/frame/RemoteFrameClient.h" #include "core/html/HTMLFrameOwnerElement.h" +#include "core/layout/LayoutView.h" #include "core/layout/api/LayoutPartItem.h" namespace blink { @@ -29,6 +33,41 @@ return view; } +void RemoteFrameView::updateRemoteViewportIntersection() { + if (!m_remoteFrame->ownerLayoutObject()) + return; + + FrameView* localRootView = + toLocalFrame(m_remoteFrame->tree().parent())->localFrameRoot()->view(); + if (!localRootView) + return; + + // Start with rect in remote frame's coordinate space. Then + // mapToVisualRectInAncestorSpace will move it to the local root's coordinate + // space and account for any clip from containing elements such as a + // scrollable div. Passing nullptr as an argument to + // mapToVisualRectInAncestorSpace causes it to be clipped to the viewport, + // even if there are RemoteFrame ancestors in the frame tree. + LayoutRect rect(0, 0, frameRect().width(), frameRect().height()); + rect.move(m_remoteFrame->ownerLayoutObject()->contentBoxOffset()); + if (!m_remoteFrame->ownerLayoutObject()->mapToVisualRectInAncestorSpace( + nullptr, rect)) + return; + IntRect rootVisibleRect = localRootView->visibleContentRect(); + IntRect viewportIntersection(rect); + viewportIntersection.intersect(rootVisibleRect); + viewportIntersection.move(-localRootView->scrollOffsetInt()); + + // Translate the intersection rect from the root frame's coordinate space + // to the remote frame's coordinate space. + viewportIntersection = convertFromRootFrame(viewportIntersection); + if (viewportIntersection != m_lastViewportIntersection) { + m_remoteFrame->client()->updateRemoteViewportIntersection( + viewportIntersection); + } + m_lastViewportIntersection = viewportIntersection; +} + void RemoteFrameView::dispose() { HTMLFrameOwnerElement* ownerElement = m_remoteFrame->deprecatedLocalOwner(); // ownerElement can be null during frame swaps, because the @@ -68,7 +107,9 @@ if (parent() && parent()->isFrameView()) newRect = parent()->convertToRootFrame( toFrameView(parent())->contentsToFrame(newRect)); - m_remoteFrame->frameRectsChanged(newRect); + m_remoteFrame->client()->frameRectsChanged(newRect); + + updateRemoteViewportIntersection(); } void RemoteFrameView::hide() { @@ -76,7 +117,7 @@ Widget::hide(); - m_remoteFrame->visibilityChanged(false); + m_remoteFrame->client()->visibilityChanged(false); } void RemoteFrameView::show() { @@ -84,7 +125,7 @@ Widget::show(); - m_remoteFrame->visibilityChanged(true); + m_remoteFrame->client()->visibilityChanged(true); } void RemoteFrameView::setParentVisible(bool visible) { @@ -95,7 +136,7 @@ if (!isSelfVisible()) return; - m_remoteFrame->visibilityChanged(isVisible()); + m_remoteFrame->client()->visibilityChanged(isVisible()); } DEFINE_TRACE(RemoteFrameView) {
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameView.h b/third_party/WebKit/Source/core/frame/RemoteFrameView.h index 6f243f4..c117abb 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrameView.h +++ b/third_party/WebKit/Source/core/frame/RemoteFrameView.h
@@ -28,14 +28,10 @@ } void dispose() override; - // Override to notify remote frame that its viewport size has changed. void frameRectsChanged() override; - void invalidateRect(const IntRect&) override; - void setFrameRect(const IntRect&) override; - void hide() override; void show() override; void setParentVisible(bool) override; @@ -45,11 +41,15 @@ private: explicit RemoteFrameView(RemoteFrame*); + void updateRemoteViewportIntersection(); + // The properties and handling of the cycle between RemoteFrame // and its RemoteFrameView corresponds to that between LocalFrame // and FrameView. Please see the FrameView::m_frame comment for // details. Member<RemoteFrame> m_remoteFrame; + + IntRect m_lastViewportIntersection; }; DEFINE_TYPE_CASTS(RemoteFrameView,
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index e0b1604..9a5a774a 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1431,6 +1431,10 @@ BaseWithNewlinesInTarget = 1761, BaseWithOpenBracketInTarget = 1762, BaseWouldBeBlockedByDefaultSrc = 1763, + V8AssigmentExpressionLHSIsCallInSloppy = 1764, + V8AssigmentExpressionLHSIsCallInStrict = 1765, + V8PromiseConstructorReturnedUndefined = 1766, + FormSubmittedWithUnclosedFormControl = 1767, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp index ba4a446..65461fc8 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
@@ -58,7 +58,8 @@ m_willValidate(true), m_isValid(true), m_validityIsDirty(false), - m_wasFocusedByMouse(false) { + m_wasFocusedByMouse(false), + m_blocksFormSubmission(false) { setHasCustomStyleCallbacks(); }
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.h b/third_party/WebKit/Source/core/html/HTMLFormControlElement.h index 3902398..308b763 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.h +++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.h
@@ -132,6 +132,9 @@ FormAssociated* toFormAssociatedOrNull() override { return this; }; void associateWith(HTMLFormElement*) override; + bool blocksFormSubmission() const { return m_blocksFormSubmission; } + void setBlocksFormSubmission(bool value) { m_blocksFormSubmission = value; } + protected: HTMLFormControlElement(const QualifiedName& tagName, Document&); @@ -207,6 +210,7 @@ bool m_validityIsDirty : 1; bool m_wasFocusedByMouse : 1; + bool m_blocksFormSubmission : 1; }; inline bool isHTMLFormControlElement(const Element& element) {
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp index 8385afd..be254a2cb 100644 --- a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
@@ -291,6 +291,26 @@ return; } + // https://github.com/whatwg/html/issues/2253 + for (const auto& element : listedElements()) { + if (element->isFormControlElement() && + toHTMLFormControlElement(element)->blocksFormSubmission()) { + UseCounter::count(document(), + UseCounter::FormSubmittedWithUnclosedFormControl); + if (RuntimeEnabledFeatures::unclosedFormControlIsInvalidEnabled()) { + String tagName = toHTMLFormControlElement(element)->tagName(); + document().addConsoleMessage(ConsoleMessage::create( + SecurityMessageSource, ErrorMessageLevel, + "Form submission failed, as the <" + tagName + "> element named " + "'" + element->name() + "' was implicitly closed by reaching " + "the end of the file. Please add an explicit end tag " + "('</" + tagName + ">')")); + dispatchEvent(Event::create(EventTypeNames::error)); + return; + } + } + } + bool skipValidation = !document().page() || noValidate(); DCHECK(event); if (submitButton && submitButton->formNoValidate())
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp b/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp index 29b41c8..e6f23d6e 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
@@ -31,6 +31,8 @@ #include "core/SVGNames.h" #include "core/dom/Element.h" #include "core/html/HTMLElement.h" +#include "core/html/HTMLFormControlElement.h" +#include "core/html/HTMLSelectElement.h" namespace blink { @@ -163,8 +165,11 @@ m_stackDepth = 0; while (m_top) { Node& node = *topNode(); - if (node.isElementNode()) + if (node.isElementNode()) { toElement(node).finishParsingChildren(); + if (isHTMLSelectElement(node)) + toHTMLFormControlElement(node).setBlocksFormSubmission(true); + } m_top = m_top->releaseNext(); } }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp index 16fb629..b7cec906 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
@@ -37,6 +37,7 @@ #include "core/dom/DocumentFragment.h" #include "core/dom/ElementTraversal.h" #include "core/frame/UseCounter.h" +#include "core/html/HTMLFormControlElement.h" #include "core/html/HTMLFormElement.h" #include "core/html/HTMLTemplateElement.h" #include "core/html/parser/AtomicHTMLToken.h" @@ -2430,17 +2431,21 @@ defaultForInTableText(); processEndOfFile(token); return; - case TextMode: + case TextMode: { parseError(token); if (m_tree.currentStackItem()->hasTagName(scriptTag)) { // Mark the script element as "already started". DVLOG(1) << "Not implemented."; } + Element* el = m_tree.openElements()->top(); + if (isHTMLTextAreaElement(el)) + toHTMLFormControlElement(el)->setBlocksFormSubmission(true); m_tree.openElements()->pop(); ASSERT(m_originalInsertionMode != TextMode); setInsertionMode(m_originalInsertionMode); processEndOfFile(token); return; + } case TemplateContentsMode: if (processEndOfFileForInTemplateContents(token)) return;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp index d23ba61..aa8d081 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.cpp
@@ -92,9 +92,17 @@ threadSafeMatch(tagName, MathMLNames::mtextTag); } +static bool tokenExitsInSelect(const CompactHTMLToken& token) { + // https://html.spec.whatwg.org/#parsing-main-inselect + const String& tagName = token.data(); + return threadSafeMatch(tagName, inputTag) || + threadSafeMatch(tagName, keygenTag) || + threadSafeMatch(tagName, textareaTag); +} + HTMLTreeBuilderSimulator::HTMLTreeBuilderSimulator( const HTMLParserOptions& options) - : m_options(options) { + : m_options(options), m_inSelectInsertionMode(false) { m_namespaceStack.push_back(HTML); } @@ -140,20 +148,38 @@ if (threadSafeMatch(tagName, textareaTag) || threadSafeMatch(tagName, titleTag)) { tokenizer->setState(HTMLTokenizer::RCDATAState); - } else if (threadSafeMatch(tagName, plaintextTag)) { - tokenizer->setState(HTMLTokenizer::PLAINTEXTState); } else if (threadSafeMatch(tagName, scriptTag)) { tokenizer->setState(HTMLTokenizer::ScriptDataState); simulatedToken = ScriptStart; - } else if (threadSafeMatch(tagName, styleTag) || - threadSafeMatch(tagName, iframeTag) || - threadSafeMatch(tagName, xmpTag) || - (threadSafeMatch(tagName, noembedTag) && - m_options.pluginsEnabled) || - threadSafeMatch(tagName, noframesTag) || - (threadSafeMatch(tagName, noscriptTag) && - m_options.scriptEnabled)) { - tokenizer->setState(HTMLTokenizer::RAWTEXTState); + } else if (!m_inSelectInsertionMode) { + // If we're in the "in select" insertion mode, all of these tags are + // ignored, so we shouldn't change the tokenizer state: + // https://html.spec.whatwg.org/#parsing-main-inselect + if (threadSafeMatch(tagName, plaintextTag) && + !m_inSelectInsertionMode) { + tokenizer->setState(HTMLTokenizer::PLAINTEXTState); + } else if (threadSafeMatch(tagName, styleTag) || + threadSafeMatch(tagName, iframeTag) || + threadSafeMatch(tagName, xmpTag) || + (threadSafeMatch(tagName, noembedTag) && + m_options.pluginsEnabled) || + threadSafeMatch(tagName, noframesTag) || + (threadSafeMatch(tagName, noscriptTag) && + m_options.scriptEnabled)) { + tokenizer->setState(HTMLTokenizer::RAWTEXTState); + } + } + + // We need to track whether we're in the "in select" insertion mode + // in order to determine whether '<plaintext>' will put the tokenizer + // into PLAINTEXTState, and whether '<xmp>' and others will consume + // textual content. + // + // https://html.spec.whatwg.org/#parsing-main-inselect + if (threadSafeMatch(tagName, selectTag)) { + m_inSelectInsertionMode = true; + } else if (m_inSelectInsertionMode && tokenExitsInSelect(token)) { + m_inSelectInsertionMode = false; } } } @@ -169,12 +195,15 @@ (m_namespaceStack.contains(SVG) && m_namespaceStack.back() == HTML && tokenExitsSVG(token)) || (m_namespaceStack.contains(MathML) && m_namespaceStack.back() == HTML && - tokenExitsMath(token))) + tokenExitsMath(token))) { m_namespaceStack.pop_back(); + } if (threadSafeMatch(tagName, scriptTag)) { if (!inForeignContent()) tokenizer->setState(HTMLTokenizer::DataState); return ScriptEnd; + } else if (threadSafeMatch(tagName, selectTag)) { + m_inSelectInsertionMode = false; } }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h index d8027db..420eb21 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilderSimulator.h
@@ -61,6 +61,7 @@ HTMLParserOptions m_options; State m_namespaceStack; + bool m_inSelectInsertionMode; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp b/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp index 8274879..d8c9a89 100644 --- a/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp +++ b/third_party/WebKit/Source/core/layout/IntersectionGeometry.cpp
@@ -109,13 +109,10 @@ } void IntersectionGeometry::initializeRootRect() { - // TODO(szager): In OOPIF, m_root will be the LayoutView of the - // localFrameRoot(). Once viewport intersection support lands, - // add a call to mapToVisualRectInAncestorSpace to map the rect up to - // top-level frame coordinates. if (m_root->isLayoutView()) { m_rootRect = LayoutRect(toLayoutView(m_root)->frameView()->visibleContentRect()); + m_root->mapToVisualRectInAncestorSpace(nullptr, m_rootRect); } else if (m_root->isBox() && m_root->hasOverflowClip()) { m_rootRect = LayoutRect(toLayoutBox(m_root)->contentBoxRect()); } else { @@ -145,11 +142,10 @@ void IntersectionGeometry::clipToRoot() { // Map and clip rect into root element coordinates. // TODO(szager): the writing mode flipping needs a test. - // TODO(szager): Once the OOPIF viewport intersection code lands, - // use nullptr for ancestor to map to the top frame. LayoutBox* ancestor = toLayoutBox(m_root); m_doesIntersect = m_target->mapToVisualRectInAncestorSpace( - ancestor, m_intersectionRect, EdgeInclusive); + (rootIsImplicit() ? nullptr : ancestor), m_intersectionRect, + EdgeInclusive); if (ancestor && ancestor->hasOverflowClip()) m_intersectionRect.move(-ancestor->scrolledContentOffset()); if (!m_doesIntersect) @@ -169,14 +165,10 @@ } void IntersectionGeometry::mapRootRectToRootFrameCoordinates() { - Document& rootDocument = m_root->document(); - if (!rootIsImplicit()) - mapRectUpToDocument(m_rootRect, *m_root, rootDocument); - // TODO(szager): When OOPIF support lands, this scroll offset adjustment - // will probably be wrong. - LayoutSize scrollPosition = - LayoutSize(rootDocument.view()->getScrollOffset()); - m_rootRect.move(-scrollPosition); + m_root->frameView()->mapQuadToAncestorFrameIncludingScrollOffset( + m_rootRect, m_root, + rootIsImplicit() ? nullptr : m_root->document().layoutView(), + UseTransforms | ApplyContainerFlip); } void IntersectionGeometry::mapIntersectionRectToTargetFrameCoordinates() {
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp index 640871b..58d135e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -343,6 +343,8 @@ transformState.move(parentDocLayoutItem.contentBoxOffset()); parentDocLayoutItem.mapLocalToAncestor(ancestor, transformState, mode); + } else { + frameView()->applyTransformForTopFrameSpace(transformState); } } } @@ -463,16 +465,15 @@ rect.move(offsetForFixedPosition(true)); // Apply our transform if we have one (because of full page zooming). - if (!ancestor && layer() && layer()->transform()) + if (layer() && layer()->transform()) rect = layer()->transform()->mapRect(rect); - ASSERT(ancestor); if (ancestor == this) return true; Element* owner = document().localOwner(); if (!owner) - return true; + return frameView()->mapToVisualRectInTopFrameSpace(rect); if (LayoutBox* obj = owner->layoutBox()) { if (!(mode & InputIsInFrameCoordinates)) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.h b/third_party/WebKit/Source/core/layout/LayoutView.h index c683ff2..4faa7b0 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.h +++ b/third_party/WebKit/Source/core/layout/LayoutView.h
@@ -114,6 +114,9 @@ FrameView* frameView() const { return m_frameView; } + // |ancestor| can be nullptr, which will map the rect to the main frame's + // space, even if the main frame is remote (or has intermediate remote + // frames in the chain). bool mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, MapCoordinatesFlags,
diff --git a/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.cpp b/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.cpp index 00ac7f14..ed4ae6a 100644 --- a/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.cpp +++ b/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.cpp
@@ -38,8 +38,7 @@ namespace blink { -ApplicationCache::ApplicationCache(LocalFrame* frame) - : ContextLifecycleObserver(frame->document()) { +ApplicationCache::ApplicationCache(LocalFrame* frame) : DOMWindowClient(frame) { ApplicationCacheHost* cacheHost = applicationCacheHost(); if (cacheHost) cacheHost->setApplicationCache(this); @@ -47,12 +46,7 @@ DEFINE_TRACE(ApplicationCache) { EventTargetWithInlineData::trace(visitor); - ContextLifecycleObserver::trace(visitor); -} - -void ApplicationCache::contextDestroyed() { - if (ApplicationCacheHost* cacheHost = applicationCacheHost()) - cacheHost->setApplicationCache(0); + DOMWindowClient::trace(visitor); } ApplicationCacheHost* ApplicationCache::applicationCacheHost() const { @@ -98,9 +92,7 @@ } ExecutionContext* ApplicationCache::getExecutionContext() const { - if (frame()) - return frame()->document(); - return 0; + return frame() ? frame()->document() : nullptr; } const AtomicString& ApplicationCache::toEventType(
diff --git a/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.h b/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.h index 50cbcbc..b5f5d334 100644 --- a/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.h +++ b/third_party/WebKit/Source/core/loader/appcache/ApplicationCache.h
@@ -38,7 +38,7 @@ class LocalFrame; class ApplicationCache final : public EventTargetWithInlineData, - public ContextLifecycleObserver { + public DOMWindowClient { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(ApplicationCache); @@ -48,8 +48,6 @@ } ~ApplicationCache() override {} - void contextDestroyed() override; - unsigned short status() const; void update(ExceptionState&); void swapCache(ExceptionState&);
diff --git a/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp b/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp index b521bd9b6..ad39760 100644 --- a/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp +++ b/third_party/WebKit/Source/core/loader/appcache/ApplicationCacheHost.cpp
@@ -260,11 +260,12 @@ const String& errorURL, int errorStatus, const String& errorMessage) { - if (!m_domApplicationCache) + // Don't dispatch an event if the window is detached. + if (!m_domApplicationCache || !m_domApplicationCache->domWindow()) return; const AtomicString& eventType = ApplicationCache::toEventType(id); - if (eventType.isEmpty() || !m_domApplicationCache->getExecutionContext()) + if (eventType.isEmpty()) return; Event* event = nullptr; if (id == kProgressEvent) {
diff --git a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp index 7dfca3c..84060c8 100644 --- a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp +++ b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp
@@ -36,7 +36,7 @@ &FirstMeaningfulPaintDetector::networkStableTimerFired) {} Document* FirstMeaningfulPaintDetector::document() { - return m_paintTiming->host(); + return m_paintTiming->supplementable(); } // Computes "layout significance" (http://goo.gl/rytlPL) of a layout operation.
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp index 25ef6f72..7edb7876 100644 --- a/third_party/WebKit/Source/core/paint/PaintTiming.cpp +++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -123,12 +123,12 @@ m_fmpDetector(new FirstMeaningfulPaintDetector(this)) {} LocalFrame* PaintTiming::frame() const { - return host()->frame(); + return supplementable()->frame(); } void PaintTiming::notifyPaintTimingChanged() { - if (host()->loader()) - host()->loader()->didChangePerformanceTiming(); + if (supplementable()->loader()) + supplementable()->loader()->didChangePerformanceTiming(); } void PaintTiming::setFirstPaint(double stamp) {
diff --git a/third_party/WebKit/Source/core/timing/DOMWindowPerformance.cpp b/third_party/WebKit/Source/core/timing/DOMWindowPerformance.cpp index 180b484..997bbe3 100644 --- a/third_party/WebKit/Source/core/timing/DOMWindowPerformance.cpp +++ b/third_party/WebKit/Source/core/timing/DOMWindowPerformance.cpp
@@ -41,7 +41,7 @@ Performance* DOMWindowPerformance::performance() { if (!m_performance) - m_performance = Performance::create(host()->frame()); + m_performance = Performance::create(supplementable()->frame()); return m_performance.get(); }
diff --git a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp index 5d84c6a..57c952d 100644 --- a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp +++ b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
@@ -70,15 +70,15 @@ } // If detached from frame, do not allow sending a Beacon. - if (!host()->frame()) + if (!supplementable()->frame()) return false; return true; } int NavigatorBeacon::maxAllowance() const { - DCHECK(host()->frame()); - const Settings* settings = host()->frame()->settings(); + DCHECK(supplementable()->frame()); + const Settings* settings = supplementable()->frame()->settings(); if (settings) { int maxAllowed = settings->getMaxBeaconTransmission(); if (maxAllowed < m_transmittedBytes) @@ -118,7 +118,7 @@ bool allowed; if (data.isArrayBufferView()) { - allowed = PingLoader::sendBeacon(host()->frame(), allowance, url, + allowed = PingLoader::sendBeacon(supplementable()->frame(), allowance, url, data.getAsArrayBufferView(), bytes); } else if (data.isBlob()) { Blob* blob = data.getAsBlob(); @@ -134,17 +134,17 @@ return false; } } - allowed = - PingLoader::sendBeacon(host()->frame(), allowance, url, blob, bytes); + allowed = PingLoader::sendBeacon(supplementable()->frame(), allowance, url, + blob, bytes); } else if (data.isString()) { - allowed = PingLoader::sendBeacon(host()->frame(), allowance, url, + allowed = PingLoader::sendBeacon(supplementable()->frame(), allowance, url, data.getAsString(), bytes); } else if (data.isFormData()) { - allowed = PingLoader::sendBeacon(host()->frame(), allowance, url, + allowed = PingLoader::sendBeacon(supplementable()->frame(), allowance, url, data.getAsFormData(), bytes); } else { - allowed = PingLoader::sendBeacon(host()->frame(), allowance, url, String(), - bytes); + allowed = PingLoader::sendBeacon(supplementable()->frame(), allowance, url, + String(), bytes); } if (allowed) {
diff --git a/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp index 63d4a4a..3e4e7db 100644 --- a/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp +++ b/third_party/WebKit/Source/modules/csspaint/WindowPaintWorklet.cpp
@@ -34,8 +34,8 @@ } PaintWorklet* WindowPaintWorklet::paintWorklet() { - if (!m_paintWorklet && host()->frame()) - m_paintWorklet = PaintWorklet::create(host()->frame()); + if (!m_paintWorklet && supplementable()->frame()) + m_paintWorklet = PaintWorklet::create(supplementable()->frame()); return m_paintWorklet.get(); }
diff --git a/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp b/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp index 108b38a0..ff645af 100644 --- a/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp +++ b/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp
@@ -62,7 +62,7 @@ } String NavigatorDoNotTrack::doNotTrack() { - LocalFrame* frame = host()->frame(); + LocalFrame* frame = supplementable()->frame(); if (!frame || !frame->loader().client()) return String(); return frame->loader().client()->doNotTrackValue();
diff --git a/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp b/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp index 8be08ed..2cd4efe 100644 --- a/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp +++ b/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp
@@ -52,8 +52,8 @@ } Geolocation* NavigatorGeolocation::geolocation() { - if (!m_geolocation && host()->frame()) - m_geolocation = Geolocation::create(host()->frame()->document()); + if (!m_geolocation && supplementable()->frame()) + m_geolocation = Geolocation::create(supplementable()->frame()->document()); return m_geolocation; }
diff --git a/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.cpp b/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.cpp index 0e998ff3..06b5b60 100644 --- a/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.cpp +++ b/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.cpp
@@ -88,10 +88,10 @@ } InstalledAppController* NavigatorInstalledApp::controller() { - if (!host()->frame()) + if (!supplementable()->frame()) return nullptr; - return InstalledAppController::from(*host()->frame()); + return InstalledAppController::from(*supplementable()->frame()); } const char* NavigatorInstalledApp::supplementName() {
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp index 54ac3bdb..099ab4b 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
@@ -128,18 +128,13 @@ return false; } -NavigatorContentUtils* NavigatorContentUtils::from(LocalFrame& frame) { +NavigatorContentUtils* NavigatorContentUtils::from(Navigator& navigator) { return static_cast<NavigatorContentUtils*>( - Supplement<LocalFrame>::from(frame, supplementName())); + Supplement<Navigator>::from(navigator, supplementName())); } NavigatorContentUtils::~NavigatorContentUtils() {} -NavigatorContentUtils* NavigatorContentUtils::create( - NavigatorContentUtilsClient* client) { - return new NavigatorContentUtils(client); -} - void NavigatorContentUtils::registerProtocolHandler( Navigator& navigator, const String& scheme, @@ -164,9 +159,8 @@ ? UseCounter::RegisterProtocolHandlerSecureOrigin : UseCounter::RegisterProtocolHandlerInsecureOrigin); - NavigatorContentUtils::from(*navigator.frame()) - ->client() - ->registerProtocolHandler(scheme, document->completeURL(url), title); + NavigatorContentUtils::from(navigator)->client()->registerProtocolHandler( + scheme, document->completeURL(url), title); } static String customHandlersStateString( @@ -210,7 +204,7 @@ return declined; return customHandlersStateString( - NavigatorContentUtils::from(*navigator.frame()) + NavigatorContentUtils::from(navigator) ->client() ->isProtocolHandlerRegistered(scheme, document->completeURL(url))); } @@ -232,25 +226,24 @@ if (!verifyCustomHandlerScheme(scheme, exceptionState)) return; - NavigatorContentUtils::from(*navigator.frame()) - ->client() - ->unregisterProtocolHandler(scheme, document->completeURL(url)); + NavigatorContentUtils::from(navigator)->client()->unregisterProtocolHandler( + scheme, document->completeURL(url)); } DEFINE_TRACE(NavigatorContentUtils) { visitor->trace(m_client); - Supplement<LocalFrame>::trace(visitor); + Supplement<Navigator>::trace(visitor); } const char* NavigatorContentUtils::supplementName() { return "NavigatorContentUtils"; } -void provideNavigatorContentUtilsTo(LocalFrame& frame, - NavigatorContentUtilsClient* client) { - NavigatorContentUtils::provideTo(frame, - NavigatorContentUtils::supplementName(), - NavigatorContentUtils::create(client)); +void NavigatorContentUtils::provideTo(Navigator& navigator, + NavigatorContentUtilsClient* client) { + Supplement<Navigator>::provideTo( + navigator, NavigatorContentUtils::supplementName(), + new NavigatorContentUtils(navigator, client)); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h index 4ee3a80..5298a38 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h
@@ -27,7 +27,7 @@ #ifndef NavigatorContentUtils_h #define NavigatorContentUtils_h -#include "core/frame/LocalFrame.h" +#include "core/frame/Navigator.h" #include "modules/ModulesExport.h" #include "modules/navigatorcontentutils/NavigatorContentUtilsClient.h" #include "platform/Supplementable.h" @@ -37,18 +37,17 @@ namespace blink { class ExceptionState; -class LocalFrame; class Navigator; class MODULES_EXPORT NavigatorContentUtils final : public GarbageCollectedFinalized<NavigatorContentUtils>, - public Supplement<LocalFrame> { + public Supplement<Navigator> { USING_GARBAGE_COLLECTED_MIXIN(NavigatorContentUtils); public: virtual ~NavigatorContentUtils(); - static NavigatorContentUtils* from(LocalFrame&); + static NavigatorContentUtils* from(Navigator&); static const char* supplementName(); static void registerProtocolHandler(Navigator&, @@ -65,7 +64,7 @@ const String& url, ExceptionState&); - static NavigatorContentUtils* create(NavigatorContentUtilsClient*); + static void provideTo(Navigator&, NavigatorContentUtilsClient*); DECLARE_VIRTUAL_TRACE(); @@ -74,8 +73,9 @@ } private: - explicit NavigatorContentUtils(NavigatorContentUtilsClient* client) - : m_client(client) {} + NavigatorContentUtils(Navigator& navigator, + NavigatorContentUtilsClient* client) + : Supplement<Navigator>(navigator), m_client(client) {} NavigatorContentUtilsClient* client() { return m_client.get(); }
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h index e8cb4e0..afb8e11d 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h
@@ -34,8 +34,6 @@ namespace blink { -class LocalFrame; - class NavigatorContentUtilsClient : public GarbageCollectedFinalized<NavigatorContentUtilsClient> { public: @@ -57,10 +55,6 @@ DEFINE_INLINE_VIRTUAL_TRACE() {} }; -MODULES_EXPORT void provideNavigatorContentUtilsTo( - LocalFrame&, - NavigatorContentUtilsClient*); - } // namespace blink #endif // NavigatorContentUtilsClient_h
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp b/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp index 08a79d0..147e713 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp
@@ -5,6 +5,7 @@ #include "InternalsNavigatorContentUtils.h" #include "core/dom/Document.h" +#include "core/frame/LocalDOMWindow.h" #include "core/testing/Internals.h" #include "modules/navigatorcontentutils/NavigatorContentUtils.h" #include "modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h" @@ -16,7 +17,7 @@ Document* document) { ASSERT(document && document->page()); NavigatorContentUtils* navigatorContentUtils = - NavigatorContentUtils::from(*document->frame()); + NavigatorContentUtils::from(*document->domWindow()->navigator()); navigatorContentUtils->setClientForTest( NavigatorContentUtilsClientMock::create()); }
diff --git a/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp b/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp index 2394a3b..190f62b 100644 --- a/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp +++ b/third_party/WebKit/Source/modules/storage/DOMWindowStorage.cpp
@@ -56,10 +56,10 @@ Storage* DOMWindowStorage::sessionStorage( ExceptionState& exceptionState) const { - if (!host()->frame()) + if (!supplementable()->frame()) return nullptr; - Document* document = host()->frame()->document(); + Document* document = supplementable()->frame()->document(); DCHECK(document); String accessDeniedMessage = "Access is denied for this document."; if (!document->getSecurityOrigin()->canAccessLocalStorage()) { @@ -99,10 +99,10 @@ } Storage* DOMWindowStorage::localStorage(ExceptionState& exceptionState) const { - if (!host()->frame()) + if (!supplementable()->frame()) return nullptr; - Document* document = host()->frame()->document(); + Document* document = supplementable()->frame()->document(); DCHECK(document); String accessDeniedMessage = "Access is denied for this document."; if (!document->getSecurityOrigin()->canAccessLocalStorage()) {
diff --git a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp index 2841674..c29f840 100644 --- a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp +++ b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
@@ -71,7 +71,7 @@ } VRController* NavigatorVR::controller() { - if (!host()->frame()) + if (!supplementable()->frame()) return 0; if (!m_controller) { @@ -82,7 +82,8 @@ } Document* NavigatorVR::document() { - return host()->frame() ? host()->frame()->document() : nullptr; + return supplementable()->frame() ? supplementable()->frame()->document() + : nullptr; } DEFINE_TRACE(NavigatorVR) { @@ -104,17 +105,17 @@ } void NavigatorVR::enqueueVREvent(VRDisplayEvent* event) { - if (host()->frame()) { - host()->frame()->domWindow()->enqueueWindowEvent(event); + if (supplementable()->frame()) { + supplementable()->frame()->domWindow()->enqueueWindowEvent(event); } } void NavigatorVR::dispatchVRGestureEvent(VRDisplayEvent* event) { - if (!(host()->frame())) + if (!(supplementable()->frame())) return; UserGestureIndicator gestureIndicator( DocumentUserGestureToken::create(document())); - LocalDOMWindow* window = host()->frame()->domWindow(); + LocalDOMWindow* window = supplementable()->frame()->domWindow(); DCHECK(window); event->setTarget(window); window->dispatchEvent(event);
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 4098586..b567a242 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1863,8 +1863,7 @@ "//cc/blink", "//device/base/synchronization", "//mojo/common:test_common_custom_types_blink", - "//mojo/edk/embedder:headers", - "//mojo/edk/test:test_support", + "//mojo/edk/system", "//mojo/public/cpp/bindings/tests:for_blink_tests", "//skia", "//testing/gmock",
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index 35fd6e6..c509438 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -285,3 +285,4 @@ BackgroundVideoTrackOptimization status=stable PerformancePaintTiming status=test HideNonceContentAttribute status=experimental +UnclosedFormControlIsInvalid status=experimental
diff --git a/third_party/WebKit/Source/platform/Supplementable.h b/third_party/WebKit/Source/platform/Supplementable.h index 6ec435c8..ad7fd69 100644 --- a/third_party/WebKit/Source/platform/Supplementable.h +++ b/third_party/WebKit/Source/platform/Supplementable.h
@@ -99,31 +99,33 @@ // All Supplement objects should be instantiated with m_host. Supplement() {} - explicit Supplement(T& host) : m_host(&host) {} + explicit Supplement(T& supplementable) : m_supplementable(&supplementable) {} // Supplementable and its supplements live and die together. - // Thus host() should never return null (if the default constructor + // Thus supplementable() should never return null (if the default constructor // is completely removed). - T* host() const { return m_host; } + T* supplementable() const { return m_supplementable; } - static void provideTo(Supplementable<T>& host, + static void provideTo(Supplementable<T>& supplementable, const char* key, Supplement<T>* supplement) { - host.provideSupplement(key, supplement); + supplementable.provideSupplement(key, supplement); } - static Supplement<T>* from(Supplementable<T>& host, const char* key) { - return host.requireSupplement(key); + static Supplement<T>* from(Supplementable<T>& supplementable, + const char* key) { + return supplementable.requireSupplement(key); } - static Supplement<T>* from(Supplementable<T>* host, const char* key) { - return host ? host->requireSupplement(key) : 0; + static Supplement<T>* from(Supplementable<T>* supplementable, + const char* key) { + return supplementable ? supplementable->requireSupplement(key) : 0; } - DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_host); } + DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(m_supplementable); } private: - Member<T> m_host; + Member<T> m_supplementable; }; // Supplementable<T> inherits from GarbageCollectedMixin virtually
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.cpp b/third_party/WebKit/Source/platform/heap/HeapCompact.cpp index b31a31b..591caef56 100644 --- a/third_party/WebKit/Source/platform/heap/HeapCompact.cpp +++ b/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
@@ -253,7 +253,6 @@ HeapCompact::HeapCompact() : m_doCompact(false), m_gcCountSinceLastCompaction(0), - m_threadCount(0), m_freeListSize(0), m_compactableArenas(0u), m_freedPages(0), @@ -346,7 +345,6 @@ m_doCompact = true; m_freedPages = 0; m_freedSize = 0; - m_threadCount = state->heap().threads().size(); m_fixups.reset(); m_gcCountSinceLastCompaction = 0; s_forceCompactionGC = false; @@ -418,7 +416,6 @@ if (!m_doCompact) return; - MutexLocker locker(m_mutex); if (!m_startCompactionTimeMS) m_startCompactionTimeMS = WTF::currentTimeMS(); } @@ -427,48 +424,32 @@ if (!m_doCompact) return; - MutexLocker locker(m_mutex); - // Final one clears out. - if (!--m_threadCount) { #if DEBUG_HEAP_COMPACTION - if (m_fixups) - m_fixups->dumpDebugStats(); + if (m_fixups) + m_fixups->dumpDebugStats(); #endif - m_fixups.reset(); - m_doCompact = false; + m_fixups.reset(); + m_doCompact = false; - double timeForHeapCompaction = - WTF::currentTimeMS() - m_startCompactionTimeMS; - DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForHeapCompactionHistogram, - ("BlinkGC.TimeForHeapCompaction", 1, 10 * 1000, 50)); - timeForHeapCompactionHistogram.count(timeForHeapCompaction); - m_startCompactionTimeMS = 0; + double timeForHeapCompaction = WTF::currentTimeMS() - m_startCompactionTimeMS; + DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForHeapCompactionHistogram, + ("BlinkGC.TimeForHeapCompaction", 1, 10 * 1000, 50)); + timeForHeapCompactionHistogram.count(timeForHeapCompaction); + m_startCompactionTimeMS = 0; - DEFINE_STATIC_LOCAL( - CustomCountHistogram, objectSizeFreedByHeapCompaction, - ("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50)); - objectSizeFreedByHeapCompaction.count(m_freedSize / 1024); + DEFINE_STATIC_LOCAL( + CustomCountHistogram, objectSizeFreedByHeapCompaction, + ("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50)); + objectSizeFreedByHeapCompaction.count(m_freedSize / 1024); #if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME - LOG_HEAP_COMPACTION_INTERNAL( - "Compaction stats: time=%gms, pages freed=%zu, size=%zu\n", - timeForHeapCompaction, m_freedPages, m_freedSize); + LOG_HEAP_COMPACTION_INTERNAL( + "Compaction stats: time=%gms, pages freed=%zu, size=%zu\n", + timeForHeapCompaction, m_freedPages, m_freedSize); #else - LOG_HEAP_COMPACTION("Compaction stats: freed pages=%zu size=%zu\n", - m_freedPages, m_freedSize); + LOG_HEAP_COMPACTION("Compaction stats: freed pages=%zu size=%zu\n", + m_freedPages, m_freedSize); #endif - - // Compaction has been completed by all participating threads, unblock - // them all. - m_finished.broadcast(); - } else { - // Letting a thread return here and let it exit its safe point opens up - // the possibility of it accessing heaps of other threads that are - // still being compacted. It is not in a valid state until objects have - // all been moved together, hence all GC-participating threads must - // complete compaction together. Grab the condition variable and wait. - m_finished.wait(m_mutex); - } } void HeapCompact::addCompactingPage(BasePage* page) {
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.h b/third_party/WebKit/Source/platform/heap/HeapCompact.h index e7e13334..5c8e1a88 100644 --- a/third_party/WebKit/Source/platform/heap/HeapCompact.h +++ b/third_party/WebKit/Source/platform/heap/HeapCompact.h
@@ -139,18 +139,6 @@ bool m_doCompact; size_t m_gcCountSinceLastCompaction; - // Lock protecting finishedThreadCompaction() signalling. - Mutex m_mutex; - - // All threads performing a GC must synchronize on completion - // of all heap compactions. Not doing so risks one thread resuming - // the mutator, which could perform cross-thread access to a heap - // that's still in the process of being compacted. - ThreadCondition m_finished; - - // Number of heap threads participating in the compaction. - int m_threadCount; - // Last reported freelist size, across all compactable arenas. size_t m_freeListSize;
diff --git a/third_party/WebKit/Source/platform/testing/DEPS b/third_party/WebKit/Source/platform/testing/DEPS index c5e2cc8..81f18ea 100644 --- a/third_party/WebKit/Source/platform/testing/DEPS +++ b/third_party/WebKit/Source/platform/testing/DEPS
@@ -11,5 +11,4 @@ "+base/test/test_io_thread.h", "+cc", "+mojo/edk/embedder", - "+mojo/edk/test", ]
diff --git a/third_party/WebKit/Source/platform/testing/RunAllTests.cpp b/third_party/WebKit/Source/platform/testing/RunAllTests.cpp index 837dd9f..67bd9c9 100644 --- a/third_party/WebKit/Source/platform/testing/RunAllTests.cpp +++ b/third_party/WebKit/Source/platform/testing/RunAllTests.cpp
@@ -33,7 +33,7 @@ #include "base/test/test_io_thread.h" #include "base/test/test_suite.h" #include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/embedder/scoped_ipc_support.h" #include "platform/heap/Heap.h" #include "platform/testing/TestingPlatformSupport.h" #include <memory> @@ -56,9 +56,9 @@ mojo::edk::Init(); base::TestIOThread testIoThread(base::TestIOThread::kAutoStart); - std::unique_ptr<mojo::edk::test::ScopedIPCSupport> ipcSupport( - WTF::wrapUnique( - new mojo::edk::test::ScopedIPCSupport(testIoThread.task_runner()))); + mojo::edk::ScopedIPCSupport ipcSupport( + testIoThread.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); result = base::LaunchUnitTests( argc, argv, base::Bind(runTestSuite, base::Unretained(&testSuite))); }
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp index e5712bb..3fa95b1 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -57,6 +57,7 @@ #include "modules/audio_output_devices/AudioOutputDeviceClient.h" #include "modules/installedapp/InstalledAppController.h" #include "modules/mediastream/UserMediaController.h" +#include "modules/navigatorcontentutils/NavigatorContentUtils.h" #include "modules/presentation/PresentationController.h" #include "modules/push_messaging/PushController.h" #include "modules/screen_orientation/ScreenOrientationControllerImpl.h" @@ -1155,8 +1156,9 @@ UserMediaClientImpl::create(client->userMediaClient())); provideIndexedDBClientTo(frame, IndexedDBClientImpl::create(frame)); provideLocalFileSystemTo(frame, LocalFileSystemClient::create()); - provideNavigatorContentUtilsTo( - frame, NavigatorContentUtilsClientImpl::create(webFrame)); + NavigatorContentUtils::provideTo( + *frame.domWindow()->navigator(), + NavigatorContentUtilsClientImpl::create(webFrame)); ScreenOrientationControllerImpl::provideTo( frame, client->webScreenOrientationClient());
diff --git a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp index 93a4c708..c4a072a 100644 --- a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp +++ b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp
@@ -12,6 +12,7 @@ #include "core/layout/api/LayoutItem.h" #include "core/layout/api/LayoutPartItem.h" #include "platform/exported/WrappedResourceRequest.h" +#include "platform/geometry/IntRect.h" #include "platform/weborigin/SecurityOrigin.h" #include "platform/weborigin/SecurityPolicy.h" #include "public/web/WebRemoteFrameClient.h" @@ -174,6 +175,11 @@ m_webFrame->client()->frameRectsChanged(frameRect); } +void RemoteFrameClientImpl::updateRemoteViewportIntersection( + const IntRect& viewportIntersection) { + m_webFrame->client()->updateRemoteViewportIntersection(viewportIntersection); +} + void RemoteFrameClientImpl::advanceFocus(WebFocusType type, LocalFrame* source) { m_webFrame->client()->advanceFocus(type,
diff --git a/third_party/WebKit/Source/web/RemoteFrameClientImpl.h b/third_party/WebKit/Source/web/RemoteFrameClientImpl.h index 85c5782..8fb019a6 100644 --- a/third_party/WebKit/Source/web/RemoteFrameClientImpl.h +++ b/third_party/WebKit/Source/web/RemoteFrameClientImpl.h
@@ -38,6 +38,7 @@ LocalFrame* source) const override; void forwardInputEvent(Event*) override; void frameRectsChanged(const IntRect& frameRect) override; + void updateRemoteViewportIntersection(const IntRect&) override; void advanceFocus(WebFocusType, LocalFrame*) override; void visibilityChanged(bool visible) override; void setHasReceivedUserGesture() override;
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index b8812f5..4f686427 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -712,6 +712,17 @@ } } +void WebFrameWidgetImpl::setRemoteViewportIntersection( + const WebRect& viewportIntersection) { + // Remote viewports are only applicable to local frames with remote ancestors. + DCHECK(m_localRoot->parent() && m_localRoot->parent()->isWebRemoteFrame()); + + if (m_localRoot->frameView()) { + m_localRoot->frameView()->setViewportIntersectionFromParent( + viewportIntersection); + } +} + void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseEvent& event) { // FIXME: WebWidget doesn't have the method below.
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h index c99f3a6..6376a986 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -113,6 +113,7 @@ void didLosePointerLock() override; bool getCompositionCharacterBounds(WebVector<WebRect>& bounds) override; void applyReplacementRange(const WebRange&) override; + void setRemoteViewportIntersection(const WebRect&) override; // WebFrameWidget implementation. WebLocalFrameImpl* localRoot() const override { return m_localRoot; }
diff --git a/third_party/WebKit/public/web/WebFrameWidget.h b/third_party/WebKit/public/web/WebFrameWidget.h index 1ff35be..5178df6 100644 --- a/third_party/WebKit/public/web/WebFrameWidget.h +++ b/third_party/WebKit/public/web/WebFrameWidget.h
@@ -112,9 +112,14 @@ const WebPoint& screenPoint, WebDragOperation) = 0; - // Notfies the WebFrameWidget that the system drag and drop operation has + // Notifies the WebFrameWidget that the system drag and drop operation has // ended. virtual void dragSourceSystemDragEnded() = 0; + + // Constrains the viewport intersection for use by IntersectionObserver. + // This is needed for out-of-process iframes to know if they are clipped + // by ancestor frames in another process. + virtual void setRemoteViewportIntersection(const WebRect&) {} }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebRemoteFrameClient.h b/third_party/WebKit/public/web/WebRemoteFrameClient.h index d559413..dc0394e5 100644 --- a/third_party/WebKit/public/web/WebRemoteFrameClient.h +++ b/third_party/WebKit/public/web/WebRemoteFrameClient.h
@@ -42,6 +42,9 @@ virtual void frameRectsChanged(const WebRect&) {} + virtual void updateRemoteViewportIntersection( + const WebRect& viewportIntersection) {} + virtual void visibilityChanged(bool visible) {} virtual void setHasReceivedUserGesture() {}
diff --git a/tools/ipc_fuzzer/message_replay/replay_process.cc b/tools/ipc_fuzzer/message_replay/replay_process.cc index c14d7d8..d69f9c1 100644 --- a/tools/ipc_fuzzer/message_replay/replay_process.cc +++ b/tools/ipc_fuzzer/message_replay/replay_process.cc
@@ -92,8 +92,9 @@ kMojoIPCChannel + base::GlobalDescriptors::kBaseDescriptor); #endif - mojo_ipc_support_.reset( - new mojo::edk::ScopedIPCSupport(io_thread_.task_runner())); + mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport( + io_thread_.task_runner(), + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); InitializeMojoIPCChannel(); return true;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 63921188..7b3ec48d 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -19833,8 +19833,21 @@ </summary> </histogram> +<histogram name="GeolocationDisclosure.PostDisclosureContentSetting" + enum="ContentSetting"> + <owner>benwells@chromium.org</owner> + <summary> + Records the geolocation content setting for the default search engine's + origin after the search geolocation disclosure has been shown and won't be + shown again. This metric is only recorded once per client. + </summary> +</histogram> + <histogram name="GeolocationDisclosure.PostDisclosurePermission" enum="PermissionStatus"> + <obsolete> + Deprecated 2017/01. Replaced by PostDisclosureContentSetting. + </obsolete> <owner>benwells@chromium.org</owner> <summary> Records the geolocation permission for the default search engine's origin @@ -19843,8 +19856,21 @@ </summary> </histogram> +<histogram name="GeolocationDisclosure.PreDisclosureContentSetting" + enum="ContentSetting"> + <owner>benwells@chromium.org</owner> + <summary> + Records the geolocation content setting for the default search engine's + origin immediately before the search geolocation disclosure has been shown. + This metric is only recorded once per client. + </summary> +</histogram> + <histogram name="GeolocationDisclosure.PreDisclosurePermission" enum="PermissionStatus"> + <obsolete> + Deprecated 2017/01. Replaced by PreDisclosureContentSetting. + </obsolete> <owner>benwells@chromium.org</owner> <summary> Records the geolocation permission for the default search engine's origin @@ -38901,6 +38927,36 @@ </summary> </histogram> +<histogram name="NewTabPage.ContentSuggestions.Notifications.Actions" + enum="ContentSuggestionsNotificationsAction"> + <owner>sfiera@chromium.org</owner> + <summary> + Android: The number of actions taken on displayed notifications, either + user-initiated (tapping to open or swiping to dismiss), or automatic (hiding + due to a change in circumstances). + </summary> +</histogram> + +<histogram name="NewTabPage.ContentSuggestions.Notifications.Impressions" + enum="ContentSuggestionsNotificationsImpression"> + <owner>sfiera@chromium.org</owner> + <summary> + Android: The number of notifications that were shown, keyed by category. One + bucket counts the server-provided ARTICLES category; the other counts + everything else. + </summary> +</histogram> + +<histogram name="NewTabPage.ContentSuggestions.Notifications.OptOuts" + enum="ContentSuggestionsNotificationsOptOut"> + <owner>sfiera@chromium.org</owner> + <summary> + Android: The number of times a user opted out, keyed by method: IMPLICIT + (user ignored enough notifications consecutively that we think they're not + interested), or EXPLICIT (via explicit setting). + </summary> +</histogram> + <histogram name="NewTabPage.ContentSuggestions.OpenDisposition" enum="WindowOpenDisposition"> <owner>treib@chromium.org</owner> @@ -44544,6 +44600,22 @@ </summary> </histogram> +<histogram + name="PasswordManager.ShouldBlockPasswordForSameOriginButDifferentScheme" + enum="BooleanBlocked"> + <owner>jdoerrie@chromium.org</owner> + <summary> + This metric is recorded every time Chrome detects a password form + submission. The credential might be proposed to be saved, or it might be + blocked. It is blocked if the previously detected password form submission + was successful, and the current submission is from a URL with the same + origin, but a different and insecure scheme. That is, if the previously + provisionally saved credential is for https://example.com, a new credential + for http://example.com would be blocked. More details can be found in the + doc associated with http://crbug.com/571580. + </summary> +</histogram> + <histogram name="PasswordManager.ShouldShowAutoSignInFirstRunExperience" enum="BooleanPending"> <owner>vasilii@chromium.org</owner> @@ -49824,16 +49896,6 @@ </summary> </histogram> -<histogram name="Prerender.NoStatePrefetchTTFCP" units="ms"> - <obsolete> - Deprecated December 28, 2016, use Prerender.PrefetchTTFCP instead. - </obsolete> - <owner>droger@chromium.org</owner> - <owner>mattcary@chromium.org</owner> - <owner>pasko@chromium.org</owner> - <summary>Time to first contentful paint.</summary> -</histogram> - <histogram name="Prerender.OmniboxNavigationsCouldPrerender"> <owner>pasko@chromium.org</owner> <summary> @@ -80923,6 +80985,26 @@ <int value="6" label="Articles"/> </enum> +<enum name="ContentSuggestionsNotificationsAction" type="int"> + <int value="0" label="Tap"/> + <int value="1" label="Dismissal"/> + <int value="2" label="Hidden (Notification deadline passed)"/> + <int value="3" label="Hidden (Suggestion expired)"/> + <int value="4" label="Hidden (Chrome became frontmost)"/> + <int value="5" label="Hidden (Category disabled)"/> + <int value="6" label="Hidden (Content Suggestion Service shut down)"/> +</enum> + +<enum name="ContentSuggestionsNotificationsImpression" type="int"> + <int value="0" label="Article"/> + <int value="1" label="Non-Article"/> +</enum> + +<enum name="ContentSuggestionsNotificationsOptOut" type="int"> + <int value="0" label="Implicit"/> + <int value="1" label="Explicit"/> +</enum> + <enum name="ContentType" type="int"> <int value="-1" label="Invalid setting"/> <int value="0" label="Cookies setting"/> @@ -88888,6 +88970,10 @@ <int value="1761" label="BaseWithNewlinesInTarget"/> <int value="1762" label="BaseWithOpenBracketInTarget"/> <int value="1763" label="BaseWouldBeBlockedByDefaultSrc"/> + <int value="1764" label="V8AssigmentExpressionLHSIsCallInSloppy"/> + <int value="1765" label="V8AssigmentExpressionLHSIsCallInStrict"/> + <int value="1766" label="V8PromiseConstructorReturnedUndefined"/> + <int value="1767" label="FormSubmittedWithUnclosedFormControl"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -114979,16 +115065,12 @@ label="No prefetch. Warning: do not compare with the load times of prefetched pages (bias)."/> <suffix name="Warm" label="Prefetch skips revalidation."/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP"/> <affected-histogram name="Prerender.PrefetchTTFCP"/> </histogram_suffixes> <histogram_suffixes name="PrerenderPrefetchMainResourceType" separator="."> <suffix name="Cacheable" label="Main resource cacheable."/> <suffix name="NoStore" label="Main resource no-store."/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Cold"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Reference"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Warm"/> <affected-histogram name="Prerender.PrefetchTTFCP.Cold"/> <affected-histogram name="Prerender.PrefetchTTFCP.Reference"/> <affected-histogram name="Prerender.PrefetchTTFCP.Warm"/> @@ -115037,13 +115119,6 @@ <affected-histogram name="Prerender.NoStatePrefetchMainResourceRedirects"/> <affected-histogram name="Prerender.NoStatePrefetchResponseTypes"/> <affected-histogram name="Prerender.NoStatePrefetchSubResourceRedirects"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Cold.Cacheable"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Cold.NoStore"/> - <affected-histogram - name="Prerender.NoStatePrefetchTTFCP.Reference.Cacheable"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Reference.NoStore"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Warm.Cacheable"/> - <affected-histogram name="Prerender.NoStatePrefetchTTFCP.Warm.NoStore"/> <affected-histogram name="Prerender.PageVisitedStatus"/> <affected-histogram name="Prerender.PerceivedPLT"/> <affected-histogram name="Prerender.PerceivedPLTFirstAfterMiss"/>
diff --git a/ui/events/event.cc b/ui/events/event.cc index dc212a5f..f17899623 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -44,39 +44,6 @@ #include "ui/events/keycodes/platform_key_map_win.h" #endif -// Support a collection of histograms, perhaps one for each entry in an -// enumeration. This macro manages a block of pointers, adding to a specific -// one by its index. -// -// A typical instantiation looks something like this: -// STATIC_HISTOGRAM_POINTER_GROUP( -// GetHistogramNameForIndex(histogram_index), -// histogram_index, MAXIMUM_HISTOGRAM_INDEX, Add(some_delta), -// base::Histogram::FactoryGet( -// GetHistogramNameForType(histogram_index), -// MINIMUM_SAMPLE, MAXIMUM_SAMPLE, BUCKET_COUNT, -// base::HistogramBase::kUmaTargetedHistogramFlag)); -// -// Though it seems inefficient to generate the name twice, the first -// instance will be used only for DCHECK builds and the second will -// execute only during the first access to the given index, after which -// the pointer is cached and the name never needed again. -// -// This is defined in this way so that it can be moved unchanged into -// base/metrics/histogram_macros.h if it is useful in other files. -#define STATIC_HISTOGRAM_POINTER_GROUP(constant_histogram_name, index, \ - constant_maximum, \ - histogram_add_method_invocation, \ - histogram_factory_get_invocation) \ - do { \ - static base::subtle::AtomicWord atomic_histograms[constant_maximum]; \ - DCHECK_LE(0, index); \ - DCHECK_LT(index, constant_maximum); \ - HISTOGRAM_POINTER_USE(&atomic_histograms[index], constant_histogram_name, \ - histogram_add_method_invocation, \ - histogram_factory_get_invocation); \ - } while (0) - namespace { std::string EventTypeName(ui::EventType type) {
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index 638bd29f..674685b 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -283,7 +283,14 @@ if (keyboard_mode_ == FLOATING) { NotifyKeyboardBoundsChanging(gfx::Rect()); } else if (keyboard_mode_ == FULL_WIDTH) { - AdjustKeyboardBounds(); + // TODO(bshe): revisit this logic after we decide to support resize virtual + // keyboard. + int keyboard_height = GetContainerWindow()->bounds().height(); + const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds(); + gfx::Rect new_bounds = root_bounds; + new_bounds.set_y(root_bounds.height() - keyboard_height); + new_bounds.set_height(keyboard_height); + GetContainerWindow()->SetBounds(new_bounds); // No animation added, so call ShowAnimationFinished immediately. ShowAnimationFinished(); } @@ -312,7 +319,6 @@ void KeyboardController::OnWindowAddedToRootWindow(aura::Window* window) { if (!window->GetRootWindow()->HasObserver(this)) window->GetRootWindow()->AddObserver(this); - AdjustKeyboardBounds(); } void KeyboardController::OnWindowRemovingFromRootWindow(aura::Window* window, @@ -505,21 +511,4 @@ observer.OnKeyboardHidden(); } -void KeyboardController::AdjustKeyboardBounds() { - // When keyboard is floating, no resize is necessary. - if (keyboard_mode_ == FLOATING) - return; - - if (keyboard_mode_ == FULL_WIDTH) { - // TODO(bshe): revisit this logic after we decide to support resize virtual - // keyboard. - int keyboard_height = GetContainerWindow()->bounds().height(); - const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds(); - gfx::Rect new_bounds = root_bounds; - new_bounds.set_y(root_bounds.height() - keyboard_height); - new_bounds.set_height(keyboard_height); - GetContainerWindow()->SetBounds(new_bounds); - } -} - } // namespace keyboard
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h index 2bfe473f..817fa0d 100644 --- a/ui/keyboard/keyboard_controller.h +++ b/ui/keyboard/keyboard_controller.h
@@ -159,10 +159,6 @@ void ShowAnimationFinished(); void HideAnimationFinished(); - // Called when the keyboard mode is set or the keyboard is moved to another - // display. - void AdjustKeyboardBounds(); - std::unique_ptr<KeyboardUI> ui_; KeyboardLayoutDelegate* layout_delegate_; std::unique_ptr<aura::Window> container_;
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc index 6357440a..c2b47f3c 100644 --- a/ui/keyboard/keyboard_controller_unittest.cc +++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -299,8 +299,7 @@ const gfx::Rect& initial_bounds = container->bounds(); // The container should be positioned at the bottom of screen and has 0 // height. - ASSERT_EQ(0, initial_bounds.height()); - ASSERT_EQ(screen_bounds.height(), initial_bounds.y()); + ASSERT_EQ(gfx::Rect(), initial_bounds); VerifyKeyboardWindowSize(container, keyboard); // In FULL_WIDTH mode, attempt to change window width or move window up from @@ -341,38 +340,6 @@ VerifyKeyboardWindowSize(container, keyboard); } -TEST_F(KeyboardControllerTest, KeyboardSizeMultiRootWindow) { - aura::Window* container(controller()->GetContainerWindow()); - aura::Window* keyboard(ui()->GetKeyboardWindow()); - gfx::Rect screen_bounds = root_window()->bounds(); - root_window()->AddChild(container); - container->AddChild(keyboard); - const gfx::Rect& initial_bounds = container->bounds(); - // The container should be positioned at the bottom of screen and has 0 - // height. - ASSERT_EQ(0, initial_bounds.height()); - ASSERT_EQ(screen_bounds.height(), initial_bounds.y()); - VerifyKeyboardWindowSize(container, keyboard); - - // Adding new root window. - std::unique_ptr<aura::WindowTreeHost> secondary_tree_host = - base::WrapUnique<aura::WindowTreeHost>( - aura::WindowTreeHost::Create(gfx::Rect(0, 0, 1000, 500))); - secondary_tree_host->InitHost(); - EXPECT_EQ(1000, secondary_tree_host->window()->bounds().width()); - EXPECT_EQ(500, secondary_tree_host->window()->bounds().height()); - - // Move the keyboard into the secondary root window. - controller()->HideKeyboard( - KeyboardController::HideReason::HIDE_REASON_AUTOMATIC); - root_window()->RemoveChild(container); - secondary_tree_host->window()->AddChild(container); - - const gfx::Rect& new_bounds = container->bounds(); - EXPECT_EQ(500, new_bounds.y()); - VerifyKeyboardWindowSize(container, keyboard); -} - // Tests that tapping/clicking inside the keyboard does not give it focus. TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) { keyboard::SetAccessibilityKeyboardEnabled(true);
diff --git a/url/DEPS b/url/DEPS index c89ac32..946d75f 100644 --- a/url/DEPS +++ b/url/DEPS
@@ -11,7 +11,6 @@ "+third_party/icu", ], "run_all_unittests\.cc": [ - "+mojo/edk/embedder/embedder.h", - "+mojo/edk/test/scoped_ipc_support.h", + "+mojo/edk/embedder", ], }
diff --git a/url/run_all_unittests.cc b/url/run_all_unittests.cc index c0b306a2..fcafd03 100644 --- a/url/run_all_unittests.cc +++ b/url/run_all_unittests.cc
@@ -13,7 +13,6 @@ #if !defined(OS_IOS) #include "mojo/edk/embedder/embedder.h" // nogncheck -#include "mojo/edk/test/scoped_ipc_support.h" // nogncheck #endif int main(int argc, char** argv) { @@ -21,10 +20,6 @@ #if !defined(OS_IOS) mojo::edk::Init(); - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - std::unique_ptr<mojo::edk::test::ScopedIPCSupport> ipc_support; - ipc_support.reset( - new mojo::edk::test::ScopedIPCSupport(test_io_thread.task_runner())); #endif return base::LaunchUnitTests(