diff --git a/AUTHORS b/AUTHORS index 4449900a..383f4ce 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -607,6 +607,7 @@ Mohammed Wajahat Ali Siddiqui <wajahat.s@samsung.com> Mohan Reddy <mohan.reddy@samsung.com> Mohit Bhalla <bhallam@amazon.com> +Momoko Hattori <momohatt10@gmail.com> Mrunal Kapade <mrunal.kapade@intel.com> Myeongjin Cho <myeongjin.cho@navercorp.com> Myles C. Maxfield <mymax@amazon.com>
diff --git a/DEPS b/DEPS index bf8d6ab..a7760251 100644 --- a/DEPS +++ b/DEPS
@@ -117,7 +117,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': 'c4533eae082ffd41da27963932345ebf344a66e0', + 'angle_revision': '671809e62e807eb0f890a5d53eee1f8cb5fb825e', # 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. @@ -600,7 +600,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd23bbdb87b57cdb8183c38e2900abd5ccdc3ae37', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '03ec3c699be2279b5583c6d5e75d0933cd8baaf4', 'condition': 'checkout_linux', }, @@ -1106,7 +1106,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6d2f3f4cb8bac1f7c4a945c73d07a33df74f22f9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '1cd39fa9ea0c29acd67008919f5b524cf071a3ae', + Var('webrtc_git') + '/src.git' + '@' + '55d1af14751ad10e0cae741240f013ea67039f45', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1137,7 +1137,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@616feb1a7c2cf11f587543d415b7f18c9a8099f6', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2cecd6e79600cfc4fc51c6109f5c2000b0fd684a', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_contents_statics.cc b/android_webview/browser/aw_contents_statics.cc index 4061d7e..47952182 100644 --- a/android_webview/browser/aw_contents_statics.cc +++ b/android_webview/browser/aw_contents_statics.cc
@@ -10,6 +10,7 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/bind.h" #include "base/callback.h" #include "base/task/post_task.h" #include "components/google/core/common/google_util.h" @@ -52,6 +53,14 @@ Java_AwContentsStatics_safeBrowsingWhitelistAssigned(env, callback, success); } +void ProxyOverrideChanged(const JavaRef<jobject>& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (callback.is_null()) + return; + JNIEnv* env = AttachCurrentThread(); + Java_AwContentsStatics_proxyOverrideChanged(env, callback); +} + } // namespace // static @@ -138,23 +147,27 @@ const JavaParamRef<jclass>&, const base::android::JavaParamRef<jstring>& jhost, jint port, - const base::android::JavaParamRef<jobjectArray>& jexclusion_list) { + const base::android::JavaParamRef<jobjectArray>& jexclusion_list, + const JavaParamRef<jobject>& callback) { std::string host; base::android::ConvertJavaStringToUTF8(env, jhost, &host); std::vector<std::string> exclusion_list; base::android::AppendJavaStringArrayToStringVector(env, jexclusion_list, &exclusion_list); - AwBrowserContext::GetDefault()->GetAwURLRequestContext()->SetProxyOverride( - host, port, exclusion_list); + host, port, exclusion_list, + base::BindOnce(&ProxyOverrideChanged, + ScopedJavaGlobalRef<jobject>(env, callback))); } // static -void JNI_AwContentsStatics_ClearProxyOverride(JNIEnv* env, - const JavaParamRef<jclass>&) { - AwBrowserContext::GetDefault() - ->GetAwURLRequestContext() - ->ClearProxyOverride(); +void JNI_AwContentsStatics_ClearProxyOverride( + JNIEnv* env, + const JavaParamRef<jclass>&, + const JavaParamRef<jobject>& callback) { + AwBrowserContext::GetDefault()->GetAwURLRequestContext()->ClearProxyOverride( + base::BindOnce(&ProxyOverrideChanged, + ScopedJavaGlobalRef<jobject>(env, callback))); } } // namespace android_webview
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 34403eb..12b5ec0 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -415,15 +415,17 @@ void AwURLRequestContextGetter::SetProxyOverride( const std::string& host, int port, - const std::vector<std::string>& exclusion_list) { + const std::vector<std::string>& exclusion_list, + base::OnceClosure callback) { if (proxy_config_service_android_ != NULL) { - proxy_config_service_android_->SetProxyOverride(host, port, exclusion_list); + proxy_config_service_android_->SetProxyOverride(host, port, exclusion_list, + std::move(callback)); } } -void AwURLRequestContextGetter::ClearProxyOverride() { +void AwURLRequestContextGetter::ClearProxyOverride(base::OnceClosure callback) { if (proxy_config_service_android_ != NULL) { - proxy_config_service_android_->ClearProxyOverride(); + proxy_config_service_android_->ClearProxyOverride(std::move(callback)); } }
diff --git a/android_webview/browser/net/aw_url_request_context_getter.h b/android_webview/browser/net/aw_url_request_context_getter.h index d9ece21b..117bdba 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.h +++ b/android_webview/browser/net/aw_url_request_context_getter.h
@@ -54,8 +54,9 @@ // Methods to set and clear proxy override void SetProxyOverride(const std::string& host, int port, - const std::vector<std::string>& exclusion_list); - void ClearProxyOverride(); + const std::vector<std::string>& exclusion_list, + base::OnceClosure callback); + void ClearProxyOverride(base::OnceClosure callback); private: friend class AwBrowserContext;
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java index 7fe5fbb..8f0c2f2 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java
@@ -118,12 +118,12 @@ () -> AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl()); } - public void setProxyOverride(String host, int port, String[] exclusionList) { + public void setProxyOverride(String host, int port, String[] exclusionList, Runnable callback) { ThreadUtils.runOnUiThread( - () -> AwContentsStatics.setProxyOverride(host, port, exclusionList)); + () -> AwContentsStatics.setProxyOverride(host, port, exclusionList, callback)); } - public void clearProxyOverride() { - ThreadUtils.runOnUiThread(() -> AwContentsStatics.clearProxyOverride()); + public void clearProxyOverride(Runnable callback) { + ThreadUtils.runOnUiThread(() -> AwContentsStatics.clearProxyOverride(callback)); } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java index 6a12a9c..8237019 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
@@ -120,12 +120,19 @@ nativeSetCheckClearTextPermitted(permitted); } - public static void setProxyOverride(String host, int port, String[] exclusionList) { - nativeSetProxyOverride(host, port, exclusionList); + @CalledByNative + private static void proxyOverrideChanged(Runnable callback) { + if (callback == null) return; + callback.run(); } - public static void clearProxyOverride() { - nativeClearProxyOverride(); + public static void setProxyOverride( + String host, int port, String[] exclusionList, Runnable callback) { + nativeSetProxyOverride(host, port, exclusionList, callback); + } + + public static void clearProxyOverride(Runnable callback) { + nativeClearProxyOverride(callback); } /** @@ -155,6 +162,6 @@ String[] urls, Callback<Boolean> callback); private static native void nativeSetCheckClearTextPermitted(boolean permitted); private static native void nativeSetProxyOverride( - String host, int port, String[] exclusionList); - private static native void nativeClearProxyOverride(); + String host, int port, String[] exclusionList, Runnable callback); + private static native void nativeClearProxyOverride(Runnable callback); }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java index b3b5aac..5511b39 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java
@@ -17,6 +17,6 @@ void initSafeBrowsing(Context context, ValueCallback<Boolean> callback); void setSafeBrowsingWhitelist(List<String> hosts, ValueCallback<Boolean> callback); Uri getSafeBrowsingPrivacyPolicyUrl(); - void setProxyOverride(String host, int port, String[] exclusionList); - void clearProxyOverride(); + void setProxyOverride(String host, int port, String[] exclusionList, Runnable callback); + void clearProxyOverride(Runnable callback); }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java index 705e0685..59ce1df 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
@@ -127,7 +127,7 @@ // WebViewCompat.setProxyOverride // WebViewCompat.clearProxyOverride - public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE"; + public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE:2"; // WebViewCompat.getWebViewRenderer public static final String GET_WEB_VIEW_RENDERER = "GET_WEB_VIEW_RENDERER";
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java index aada5cd7..83793ffa 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -118,13 +118,14 @@ } @Override - public void setProxyOverride(String host, int port, String[] exclusionList) { - mSharedStatics.setProxyOverride(host, port, exclusionList); + public void setProxyOverride( + String host, int port, String[] exclusionList, Runnable callback) { + mSharedStatics.setProxyOverride(host, port, exclusionList, callback); } @Override - public void clearProxyOverride() { - mSharedStatics.clearProxyOverride(); + public void clearProxyOverride(Runnable callback) { + mSharedStatics.clearProxyOverride(callback); } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index d91626d..6adae32 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1190,6 +1190,8 @@ "wm/overview/window_selector_delegate.h", "wm/overview/window_selector_item.cc", "wm/overview/window_selector_item.h", + "wm/pip/pip_window_resizer.cc", + "wm/pip/pip_window_resizer.h", "wm/property_util.cc", "wm/property_util.h", "wm/resize_shadow.cc", @@ -1966,6 +1968,7 @@ "wm/overlay_layout_manager_unittest.cc", "wm/overview/cleanup_animation_observer_unittest.cc", "wm/overview/window_selector_unittest.cc", + "wm/pip/pip_window_resizer_unittest.cc", "wm/resize_shadow_and_cursor_unittest.cc", "wm/root_window_layout_manager_unittest.cc", "wm/screen_dimmer_unittest.cc",
diff --git a/ash/wm/client_controlled_state.cc b/ash/wm/client_controlled_state.cc index 8bfc26c..725b97d 100644 --- a/ash/wm/client_controlled_state.cc +++ b/ash/wm/client_controlled_state.cc
@@ -68,7 +68,8 @@ bool was_pinned = window_state->IsPinned(); bool was_trusted_pinned = window_state->IsTrustedPinned(); - EnterNextState(window_state, next_state_type, kAnimationCrossFade); + set_next_bounds_change_animation_type(kAnimationCrossFade); + EnterNextState(window_state, next_state_type); VLOG(1) << "Processing Pinned Transtion: event=" << event->type() << ", state=" << old_state_type << "=>" << next_state_type @@ -193,20 +194,25 @@ return; switch (event->type()) { case WM_EVENT_SET_BOUNDS: { - const gfx::Rect& bounds = - static_cast<const SetBoundsEvent*>(event)->requested_bounds(); + const auto* set_bounds_event = static_cast<const SetBoundsEvent*>(event); + const gfx::Rect& bounds = set_bounds_event->requested_bounds(); if (set_bounds_locally_) { - switch (bounds_change_animation_type_) { + switch (next_bounds_change_animation_type_) { case kAnimationNone: window_state->SetBoundsDirect(bounds); break; case kAnimationCrossFade: window_state->SetBoundsDirectCrossFade(bounds); break; + case kAnimationAnimated: + window_state->SetBoundsDirectAnimated( + bounds, bounds_change_animation_duration_); + break; } - bounds_change_animation_type_ = kAnimationNone; + next_bounds_change_animation_type_ = kAnimationNone; } else if (!window_state->IsPinned()) { // TODO(oshima): Define behavior for pinned app. + bounds_change_animation_duration_ = set_bounds_event->duration(); delegate_->HandleBoundsRequest(window_state, window_state->GetStateType(), bounds); } @@ -226,13 +232,11 @@ bool ClientControlledState::EnterNextState( WindowState* window_state, - mojom::WindowStateType next_state_type, - BoundsChangeAnimationType animation_type) { + mojom::WindowStateType next_state_type) { // Do nothing if we're already in the same state, or delegate has already // been deleted. if (state_type_ == next_state_type || !delegate_) return false; - bounds_change_animation_type_ = animation_type; mojom::WindowStateType previous_state_type = state_type_; state_type_ = next_state_type;
diff --git a/ash/wm/client_controlled_state.h b/ash/wm/client_controlled_state.h index f298239..d1bf73c4 100644 --- a/ash/wm/client_controlled_state.h +++ b/ash/wm/client_controlled_state.h
@@ -65,8 +65,16 @@ enum BoundsChangeAnimationType { kAnimationNone, kAnimationCrossFade, + kAnimationAnimated, }; + // Sets the type of animation for the next bounds change + // applied locally. + void set_next_bounds_change_animation_type( + BoundsChangeAnimationType animation_type) { + next_bounds_change_animation_type_ = animation_type; + } + // WindowState::State: void AttachState(WindowState* window_state, WindowState::State* previous_state) override; @@ -86,18 +94,17 @@ // Enters next state. This is used when the state moves from one to another // within the same desktop mode. Returns true if the state has changed, or // false otherwise. - // |animation_type| specifies the type of animation to be applied when - // bounds changes. bool EnterNextState(wm::WindowState* window_state, - mojom::WindowStateType next_state_type, - BoundsChangeAnimationType animation_type); + mojom::WindowStateType next_state_type); private: std::unique_ptr<Delegate> delegate_; bool set_bounds_locally_ = false; + base::TimeDelta bounds_change_animation_duration_ = + WindowState::kBoundsChangeSlideDuration; - BoundsChangeAnimationType bounds_change_animation_type_ = kAnimationNone; + BoundsChangeAnimationType next_bounds_change_animation_type_ = kAnimationNone; DISALLOW_COPY_AND_ASSIGN(ClientControlledState); };
diff --git a/ash/wm/client_controlled_state_unittest.cc b/ash/wm/client_controlled_state_unittest.cc index 808515a..43c52297 100644 --- a/ash/wm/client_controlled_state_unittest.cc +++ b/ash/wm/client_controlled_state_unittest.cc
@@ -160,8 +160,7 @@ EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->new_state()); // Now enters the new state. - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); // Bounds is controlled by client. EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -176,8 +175,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); } @@ -188,8 +186,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -198,8 +195,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -209,8 +205,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -222,8 +217,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); } @@ -234,8 +228,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -243,8 +236,7 @@ EXPECT_TRUE(widget()->IsFullscreen()); EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); } @@ -257,8 +249,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -267,8 +258,7 @@ EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -276,8 +266,7 @@ EXPECT_TRUE(widget()->IsFullscreen()); EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -285,16 +274,14 @@ EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->old_state()); EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); } TEST_F(ClientControlledStateTest, IgnoreWorkspace) { widget()->Maximize(); - state()->EnterNextState(window_state(), delegate()->new_state(), - ClientControlledState::kAnimationNone); + state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); delegate()->Reset();
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc index 757c4bd2..2a9bb471 100644 --- a/ash/wm/default_state.cc +++ b/ash/wm/default_state.cc
@@ -392,7 +392,8 @@ window_state->SetBoundsDirect(event->requested_bounds()); } else if (!SetMaximizedOrFullscreenBounds(window_state)) { if (event->animate()) { - window_state->SetBoundsDirectAnimated(event->requested_bounds()); + window_state->SetBoundsDirectAnimated(event->requested_bounds(), + event->duration()); } else { window_state->SetBoundsConstrained(event->requested_bounds()); }
diff --git a/ash/wm/pip/pip_window_resizer.cc b/ash/wm/pip/pip_window_resizer.cc new file mode 100644 index 0000000..6967ddda --- /dev/null +++ b/ash/wm/pip/pip_window_resizer.cc
@@ -0,0 +1,56 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/pip/pip_window_resizer.h" + +#include "ash/wm/window_util.h" +#include "ui/aura/window.h" +#include "ui/display/screen.h" +#include "ui/wm/core/coordinate_conversion.h" + +namespace ash { + +PipWindowResizer::PipWindowResizer(wm::WindowState* window_state) + : WindowResizer(window_state) { + window_state->OnDragStarted(details().window_component); +} + +PipWindowResizer::~PipWindowResizer() {} + +void PipWindowResizer::Drag(const gfx::Point& location_in_parent, + int event_flags) { + last_location_in_screen_ = location_in_parent; + ::wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_in_screen_); + + gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); + display::Display display = + display::Screen::GetScreen()->GetDisplayNearestWindow(GetTarget()); + gfx::Rect work_area = display.work_area(); + bounds.AdjustToFit(work_area); + + if (bounds != GetTarget()->bounds()) { + moved_or_resized_ = true; + GetTarget()->SetBounds(bounds); + } +} + +void PipWindowResizer::CompleteDrag() { + window_state()->OnCompleteDrag(last_location_in_screen_); + window_state()->DeleteDragDetails(); + window_state()->ClearRestoreBounds(); + window_state()->set_bounds_changed_by_user(moved_or_resized_); +} + +void PipWindowResizer::RevertDrag() { + // Handle cancel as a complete drag for pip. Having the PIP window + // go back to where it was on cancel looks strange, so instead just + // will just stop it where it is and animate to the edge of the screen. + CompleteDrag(); +} + +void PipWindowResizer::FlingOrSwipe(ui::GestureEvent* event) { + CompleteDrag(); +} + +} // namespace ash
diff --git a/ash/wm/pip/pip_window_resizer.h b/ash/wm/pip/pip_window_resizer.h new file mode 100644 index 0000000..6254289 --- /dev/null +++ b/ash/wm/pip/pip_window_resizer.h
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_PIP_PIP_WINDOW_RESIZER_H_ +#define ASH_WM_PIP_PIP_WINDOW_RESIZER_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "ash/wm/window_resizer.h" +#include "base/macros.h" +#include "ui/display/display.h" +#include "ui/gfx/geometry/rect.h" + +namespace ash { + +namespace wm { +class WindowState; +} // namespace wm + +// Controls resizing for windows with the PIP window state type. This +// includes things like snapping the PIP window to the edges of the work area +// and handling swipe-to-dismiss. +class ASH_EXPORT PipWindowResizer : public WindowResizer { + public: + explicit PipWindowResizer(wm::WindowState* window_state); + ~PipWindowResizer() override; + + // WindowResizer: + void Drag(const gfx::Point& location_in_parent, int event_flags) override; + void CompleteDrag() override; + void RevertDrag() override; + void FlingOrSwipe(ui::GestureEvent* event) override; + + private: + wm::WindowState* window_state() { return window_state_; } + + gfx::Point last_location_in_screen_; + bool moved_or_resized_ = false; + + DISALLOW_COPY_AND_ASSIGN(PipWindowResizer); +}; + +} // namespace ash + +#endif // ASH_WM_PIP_PIP_WINDOW_RESIZER_H_
diff --git a/ash/wm/pip/pip_window_resizer_unittest.cc b/ash/wm/pip/pip_window_resizer_unittest.cc new file mode 100644 index 0000000..521365f --- /dev/null +++ b/ash/wm/pip/pip_window_resizer_unittest.cc
@@ -0,0 +1,148 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/pip/pip_window_resizer.h" + +#include <string> + +#include "ash/shelf/shelf.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ash/wm/window_state.h" +#include "ash/wm/wm_event.h" +#include "ui/aura/window.h" +#include "ui/base/hit_test.h" +#include "ui/gfx/geometry/insets.h" + +namespace ash { +namespace wm { + +namespace { + +// WindowState based on a given initial state. Records the last resize bounds. +class FakeWindowState : public wm::WindowState::State { + public: + explicit FakeWindowState(mojom::WindowStateType initial_state_type) + : state_type_(initial_state_type) {} + ~FakeWindowState() override = default; + + // WindowState::State overrides: + void OnWMEvent(wm::WindowState* window_state, + const wm::WMEvent* event) override { + if (event->IsBoundsEvent()) { + if (event->type() == wm::WM_EVENT_SET_BOUNDS) { + const auto* set_bounds_event = + static_cast<const wm::SetBoundsEvent*>(event); + last_bounds_ = set_bounds_event->requested_bounds(); + } + } + } + mojom::WindowStateType GetType() const override { return state_type_; } + void AttachState(wm::WindowState* window_state, + wm::WindowState::State* previous_state) override {} + void DetachState(wm::WindowState* window_state) override {} + + const gfx::Rect& last_bounds() { return last_bounds_; } + + private: + mojom::WindowStateType state_type_; + gfx::Rect last_bounds_; + + DISALLOW_COPY_AND_ASSIGN(FakeWindowState); +}; + +} // namespace + +class PipWindowResizerTest : public AshTestBase { + public: + PipWindowResizerTest() = default; + ~PipWindowResizerTest() override = default; + + void SetUp() override { + AshTestBase::SetUp(); + + window_ = CreateTestWindowInShellWithBounds(gfx::Rect(200, 200, 100, 100)); + wm::WindowState* window_state = wm::GetWindowState(window_); + test_state_ = new FakeWindowState(mojom::WindowStateType::PIP); + window_state->SetStateObject( + std::unique_ptr<wm::WindowState::State>(test_state_)); + } + + void TearDown() override { AshTestBase::TearDown(); } + + protected: + aura::Window* window() { return window_; } + FakeWindowState* test_state() { return test_state_; } + + PipWindowResizer* CreateResizerForTest(int window_component) { + wm::WindowState* window_state = wm::GetWindowState(window()); + window_state->CreateDragDetails(gfx::Point(), window_component, + ::wm::WINDOW_MOVE_SOURCE_MOUSE); + return new PipWindowResizer(window_state); + } + + gfx::Point CalculateDragPoint(const WindowResizer& resizer, + int delta_x, + int delta_y) const { + gfx::Point location = resizer.GetInitialLocation(); + location.set_x(location.x() + delta_x); + location.set_y(location.y() + delta_y); + return location; + } + + void UpdateWorkArea(const std::string& bounds) { + UpdateDisplay(bounds); + aura::Window* root = Shell::GetPrimaryRootWindow(); + Shell::Get()->SetDisplayWorkAreaInsets(root, gfx::Insets()); + } + + private: + aura::Window* window_; + FakeWindowState* test_state_; + + DISALLOW_COPY_AND_ASSIGN(PipWindowResizerTest); +}; + +TEST_F(PipWindowResizerTest, PipWindowCanDrag) { + UpdateWorkArea("400x800"); + std::unique_ptr<PipWindowResizer> resizer(CreateResizerForTest(HTCAPTION)); + ASSERT_TRUE(resizer.get()); + + resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0); + EXPECT_EQ("200,210 100x100", test_state()->last_bounds().ToString()); +} + +TEST_F(PipWindowResizerTest, PipWindowCanResize) { + UpdateWorkArea("400x800"); + std::unique_ptr<PipWindowResizer> resizer(CreateResizerForTest(HTBOTTOM)); + ASSERT_TRUE(resizer.get()); + + resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0); + EXPECT_EQ("200,200 100x110", test_state()->last_bounds().ToString()); +} + +TEST_F(PipWindowResizerTest, PipWindowDragIsRestrictedToWorkArea) { + UpdateWorkArea("400x400"); + std::unique_ptr<PipWindowResizer> resizer(CreateResizerForTest(HTCAPTION)); + ASSERT_TRUE(resizer.get()); + + // Drag to the right. + resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0); + EXPECT_EQ("300,200 100x100", test_state()->last_bounds().ToString()); + + // Drag down. + resizer->Drag(CalculateDragPoint(*resizer, 0, 800), 0); + EXPECT_EQ("200,300 100x100", test_state()->last_bounds().ToString()); + + // Drag to the left. + resizer->Drag(CalculateDragPoint(*resizer, -800, 0), 0); + EXPECT_EQ("0,200 100x100", test_state()->last_bounds().ToString()); + + // Drag up. + resizer->Drag(CalculateDragPoint(*resizer, 0, -800), 0); + EXPECT_EQ("200,0 100x100", test_state()->last_bounds().ToString()); +} + +} // namespace wm +} // namespace ash
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index d31eec0..4144f49 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc
@@ -146,6 +146,8 @@ } // namespace +constexpr base::TimeDelta WindowState::kBoundsChangeSlideDuration; + WindowState::~WindowState() { // WindowState is registered as an owned property of |window_|, and window // unregisters all of its observers in its d'tor before destroying its @@ -621,15 +623,13 @@ SetBoundsDirect(child_bounds); } -void WindowState::SetBoundsDirectAnimated(const gfx::Rect& bounds) { - const int kBoundsChangeSlideDurationMs = 120; - +void WindowState::SetBoundsDirectAnimated(const gfx::Rect& bounds, + base::TimeDelta duration) { ui::Layer* layer = window_->layer(); ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator()); slide_settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - slide_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs)); + slide_settings.SetTransitionDuration(duration); SetBoundsDirect(bounds); }
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h index c471434..b709edc 100644 --- a/ash/wm/window_state.h +++ b/ash/wm/window_state.h
@@ -61,6 +61,10 @@ // accessing the window using |window()| is cheap. class ASH_EXPORT WindowState : public aura::WindowObserver { public: + // The default duration for an animation between two sets of bounds. + static constexpr base::TimeDelta kBoundsChangeSlideDuration = + base::TimeDelta::FromMilliseconds(120); + // A subclass of State class represents one of the window's states // that corresponds to WindowStateType in Ash environment, e.g. // maximized, minimized or side snapped, as subclass. @@ -391,8 +395,10 @@ void SetBoundsConstrained(const gfx::Rect& bounds); // Sets the wndow's |bounds| and transitions to the new bounds with - // a scale animation. - void SetBoundsDirectAnimated(const gfx::Rect& bounds); + // a scale animation, with duration specified by |duration|. + void SetBoundsDirectAnimated( + const gfx::Rect& bounds, + base::TimeDelta duration = kBoundsChangeSlideDuration); // Sets the window's |bounds| and transition to the new bounds with // a cross fade animation.
diff --git a/ash/wm/wm_event.cc b/ash/wm/wm_event.cc index 8df1a23..8ad7737 100644 --- a/ash/wm/wm_event.cc +++ b/ash/wm/wm_event.cc
@@ -84,8 +84,12 @@ SetBoundsEvent::SetBoundsEvent(WMEventType type, const gfx::Rect& bounds, - bool animate) - : WMEvent(type), requested_bounds_(bounds), animate_(animate) {} + bool animate, + base::TimeDelta duration) + : WMEvent(type), + requested_bounds_(bounds), + animate_(animate), + duration_(duration) {} SetBoundsEvent::~SetBoundsEvent() = default;
diff --git a/ash/wm/wm_event.h b/ash/wm/wm_event.h index 7ed5d7c1..3b87ecc 100644 --- a/ash/wm/wm_event.h +++ b/ash/wm/wm_event.h
@@ -6,7 +6,9 @@ #define ASH_WM_WM_EVENT_H_ #include "ash/ash_export.h" +#include "ash/wm/window_state.h" #include "base/macros.h" +#include "base/time/time.h" #include "ui/gfx/geometry/rect.h" namespace ash { @@ -131,18 +133,23 @@ // An WMEvent to request new bounds for the window. class ASH_EXPORT SetBoundsEvent : public WMEvent { public: - SetBoundsEvent(WMEventType type, - const gfx::Rect& requested_bounds, - bool animate = false); + SetBoundsEvent( + WMEventType type, + const gfx::Rect& requested_bounds, + bool animate = false, + base::TimeDelta duration = WindowState::kBoundsChangeSlideDuration); ~SetBoundsEvent() override; const gfx::Rect& requested_bounds() const { return requested_bounds_; } bool animate() const { return animate_; } + base::TimeDelta duration() const { return duration_; } + private: gfx::Rect requested_bounds_; bool animate_; + base::TimeDelta duration_; DISALLOW_COPY_AND_ASSIGN(SetBoundsEvent); };
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc index 215910c..a9bf314 100644 --- a/ash/wm/workspace/workspace_window_resizer.cc +++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -17,6 +17,7 @@ #include "ash/shell.h" #include "ash/wm/default_window_resizer.h" #include "ash/wm/drag_window_resizer.h" +#include "ash/wm/pip/pip_window_resizer.h" #include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_positioning_utils.h" @@ -117,10 +118,15 @@ // refactor and eliminate chaining. std::unique_ptr<WindowResizer> window_resizer; + if (window_state->IsPip()) { + window_state->CreateDragDetails(point_in_parent, window_component, source); + window_resizer = std::make_unique<PipWindowResizer>(window_state); + return window_resizer; + } + if (Shell::Get() ->tablet_mode_controller() - ->IsTabletModeWindowManagerEnabled() && - !window_state->IsPip()) { + ->IsTabletModeWindowManagerEnabled()) { if (!CanDragInTabletMode(window, window_component)) return nullptr; @@ -132,7 +138,7 @@ return window_resizer; } - if (!window_state->IsNormalOrSnapped() && !window_state->IsPip()) + if (!window_state->IsNormalOrSnapped()) return nullptr; int bounds_change =
diff --git a/base/synchronization/atomic_flag.cc b/base/synchronization/atomic_flag.cc index 5aed67f..a7ff0e7 100644 --- a/base/synchronization/atomic_flag.cc +++ b/base/synchronization/atomic_flag.cc
@@ -16,17 +16,15 @@ DETACH_FROM_SEQUENCE(set_sequence_checker_); } +AtomicFlag::~AtomicFlag() = default; + void AtomicFlag::Set() { DCHECK_CALLED_ON_VALID_SEQUENCE(set_sequence_checker_); - base::subtle::Release_Store(&flag_, 1); -} - -bool AtomicFlag::IsSet() const { - return base::subtle::Acquire_Load(&flag_) != 0; + flag_.store(1, std::memory_order_release); } void AtomicFlag::UnsafeResetForTesting() { - base::subtle::Release_Store(&flag_, 0); + flag_.store(0, std::memory_order_release); } } // namespace base
diff --git a/base/synchronization/atomic_flag.h b/base/synchronization/atomic_flag.h index a98a35c..f386a16 100644 --- a/base/synchronization/atomic_flag.h +++ b/base/synchronization/atomic_flag.h
@@ -5,7 +5,10 @@ #ifndef BASE_SYNCHRONIZATION_ATOMIC_FLAG_H_ #define BASE_SYNCHRONIZATION_ATOMIC_FLAG_H_ -#include "base/atomicops.h" +#include <stdint.h> + +#include <atomic> + #include "base/base_export.h" #include "base/macros.h" #include "base/sequence_checker.h" @@ -18,7 +21,7 @@ class BASE_EXPORT AtomicFlag { public: AtomicFlag(); - ~AtomicFlag() = default; + ~AtomicFlag(); // Set the flag. Must always be called from the same sequence. void Set(); @@ -26,14 +29,17 @@ // Returns true iff the flag was set. If this returns true, the current thread // is guaranteed to be synchronized with all memory operations on the sequence // which invoked Set() up until at least the first call to Set() on it. - bool IsSet() const; + bool IsSet() const { + // Inline here: this has a measurable performance impact on base::WeakPtr. + return flag_.load(std::memory_order_acquire) != 0; + } // Resets the flag. Be careful when using this: callers might not expect // IsSet() to return false after returning true once. void UnsafeResetForTesting(); private: - base::subtle::Atomic32 flag_ = 0; + std::atomic<uint_fast8_t> flag_{0}; SEQUENCE_CHECKER(set_sequence_checker_); DISALLOW_COPY_AND_ASSIGN(AtomicFlag);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index d1c30fdd..d61e686b 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -154,6 +154,14 @@ custom_package = "org.chromium.chrome.download" } +android_resources("chrome_autofill_assistant_java_resources") { + resource_dirs = [ "//chrome/android/java/res_autofill_assistant" ] + deps = [ + ":chrome_app_java_resources", + ] + custom_package = "org.chromium.chrome.autofill_assistant" +} + java_strings_grd("chrome_strings_grd") { defines = chrome_grit_defines grd_file = "java/strings/android_chrome_strings.grd" @@ -223,6 +231,7 @@ android_library("chrome_java") { deps = [ ":chrome_app_java_resources", + ":chrome_autofill_assistant_java_resources", ":chrome_download_java_resources", ":chrome_public_android_manifest", ":chrome_public_apk_template_resources",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java index 24d6cf4a..35bd1f7b 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
@@ -4,11 +4,15 @@ package org.chromium.chrome.browser.feed; +import com.google.android.libraries.feed.host.logging.ActionType; import com.google.android.libraries.feed.host.logging.BasicLoggingApi; import com.google.android.libraries.feed.host.logging.ContentLoggingData; import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.ui.mojom.WindowOpenDisposition; + +import java.util.concurrent.TimeUnit; /** * Implementation of {@link BasicLoggingApi} that log actions performed on the Feed, @@ -39,34 +43,36 @@ public void onContentViewed(ContentLoggingData data) { assert mNativeFeedLoggingBridge != 0; nativeOnContentViewed(mNativeFeedLoggingBridge, data.getPositionInStream(), - data.getPublishedTimeSeconds(), data.getTimeContentBecameAvailable(), - data.getScore()); + TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), + TimeUnit.SECONDS.toMillis(data.getTimeContentBecameAvailable()), data.getScore()); } @Override public void onContentDismissed(ContentLoggingData data) { assert mNativeFeedLoggingBridge != 0; - nativeOnContentDismissed(mNativeFeedLoggingBridge, data.getRepresentationUri()); + nativeOnContentDismissed( + mNativeFeedLoggingBridge, data.getPositionInStream(), data.getRepresentationUri()); } @Override public void onContentClicked(ContentLoggingData data) { assert mNativeFeedLoggingBridge != 0; nativeOnContentClicked(mNativeFeedLoggingBridge, data.getPositionInStream(), - data.getPublishedTimeSeconds(), data.getScore()); + TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), data.getScore()); } @Override - public void onClientAction(ContentLoggingData data, int actionType) { + public void onClientAction(ContentLoggingData data, @ActionType int actionType) { assert mNativeFeedLoggingBridge != 0; - nativeOnClientAction(mNativeFeedLoggingBridge, actionType); + nativeOnClientAction( + mNativeFeedLoggingBridge, feedActionToWindowOpenDisposition(actionType)); } @Override public void onContentContextMenuOpened(ContentLoggingData data) { assert mNativeFeedLoggingBridge != 0; nativeOnContentContextMenuOpened(mNativeFeedLoggingBridge, data.getPositionInStream(), - data.getPublishedTimeSeconds(), data.getScore()); + TimeUnit.SECONDS.toMillis(data.getPublishedTimeSeconds()), data.getScore()); } @Override @@ -119,16 +125,37 @@ nativeOnOfflinePageVisited(mNativeFeedLoggingBridge, visitTimeMs); } + private int feedActionToWindowOpenDisposition(@ActionType int actionType) { + switch (actionType) { + case ActionType.OPEN_URL: + return WindowOpenDisposition.CURRENT_TAB; + case ActionType.OPEN_URL_INCOGNITO: + return WindowOpenDisposition.IGNORE_ACTION; + case ActionType.OPEN_URL_NEW_TAB: + return WindowOpenDisposition.NEW_BACKGROUND_TAB; + case ActionType.OPEN_URL_NEW_WINDOW: + return WindowOpenDisposition.NEW_WINDOW; + case ActionType.DOWNLOAD: + return WindowOpenDisposition.SAVE_TO_DISK; + case ActionType.LEARN_MORE: + case ActionType.UNKNOWN: + default: + return WindowOpenDisposition.UNKNOWN; + } + } + private native long nativeInit(Profile profile); private native void nativeDestroy(long nativeFeedLoggingBridge); private native void nativeOnContentViewed(long nativeFeedLoggingBridge, int position, - long publishedTimeSeconds, long timeContentBecameAvailable, float score); - private native void nativeOnContentDismissed(long nativeFeedLoggingBridge, String uri); + long publishedTimeMs, long timeContentBecameAvailableMs, float score); + private native void nativeOnContentDismissed( + long nativeFeedLoggingBridge, int position, String uri); private native void nativeOnContentClicked( - long nativeFeedLoggingBridge, int position, long publishedTimeSeconds, float score); - private native void nativeOnClientAction(long nativeFeedLoggingBridge, int actionType); + long nativeFeedLoggingBridge, int position, long publishedTimeMs, float score); + private native void nativeOnClientAction( + long nativeFeedLoggingBridge, int windowOpenDisposition); private native void nativeOnContentContextMenuOpened( - long nativeFeedLoggingBridge, int position, long publishedTimeSeconds, float score); + long nativeFeedLoggingBridge, int position, long publishedTimeMs, float score); private native void nativeOnMoreButtonViewed(long nativeFeedLoggingBridge, int position); private native void nativeOnMoreButtonClicked(long nativeFeedLoggingBridge, int position); private native void nativeOnOpenedWithContent(
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java index a07113ab..5faf2c6 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -71,7 +71,6 @@ // Used when Feed is enabled. private @Nullable Stream mStream; private @Nullable FeedImageLoader mImageLoader; - private @Nullable FeedLoggingBridge mLoggingBridge; private @Nullable StreamLifecycleManager mStreamLifecycleManager; private @Nullable SectionHeaderView mSectionHeaderView; private @Nullable MarginResizer mSectionHeaderViewMarginResizer; @@ -256,7 +255,6 @@ mMediator.destroy(); if (mStreamLifecycleManager != null) mStreamLifecycleManager.destroy(); if (mImageLoader != null) mImageLoader.destroy(); - if (mLoggingBridge != null) mLoggingBridge.destroy(); mTab.getWindowAndroid().removeContextMenuCloseListener(mContextMenuManager); } @@ -306,13 +304,13 @@ Profile profile = mTab.getProfile(); mImageLoader = new FeedImageLoader(profile, activity); - mLoggingBridge = new FeedLoggingBridge(profile); + FeedLoggingBridge loggingBridge = FeedProcessScopeFactory.getFeedLoggingBridge(); FeedOfflineIndicator offlineIndicator = FeedProcessScopeFactory.getFeedOfflineIndicator(); Runnable consumptionObserver = () -> FeedProcessScopeFactory.getFeedScheduler().onSuggestionConsumed(); ActionApi actionApi = new FeedActionHandler(mNewTabPageManager.getNavigationDelegate(), consumptionObserver, offlineIndicator, OfflinePageBridge.getForProfile(profile), - mLoggingBridge); + loggingBridge); FeedStreamScope streamScope = feedProcessScope @@ -320,7 +318,7 @@ new BasicStreamConfiguration(), new BasicCardConfiguration(activity.getResources(), mUiConfig), new BasicSnackbarApi(mNewTabPageManager.getSnackbarManager()), - mLoggingBridge, offlineIndicator, + loggingBridge, offlineIndicator, (FeedAppLifecycleListener) feedProcessScope.getAppLifecycleListener()) .build(); @@ -368,8 +366,6 @@ mStream = null; mImageLoader.destroy(); mImageLoader = null; - mLoggingBridge.destroy(); - mLoggingBridge = null; mSectionHeaderView = null; mSectionHeaderViewMarginResizer.detach(); mSectionHeaderViewMarginResizer = null;
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java index 36038f0..8111f6d 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
@@ -34,6 +34,7 @@ private static FeedScheduler sFeedScheduler; private static FeedOfflineIndicator sFeedOfflineIndicator; private static NetworkClient sTestNetworkClient; + private static FeedLoggingBridge sFeedLoggingBridge; /** @return The shared {@link FeedProcessScope} instance. Null if the Feed is disabled. */ public static @Nullable FeedProcessScope getFeedProcessScope() { @@ -72,6 +73,15 @@ return sFeedAppLifecycle; } + /** @return The {@link FeedLoggingBridge} that was given to the {@link FeedStreamScope}. Null if + * the Feed is disabled. */ + public static @Nullable FeedLoggingBridge getFeedLoggingBridge() { + if (sFeedLoggingBridge == null) { + initialize(); + } + return sFeedLoggingBridge; + } + /** * @return Whether the dependencies provided by this class are allowed to be created. The feed * process is disabled if supervised user or enterprise policy has once been added @@ -84,7 +94,7 @@ private static void initialize() { assert sFeedProcessScope == null && sFeedScheduler == null && sFeedOfflineIndicator == null - && sFeedAppLifecycle == null; + && sFeedAppLifecycle == null && sFeedLoggingBridge == null; if (!isFeedProcessEnabled()) return; sPrefChangeRegistrar = new PrefChangeRegistrar(); @@ -107,6 +117,7 @@ FeedJournalStorage journalStorage = new FeedJournalStorage(profile); NetworkClient networkClient = sTestNetworkClient == null ? new FeedNetworkBridge(profile) : sTestNetworkClient; + sFeedLoggingBridge = new FeedLoggingBridge(profile); sFeedProcessScope = new FeedProcessScope .Builder(configHostApi, Executors.newSingleThreadExecutor(), new LoggingApiImpl(), networkClient, schedulerBridge, @@ -202,5 +213,9 @@ sFeedAppLifecycle.destroy(); sFeedAppLifecycle = null; } + if (sFeedLoggingBridge != null) { + sFeedLoggingBridge.destroy(); + sFeedLoggingBridge = null; + } } }
diff --git a/chrome/android/java/res_autofill_assistant/drawable-hdpi/autofill_assistant_bottombar_bg.9.png b/chrome/android/java/res_autofill_assistant/drawable-hdpi/autofill_assistant_bottombar_bg.9.png new file mode 100644 index 0000000..606060d7 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable-hdpi/autofill_assistant_bottombar_bg.9.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-mdpi/autofill_assistant_bottombar_bg.9.png b/chrome/android/java/res_autofill_assistant/drawable-mdpi/autofill_assistant_bottombar_bg.9.png new file mode 100644 index 0000000..6d12e19 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable-mdpi/autofill_assistant_bottombar_bg.9.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-xhdpi/autofill_assistant_bottombar_bg.9.png b/chrome/android/java/res_autofill_assistant/drawable-xhdpi/autofill_assistant_bottombar_bg.9.png new file mode 100644 index 0000000..cbba344 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable-xhdpi/autofill_assistant_bottombar_bg.9.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/autofill_assistant_bottombar_bg.9.png b/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/autofill_assistant_bottombar_bg.9.png new file mode 100644 index 0000000..f0ccbfea --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable-xxhdpi/autofill_assistant_bottombar_bg.9.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable-xxxhdpi/autofill_assistant_bottombar_bg.9.png b/chrome/android/java/res_autofill_assistant/drawable-xxxhdpi/autofill_assistant_bottombar_bg.9.png new file mode 100644 index 0000000..a286cb21 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable-xxxhdpi/autofill_assistant_bottombar_bg.9.png Binary files differ
diff --git a/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg.xml b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg.xml new file mode 100644 index 0000000..86aa4759 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_pressed="true" + android:drawable="@drawable/autofill_assistant_chip_bg_pressed" /> + <item + android:drawable="@drawable/autofill_assistant_chip_bg_normal" /> +</selector>
diff --git a/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg_normal.xml b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg_normal.xml new file mode 100644 index 0000000..b3c0ba1 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg_normal.xml
@@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners + android:radius="20dp" /> + <solid + android:color="@color/white_mode_tint" /> + <stroke + android:width="1dp" + android:color="@color/modern_grey_300" /> +</shape>
diff --git a/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg_pressed.xml b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg_pressed.xml new file mode 100644 index 0000000..1bdf15ea --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_chip_bg_pressed.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners + android:radius="20dp" /> + <solid + android:color="@color/modern_grey_300" /> +</shape>
diff --git a/chrome/android/java/res/layout/autofill_assistant_chip.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_chip.xml similarity index 81% rename from chrome/android/java/res/layout/autofill_assistant_chip.xml rename to chrome/android/java/res_autofill_assistant/layout/autofill_assistant_chip.xml index 1ae075380..ea7c4f9 100644 --- a/chrome/android/java/res/layout/autofill_assistant_chip.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_chip.xml
@@ -8,7 +8,8 @@ android:layout_height="wrap_content" android:paddingStart="16dp" android:paddingEnd="16dp" + android:textAppearance="@style/BlackBodyDefault" android:gravity="center_vertical" android:minHeight="40dp" android:singleLine="true" - android:background="@drawable/chip_bg" /> + android:background="@drawable/autofill_assistant_chip_bg" />
diff --git a/chrome/android/java/res/layout/autofill_assistant_sheet.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml similarity index 76% rename from chrome/android/java/res/layout/autofill_assistant_sheet.xml rename to chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml index c81f1134..535f5ace 100644 --- a/chrome/android/java/res/layout/autofill_assistant_sheet.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml
@@ -15,24 +15,12 @@ android:id="@+id/overlay" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/white_alpha_90" android:gravity="center" android:clickable="true" android:visibility="gone" android:focusable="false" android:orientation="vertical"> - - <ProgressBar - style="@style/Widget.AppCompat.ProgressBar.Horizontal" - android:layout_width="match_parent" - android:layout_height="16dp" - android:indeterminate="true" /> - - <TextView - android:id="@+id/overlay_text" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:gravity="center_horizontal" /> </LinearLayout> <LinearLayout @@ -40,16 +28,17 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" - android:background="@drawable/popup_bg_bottom" + android:background="@drawable/autofill_assistant_bottombar_bg" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="56dp" - android:layout_marginTop="8dp" + android:layout_marginTop="16dp" android:layout_marginStart="24dp" android:layout_marginEnd="24dp" - android:orientation="horizontal"> + android:orientation="horizontal" + android:gravity="center_vertical"> <android.support.v7.widget.AppCompatImageView android:layout_width="24dp" android:layout_height="24dp" @@ -59,10 +48,13 @@ android:id="@+id/status_message" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_gravity="center_vertical" + android:gravity="center_vertical" android:paddingStart="24dp" - android:maxLines="1" - android:layout_weight="1.0"/> + android:paddingEnd="24dp" + android:textAppearance="@style/BlackTitle2" + android:layout_weight="1.0" + android:maxLines="2" + android:ellipsize="end"/> <ImageButton android:id="@+id/feedback_button" @@ -87,7 +79,9 @@ <RelativeLayout android:id="@+id/details" android:layout_width="match_parent" - android:layout_height="60dp" + android:layout_height="@dimen/autofill_assistant_details_image_size" + android:layout_marginStart="24dp" + android:layout_marginEnd="24dp" android:layout_marginBottom="8dp" android:visibility="gone"> <TextView @@ -96,7 +90,11 @@ android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentStart="true" - android:layout_toStartOf="@+id/details_image"/> + android:layout_toStartOf="@+id/details_image" + android:gravity="center_vertical" + android:textAppearance="@style/BlackTitle2" + android:maxLines="1" + android:ellipsize="end"/> <TextView android:id="@+id/details_text" android:layout_width="wrap_content" @@ -105,14 +103,20 @@ android:layout_above="@+id/details_time" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/details_image" - android:gravity="center_vertical" /> + android:gravity="center_vertical" + android:textAppearance="@style/BlackBody" + android:maxLines="1" + android:ellipsize="end"/> <TextView android:id="@+id/details_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentStart="true" - android:layout_toStartOf="@+id/details_image"/> + android:gravity="center_vertical" + android:textAppearance="@style/TextAppearance.AutofillAssistantDetailsTime" + android:maxLines="1" + android:ellipsize="end"/> <android.support.v7.widget.AppCompatImageView android:id="@+id/details_image" android:layout_width="@dimen/autofill_assistant_details_image_size" @@ -132,10 +136,10 @@ android:id="@+id/carousel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:layout_marginBottom="8dp" - android:layout_marginStart="24dp" - android:layout_marginEnd="24dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:paddingStart="24dp" + android:paddingEnd="24dp" android:gravity="center_vertical" android:orientation="horizontal"> </LinearLayout>
diff --git a/chrome/android/java/res_autofill_assistant/values-v17/styles.xml b/chrome/android/java/res_autofill_assistant/values-v17/styles.xml new file mode 100644 index 0000000..41c86a2b --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/values-v17/styles.xml
@@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<resources xmlns:tools="http://schemas.android.com/tools"> + <!-- Q: Why put style resources under values-v17/ ? + A: Problem: + 1. paddingStart causes a crash on Galaxy Tab&Note b/8351339. + 2. So we wrote a build script(generate_v14_compatible_resources.py) to convert + paddingStart to paddingLeft for pre-v17 (crbug.com/235118). + 3. However, style files are not overridden by the corresponding generated style files, + but merged when we pass them to aapt unlike layout files. + + So we decided to keep style resources under values-v17/ so that it is not merged with + the generated style resources under res_v14_compatibility/values/ (crbug.com/243952). + --> + + <style + name="TextAppearance.AutofillAssistantDetailsTime" + parent="@style/BlackBodyDefault"> + <item name="android:textColor">@color/google_green_700</item> + </style> +</resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java index f9e7432..c996577 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
@@ -14,6 +14,7 @@ import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.support.v7.widget.AppCompatImageView; import android.text.TextUtils; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,7 +22,7 @@ import android.widget.TextView; import org.chromium.base.Promise; -import org.chromium.chrome.R; +import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; @@ -223,7 +224,7 @@ * @param scriptHandles List of scripts to show. */ public void updateScripts(ArrayList<ScriptHandle> scriptHandles) { - mChipsViewContainer.removeAllViews(); + clearChipsViewContainer(); if (scriptHandles.isEmpty()) { return; @@ -233,18 +234,33 @@ ScriptHandle scriptHandle = scriptHandles.get(i); TextView chipView = createChipView(scriptHandle.getName()); chipView.setOnClickListener((unusedView) -> { - mChipsViewContainer.removeAllViews(); + clearChipsViewContainer(); mClient.onScriptSelected(scriptHandle.getPath()); }); - mChipsViewContainer.addView(chipView); + addChipViewToContainer(chipView); } ensureFullContainerIsShown(); } + private void addChipViewToContainer(TextView newChild) { + // Add a left margin if it's not the first child. + if (mChipsViewContainer.getChildCount() > 0) { + LinearLayout.LayoutParams layoutParams = + new LinearLayout.LayoutParams(newChild.getLayoutParams()); + int leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, + newChild.getContext().getResources().getDisplayMetrics()); + layoutParams.setMargins(leftMargin, 0, 0, 0); + newChild.setLayoutParams(layoutParams); + } + + mChipsViewContainer.addView(newChild); + mChipsViewContainer.setVisibility(View.VISIBLE); + } + private TextView createChipView(String text) { TextView chipView = (TextView) (LayoutInflater.from(mActivity).inflate( - R.layout.autofill_assistant_chip, null /* root */)); + R.layout.autofill_assistant_chip, mChipsViewContainer, false)); chipView.setText(text); return chipView; } @@ -269,7 +285,7 @@ mDetailsText.setText(getDetailsText(details)); mDetailsTime.setText(getDetailsTime(details.getDate())); - mDetailsImage.setVisibility(View.GONE); + mDetailsImage.setVisibility(View.INVISIBLE); mDetails.setVisibility(View.VISIBLE); ensureFullContainerIsShown(); @@ -332,22 +348,27 @@ return; } - mChipsViewContainer.removeAllViews(); + clearChipsViewContainer(); for (int i = 0; i < profiles.size(); i++) { AutofillProfile profile = profiles.get(i); // TODO(crbug.com/806868): Show more information than the street. TextView chipView = createChipView(profile.getStreetAddress()); chipView.setOnClickListener((unusedView) -> { - mChipsViewContainer.removeAllViews(); + clearChipsViewContainer(); mClient.onAddressSelected(profile.getGUID()); }); - mChipsViewContainer.addView(chipView); + addChipViewToContainer(chipView); } ensureFullContainerIsShown(); } + private void clearChipsViewContainer() { + mChipsViewContainer.removeAllViews(); + mChipsViewContainer.setVisibility(View.GONE); + } + /** * Show credit cards in the bar. * @@ -359,17 +380,17 @@ return; } - mChipsViewContainer.removeAllViews(); + clearChipsViewContainer(); for (int i = 0; i < cards.size(); i++) { CreditCard card = cards.get(i); // TODO(crbug.com/806868): Show more information than the card number. TextView chipView = createChipView(card.getObfuscatedNumber()); chipView.setOnClickListener((unusedView) -> { - mChipsViewContainer.removeAllViews(); + clearChipsViewContainer(); mClient.onCardSelected(card.getGUID()); }); - mChipsViewContainer.addView(chipView); + addChipViewToContainer(chipView); } ensureFullContainerIsShown();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java index 8122c9d..1b06bfe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -28,6 +28,7 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.ContextUtils; import org.chromium.base.PathUtils; +import org.chromium.base.StrictModeContext; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordUserAction; @@ -342,7 +343,9 @@ */ public static boolean isPackageSpecializedHandler(String packageName, Intent intent) { Context context = ContextUtils.getApplicationContext(); - try { + // On certain Samsung devices, queryIntentActivities can trigger a + // StrictModeDiskReadViolation (https://crbug.com/894160). + try (StrictModeContext unused = StrictModeContext.allowDiskReads()){ List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities( intent, PackageManager.GET_RESOLVED_FILTER); return getSpecializedHandlersWithFilter(handlers, packageName, intent).size() > 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java index da99bfc..5af33e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
@@ -22,12 +22,14 @@ import android.widget.Button; import android.widget.ListView; +import org.chromium.base.CollectionUtil; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.browsing_data.BrowsingDataType; import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTab; +import org.chromium.chrome.browser.browsing_data.CookieOrCacheDeletionChoice; import org.chromium.chrome.browser.browsing_data.TimePeriod; import org.chromium.chrome.browser.historyreport.AppIndexingReporter; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; @@ -42,6 +44,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -280,8 +283,8 @@ /** * @return All available {@link DialogOption} entries. */ - protected final static ArraySet<Integer> getAllOptions() { - ArraySet<Integer> all = new ArraySet<>(); + protected final static Set<Integer> getAllOptions() { + Set<Integer> all = new ArraySet<>(); for (@DialogOption int i = DialogOption.CLEAR_HISTORY; i < DialogOption.NUM_ENTRIES; i++) { all.add(i); } @@ -293,11 +296,10 @@ * @param options The set of selected {@link DialogOption} entries. * @return int[] List of {@link BrowsingDataType} that should be deleted. */ - protected int[] getDataTypesFromOptions(ArraySet<Integer> options) { - int[] dataTypes = new int[options.size()]; - int i = 0; + protected Set<Integer> getDataTypesFromOptions(Set<Integer> options) { + Set<Integer> dataTypes = new ArraySet<>(); for (@DialogOption Integer option : options) { - dataTypes[i++] = getDataType(option); + dataTypes.add(getDataType(option)); } return dataTypes; } @@ -305,8 +307,8 @@ /** * @return The currently selected {@link DialogOption} entries. */ - protected final ArraySet<Integer> getSelectedOptions() { - ArraySet<Integer> selected = new ArraySet<>(); + protected final Set<Integer> getSelectedOptions() { + Set<Integer> selected = new ArraySet<>(); for (Item item : mItems) { if (item.isSelected()) selected.add(item.getOption()); } @@ -334,26 +336,41 @@ * Requests the browsing data corresponding to the given dialog options to be deleted. * @param options The dialog options whose corresponding data should be deleted. */ - private void clearBrowsingData(ArraySet<Integer> options, @Nullable String[] blacklistedDomains, + private void clearBrowsingData(Set<Integer> options, @Nullable String[] blacklistedDomains, @Nullable int[] blacklistedDomainReasons, @Nullable String[] ignoredDomains, @Nullable int[] ignoredDomainReasons) { onClearBrowsingData(); showProgressDialog(); + Set<Integer> dataTypes = getDataTypesFromOptions(options); RecordHistogram.recordMediumTimesHistogram("History.ClearBrowsingData.TimeSpentInDialog", SystemClock.elapsedRealtime() - mDialogOpened, TimeUnit.MILLISECONDS); - int[] dataTypes = getDataTypesFromOptions(options); + final @CookieOrCacheDeletionChoice int choice; + if (dataTypes.contains(BrowsingDataType.COOKIES)) { + choice = dataTypes.contains(BrowsingDataType.CACHE) + ? CookieOrCacheDeletionChoice.BOTH_COOKIES_AND_CACHE + : CookieOrCacheDeletionChoice.ONLY_COOKIES; + } else { + choice = dataTypes.contains(BrowsingDataType.CACHE) + ? CookieOrCacheDeletionChoice.ONLY_CACHE + : CookieOrCacheDeletionChoice.NEITHER_COOKIES_NOR_CACHE; + } + RecordHistogram.recordEnumeratedHistogram( + "History.ClearBrowsingData.UserDeletedCookieOrCacheFromDialog", choice, + CookieOrCacheDeletionChoice.MAX_CHOICE_VALUE); Object spinnerSelection = ((SpinnerPreference) findPreference(PREF_TIME_RANGE)).getSelectedOption(); int timePeriod = ((TimePeriodSpinnerOption) spinnerSelection).getTimePeriod(); + // TODO(bsazonov): Change integerListToIntArray to handle Collection<Integer>. + int[] dataTypesArray = CollectionUtil.integerListToIntArray(new ArrayList<>(dataTypes)); if (blacklistedDomains != null && blacklistedDomains.length != 0) { - BrowsingDataBridge.getInstance().clearBrowsingDataExcludingDomains(this, dataTypes, + BrowsingDataBridge.getInstance().clearBrowsingDataExcludingDomains(this, dataTypesArray, timePeriod, blacklistedDomains, blacklistedDomainReasons, ignoredDomains, ignoredDomainReasons); } else { - BrowsingDataBridge.getInstance().clearBrowsingData(this, dataTypes, timePeriod); + BrowsingDataBridge.getInstance().clearBrowsingData(this, dataTypesArray, timePeriod); } // Clear all reported entities. @@ -454,7 +471,7 @@ * </ol> */ private boolean shouldShowImportantSitesDialog() { - ArraySet<Integer> selectedOptions = getSelectedOptions(); + Set<Integer> selectedOptions = getSelectedOptions(); if (!selectedOptions.contains(DialogOption.CLEAR_CACHE) && !selectedOptions.contains(DialogOption.CLEAR_COOKIES_AND_SITE_DATA)) { return false; @@ -555,7 +572,7 @@ // Not all checkboxes defined in the layout are necessarily handled by this class // or a particular subclass. Hide those that are not. - ArraySet<Integer> unboundOptions = getAllOptions(); + Set<Integer> unboundOptions = getAllOptions(); unboundOptions.removeAll(options); for (@DialogOption Integer option : unboundOptions) { getPreferenceScreen().removePreference(findPreference(getPreferenceKey(option)));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java index 66446b9d..4082ad1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.preferences.privacy; import android.os.Bundle; -import android.support.v4.util.ArraySet; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; @@ -23,6 +22,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Set; /** * A simpler version of {@link ClearBrowsingDataPreferences} with fewer dialog options and more @@ -76,20 +76,13 @@ } @Override - protected int[] getDataTypesFromOptions(ArraySet<Integer> options) { - int[] dataTypes; - int i = 0; + protected Set<Integer> getDataTypesFromOptions(Set<Integer> options) { + Set<Integer> dataTypes = super.getDataTypesFromOptions(options); if (options.contains(DialogOption.CLEAR_COOKIES_AND_SITE_DATA)) { // COOKIES checkbox includes MEDIA_LICENSES, which need to be // specified separately. This is only done for the basic tab. // On the advanced tab Media Licenses has its own checkbox. - dataTypes = new int[options.size() + 1]; - dataTypes[i++] = BrowsingDataType.MEDIA_LICENSES; - } else { - dataTypes = new int[options.size()]; - } - for (Integer option : options) { - dataTypes[i++] = getDataType(option); + dataTypes.add(BrowsingDataType.MEDIA_LICENSES); } return dataTypes; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index b689894..257b746 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -69,7 +69,10 @@ private WebContentsObserver mObserver; public static void from(Tab tab) { - tab.getUserDataHost().setUserData(USER_DATA_KEY, new TabWebContentsObserver(tab)); + TabWebContentsObserver observer = get(tab); + if (observer == null) { + tab.getUserDataHost().setUserData(USER_DATA_KEY, new TabWebContentsObserver(tab)); + } } @VisibleForTesting
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java index 09c7d481..1db9f72 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -66,6 +66,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Integration tests for ClearBrowsingDataPreferences. @@ -624,7 +625,7 @@ } } - private void setDataTypesToClear(final ArraySet<Integer> typesToClear) { + private void setDataTypesToClear(final Set<Integer> typesToClear) { ThreadUtils.runOnUiThreadBlocking(() -> { for (@DialogOption Integer option : ClearBrowsingDataPreferences.getAllOptions()) { boolean enabled = typesToClear.contains(option);
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni index 0b56bd0..066e59bc 100644 --- a/chrome/android/webapk/shell_apk/current_version/current_version.gni +++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@ # //chrome/android/webapk/shell_apk:webapk is changed. This includes # Java files, Android resource files and AndroidManifest.xml. Does not affect # Chrome.apk -current_shell_apk_version = 63 +current_shell_apk_version = 64
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java index fcfa6e11..c76a74b 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java
@@ -32,12 +32,12 @@ private static final String TAG = "cr_HostBrowserUtils"; /** - * The package names of the channels of Chrome that support WebAPKs. The most preferred one - * comes first. + * The package names of the browsers that support WebAPKs. The most preferred one comes first. */ - private static List<String> sBrowsersSupportingWebApk = new ArrayList<String>( - Arrays.asList("com.google.android.apps.chrome", "com.android.chrome", "com.chrome.beta", - "com.chrome.dev", "com.chrome.canary", "org.chromium.chrome")); + private static List<String> sBrowsersSupportingWebApk = + new ArrayList<String>(Arrays.asList("com.google.android.apps.chrome", + "com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.chrome.canary", + "org.chromium.chrome", "org.chromium.arc.intent_helper")); /** Caches the package name of the host browser. */ private static String sHostPackage;
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index 713ac2d0..101b0f89 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -151,9 +151,6 @@ #define IDC_SHOW_KEYBOARD_OVERLAY 40027 #define IDC_PROFILING_ENABLED 40028 #define IDC_BOOKMARKS_MENU 40029 -// TODO(atwilson): Remove IDC_SHOW_SYNC_SETUP when we officially allow signin -// when sync is disabled. -#define IDC_SHOW_SYNC_SETUP 40030 #define IDC_SHOW_SIGNIN 40030 #define IDC_EXTENSION_ERRORS 40031 #define IDC_SHOW_SIGNIN_ERROR 40032
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 9881509..d43d0ddb 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -691,9 +691,6 @@ <message name="IDS_DISCOVER_PIN_SETUP_SUBTITLE1" desc="A sub-title of the dialog that starts 'PIN-unlock' setup process. Subtitle explains to the user how this feature can be configured."> Use a number (PIN) instead of a password to unlock your device. To set your PIN later, go to Settings. </message> - <message name="IDS_DISCOVER_PIN_SETUP_LEARN_MORE" desc="A label on the link that leads to the help page."> - Learn more - </message> <message name="IDS_DISCOVER_PIN_SETUP_SKIP" desc="A label on the button that interrupts current setup flow."> Skip </message> @@ -704,7 +701,19 @@ Your PIN is added </message> <message name="IDS_DISCOVER_PIN_SETUP_SUBTITLE3" desc="A sub-title of the dialog that finishes 'PIN-unlock' setup process successfully suggesting how user can use the PIN that they have just set up."> - You can use PIN to unlock your device when signed out + You can use PIN to unlock your device when you signed out. + </message> + <message name="IDS_DISCOVER_PIN_SETUP" desc="A label on the button that leads to Pin Unlock feature set up."> + Pin setup + </message> + <message name="IDS_DISCOVER_PIN_SETUP_PASSWORD_TITLE" desc="A title of the dialog that starts 'PIN-unlock' setup process, and asks user to type their password first."> + Confirm your password + </message> + <message name="IDS_DISCOVER_PIN_SETUP_PASSWORD_SUBTITLE" desc="A sub-title of the dialog that starts 'PIN-unlock' setup process, and asks user to type their password first."> + Enter your password to configure screen lock and sign-in + </message> + <message name="IDS_DISCOVER_PIN_SETUP_DONE" desc="Label for the done button on the success screen in 'PIN-unlock' setup dialog."> + Done </message> <message name="IDS_APP_START_NETWORK_WAIT_MESSAGE" desc="Message displayed while installing and/or launching web application in kiosk mode."> Waiting for network connection...
diff --git a/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP.png.sha1 new file mode 100644 index 0000000..d1ceca3 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP.png.sha1
@@ -0,0 +1 @@ +0bcf70651e715c2a6ee25f6087dd5ca7d06d0f36 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_DONE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_DONE.png.sha1 new file mode 100644 index 0000000..6e9a3fb --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_DONE.png.sha1
@@ -0,0 +1 @@ +b9f29ad0e5b2f9da1b79b53b881ccf9ff1b2ba81 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_PASSWORD_SUBTITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_PASSWORD_SUBTITLE.png.sha1 new file mode 100644 index 0000000..d499c53 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_PASSWORD_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +f2f12b480baa8b7015852593f61af93711541436 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_PASSWORD_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_PASSWORD_TITLE.png.sha1 new file mode 100644 index 0000000..d499c53 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_PASSWORD_TITLE.png.sha1
@@ -0,0 +1 @@ +f2f12b480baa8b7015852593f61af93711541436 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_SUBTITLE3.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_SUBTITLE3.png.sha1 index 05dc333..6e9a3fb 100644 --- a/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_SUBTITLE3.png.sha1 +++ b/chrome/app/chromeos_strings_grdp/IDS_DISCOVER_PIN_SETUP_SUBTITLE3.png.sha1
@@ -1 +1 @@ -71a9d2779ab9039cccc94f1791ea4141b6f16387 \ No newline at end of file +b9f29ad0e5b2f9da1b79b53b881ccf9ff1b2ba81 \ No newline at end of file
diff --git a/chrome/app/file_manager_strings.grdp b/chrome/app/file_manager_strings.grdp index 649da9d..f4848de 100644 --- a/chrome/app/file_manager_strings.grdp +++ b/chrome/app/file_manager_strings.grdp
@@ -513,6 +513,9 @@ <message name="IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL" desc="Label for menu that will share a folder with the crostini Linux container."> Share with Linux </message> + <message name="IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL" desc="Label for menu that will take users to the settings page where they can manage which files and folders are shared with the crostini Linux container."> + Manage Linux sharing + </message> <message name="IDS_FILE_BROWSER_TOGGLE_HIDDEN_FILES_COMMAND_LABEL" desc="Label for menu or button with checkmark that toggles visibility of hidden files."> Show hidden files </message>
diff --git a/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1 b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..caf2eb1 --- /dev/null +++ b/chrome/app/file_manager_strings_grdp/IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +129ee36bc8d092098adb2dd669278d7010b109a7 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index bb7bbbd..e1aa088 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5563,6 +5563,9 @@ <message name="IDS_PICTURE_IN_PICTURE_CLOSE_CONTROL_TEXT" desc="Text label of the close control button. The button appears when the user hovers over the Picture-in-Picture window."> Close </message> + <message name="IDS_PICTURE_IN_PICTURE_RESIZE_HANDLE_TEXT" desc="Text label of the resize handle. The button appears when the user hovers over the Picture-in-Picture window."> + Resize + </message> <message name="IDS_PICTURE_IN_PICTURE_PLAY_PAUSE_CONTROL_ACCESSIBLE_TEXT" desc="Accessible text label used for the controls button in the Picture-in-Picture window. The button toggles between play and pause controls."> Toggle video to play or pause </message>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index 5fc11590..cb203c62 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -79,6 +79,7 @@ "reload_touch.icon", "remove.icon", "remove_box.icon", + "resize_handle.icon", "sad_tab.icon", "security.icon", "sensors.icon",
diff --git a/chrome/app/vector_icons/resize_handle.icon b/chrome/app/vector_icons/resize_handle.icon new file mode 100644 index 0000000..3865d96 --- /dev/null +++ b/chrome/app/vector_icons/resize_handle.icon
@@ -0,0 +1,11 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 15, +STROKE, 2.f, +MOVE_TO, 2, 2, +R_LINE_TO, 11.31f, 11.31f, +MOVE_TO, 9, 2, +R_LINE_TO, 4.24f, 4.24f, +CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 8e95359..a0d0dd38 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -367,6 +367,8 @@ "data_use_measurement/chrome_data_use_ascriber_service.h", "data_use_measurement/chrome_data_use_ascriber_service_factory.cc", "data_use_measurement/chrome_data_use_ascriber_service_factory.h", + "data_use_measurement/chrome_data_use_measurement.cc", + "data_use_measurement/chrome_data_use_measurement.h", "data_use_measurement/chrome_data_use_recorder.cc", "data_use_measurement/chrome_data_use_recorder.h", "data_use_measurement/data_use_web_contents_observer.cc",
diff --git a/chrome/browser/android/feed/feed_logging_bridge.cc b/chrome/browser/android/feed/feed_logging_bridge.cc index 5937cfb7..22f8430 100644 --- a/chrome/browser/android/feed/feed_logging_bridge.cc +++ b/chrome/browser/android/feed/feed_logging_bridge.cc
@@ -6,6 +6,8 @@ #include <jni.h> +#include "base/android/jni_string.h" +#include "base/time/time.h" #include "chrome/browser/android/feed/feed_host_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" @@ -38,54 +40,77 @@ FeedLoggingBridge::~FeedLoggingBridge() = default; -void FeedLoggingBridge::Destroy(JNIEnv* env, const JavaRef<jobject>& j_this) { +void FeedLoggingBridge::Destroy(JNIEnv* j_env, const JavaRef<jobject>& j_this) { delete this; } void FeedLoggingBridge::OnContentViewed( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint position, - const jlong publishedTimeSeconds, - const jlong timeContentBecameAvailable, - const jfloat score) {} + const jint j_position, + const jlong j_publishedTimeSeconds, + const jlong j_timeContentBecameAvailableSeconds, + const jfloat j_score) { + feed_logging_metrics_->OnSuggestionShown( + j_position, base::Time::FromJavaTime(j_publishedTimeSeconds), j_score, + base::Time::FromJavaTime(j_timeContentBecameAvailableSeconds)); +} void FeedLoggingBridge::OnContentDismissed( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const base::android::JavaRef<jstring>& j_url) {} + const jint j_position, + const base::android::JavaRef<jstring>& j_url) { + feed_logging_metrics_->OnSuggestionDismissed( + j_position, GURL(ConvertJavaStringToUTF8(j_env, j_url))); +} void FeedLoggingBridge::OnContentClicked( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint position, - const jlong publishedTimeSeconds, - const jfloat score) {} + const jint j_position, + const jlong j_publishedTimeSeconds, + const jfloat j_score) { + feed_logging_metrics_->OnSuggestionOpened( + j_position, base::Time::FromJavaTime(j_publishedTimeSeconds), j_score); +} void FeedLoggingBridge::OnClientAction( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint j_action_type) {} + const jint j_window_open_disposition) { + feed_logging_metrics_->OnSuggestionWindowOpened( + static_cast<WindowOpenDisposition>(j_window_open_disposition)); +} void FeedLoggingBridge::OnContentContextMenuOpened( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint position, - const jlong publishedTimeSeconds, - const jfloat score) {} + const jint j_position, + const jlong j_publishedTimeSeconds, + const jfloat j_score) { + feed_logging_metrics_->OnSuggestionMenuOpened( + j_position, base::Time::FromJavaTime(j_publishedTimeSeconds), j_score); +} void FeedLoggingBridge::OnMoreButtonViewed(JNIEnv* j_env, const JavaRef<jobject>& j_this, - const jint j_position) {} + const jint j_position) { + feed_logging_metrics_->OnMoreButtonShown(j_position); +} void FeedLoggingBridge::OnMoreButtonClicked(JNIEnv* j_env, const JavaRef<jobject>& j_this, - const jint j_position) {} + const jint j_position) { + feed_logging_metrics_->OnMoreButtonClicked(j_position); +} void FeedLoggingBridge::OnOpenedWithContent(JNIEnv* j_env, const JavaRef<jobject>& j_this, const jint j_time_to_Populate, - const jint j_content_count) {} + const jint j_content_count) { + feed_logging_metrics_->OnPageShown(j_content_count); +} void FeedLoggingBridge::OnOpenedWithNoImmediateContent( JNIEnv* j_env, @@ -98,11 +123,17 @@ void FeedLoggingBridge::OnContentTargetVisited( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jlong visit_time) {} + const jlong visit_time_ms) { + feed_logging_metrics_->OnSuggestionArticleVisited( + base::TimeDelta::FromMilliseconds(visit_time_ms)); +} void FeedLoggingBridge::OnOfflinePageVisited( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jlong visit_time) {} + const jlong visit_time_ms) { + feed_logging_metrics_->OnSuggestionOfflinePageVisited( + base::TimeDelta::FromMilliseconds(visit_time_ms)); +} } // namespace feed
diff --git a/chrome/browser/android/feed/feed_logging_bridge.h b/chrome/browser/android/feed/feed_logging_bridge.h index e06ea226..f0ee72f4 100644 --- a/chrome/browser/android/feed/feed_logging_bridge.h +++ b/chrome/browser/android/feed/feed_logging_bridge.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_ANDROID_FEED_FEED_LOGGING_BRIDGE_H_ #define CHROME_BROWSER_ANDROID_FEED_FEED_LOGGING_BRIDGE_H_ +#include <utility> + #include "base/android/scoped_java_ref.h" namespace feed { @@ -23,30 +25,31 @@ void OnContentViewed(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint position, - const jlong publishedTimeSeconds, - const jlong timeContentBecameAvailable, - const jfloat score); + const jint j_position, + const jlong j_publishedTimeMs, + const jlong j_timeContentBecameAvailableMs, + const jfloat j_score); void OnContentDismissed(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, + const jint j_position, const base::android::JavaRef<jstring>& j_url); void OnContentClicked(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint position, - const jlong publishedTimeSeconds, - const jfloat score); + const jint j_position, + const jlong j_publishedTimeMs, + const jfloat j_score); void OnClientAction(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint j_action_type); + const jint j_window_open_disposition); void OnContentContextMenuOpened(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jint position, - const jlong publishedTimeSeconds, - const jfloat score); + const jint j_position, + const jlong j_publishedTimeMs, + const jfloat j_score); void OnMoreButtonViewed(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, @@ -70,11 +73,11 @@ void OnContentTargetVisited(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jlong visit_time); + const jlong visit_time_ms); void OnOfflinePageVisited(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const jlong visit_time); + const jlong visit_time_ms); private: FeedLoggingMetrics* feed_logging_metrics_;
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc index 57e325b..1a557bb 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.cc +++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/chromeos/system/timezone_util.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" #include "chrome/browser/component_updater/metadata_table_chromeos.h" -#include "chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chromeos/account_manager/account_manager_factory.h" @@ -176,13 +175,6 @@ return timezone_resolver_.get(); } -chromeos::DiscoverManager* BrowserProcessPlatformPart::GetDiscoverManager() { - if (!discover_manager_.get()) - discover_manager_ = std::make_unique<chromeos::DiscoverManager>(); - - return discover_manager_.get(); -} - void BrowserProcessPlatformPart::StartTearDown() { // interactive_ui_tests check for memory leaks before this object is // destroyed. So we need to destroy |timezone_resolver_| here.
diff --git a/chrome/browser/browser_process_platform_part_chromeos.h b/chrome/browser/browser_process_platform_part_chromeos.h index b2f616d..77c2d5c9 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.h +++ b/chrome/browser/browser_process_platform_part_chromeos.h
@@ -19,7 +19,6 @@ class AccountManagerFactory; class ChromeSessionManager; class ChromeUserManager; -class DiscoverManager; class ProfileHelper; class TimeZoneResolver; @@ -105,8 +104,6 @@ chromeos::TimeZoneResolver* GetTimezoneResolver(); - chromeos::DiscoverManager* GetDiscoverManager(); - // Overridden from BrowserProcessPlatformPartBase: void StartTearDown() override; std::unique_ptr<policy::ChromeBrowserPolicyConnector> @@ -163,8 +160,6 @@ input_device_controller_client_; #endif - std::unique_ptr<chromeos::DiscoverManager> discover_manager_; - SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(BrowserProcessPlatformPart);
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc new file mode 100644 index 0000000..eb4983e --- /dev/null +++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc
@@ -0,0 +1,126 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/browsing_data/counters/browsing_data_counter_utils.h" + +#include "build/buildflag.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/unified_consent/unified_consent_service_factory.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/browser_sync/profile_sync_service.h" +#include "components/signin/core/browser/signin_buildflags.h" +#include "components/sync/test/fake_server/fake_server_network_resources.h" +#include "components/unified_consent/feature.h" +#include "components/unified_consent/scoped_unified_consent.h" + +#if BUILDFLAG(ENABLE_DICE_SUPPORT) || defined(OS_CHROMEOS) +#include "chrome/browser/signin/scoped_account_consistency.h" +#endif + +#if defined(OS_CHROMEOS) +#include "chrome/browser/signin/signin_manager_factory.h" +#include "components/signin/core/browser/signin_manager_base.h" +#endif + +namespace { + +class BrowsingDataCounterUtilsBrowserTest + : public SyncTest, + public testing::WithParamInterface<bool> { + public: + BrowsingDataCounterUtilsBrowserTest() + : SyncTest(SINGLE_CLIENT), +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + scoped_dice_(GetParam() + ? std::make_unique<ScopedAccountConsistencyDice>() + : nullptr), +#elif defined(OS_CHROMEOS) + scoped_mirror_(std::make_unique<ScopedAccountConsistencyMirror>()), +#endif + scoped_unified_consent_( + GetParam() + ? unified_consent::UnifiedConsentFeatureState::kEnabledNoBump + : unified_consent::UnifiedConsentFeatureState::kDisabled) { + } + ~BrowsingDataCounterUtilsBrowserTest() override = default; + + private: +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + // ScopedAccountConsistencyDice is required for unified consent to be enabled. + const std::unique_ptr<ScopedAccountConsistencyDice> scoped_dice_; +#elif defined(OS_CHROMEOS) + // Need to manually turn on mirror for now. + const std::unique_ptr<ScopedAccountConsistencyMirror> scoped_mirror_; +#endif + const unified_consent::ScopedUnifiedConsent scoped_unified_consent_; + + DISALLOW_COPY_AND_ASSIGN(BrowsingDataCounterUtilsBrowserTest); +}; + +// Instantiate test for unified consent disabled & enabled. +INSTANTIATE_TEST_CASE_P(, + BrowsingDataCounterUtilsBrowserTest, + ::testing::Bool()); + +IN_PROC_BROWSER_TEST_P(BrowsingDataCounterUtilsBrowserTest, + ShouldShowCookieException) { + Profile* profile = browser()->profile(); + + browser_sync::ProfileSyncService* sync_service = + ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); + + sync_service->OverrideNetworkResourcesForTest( + std::make_unique<fake_server::FakeServerNetworkResources>( + GetFakeServer()->AsWeakPtr())); + + std::string username; +#if defined(OS_CHROMEOS) + // In browser tests, the profile may already by authenticated with stub + // account |user_manager::kStubUserEmail|. + AccountInfo info = SigninManagerFactory::GetForProfile(profile) + ->GetAuthenticatedAccountInfo(); + username = info.email; +#endif + if (username.empty()) + username = "user@gmail.com"; + + std::unique_ptr<ProfileSyncServiceHarness> harness = + ProfileSyncServiceHarness::Create( + profile, username, "unused" /* password */, + ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN); + +#if defined(OS_CHROMEOS) + // On Chrome OS, the profile is always authenticated. + EXPECT_TRUE(ShouldShowCookieException(profile)); +#else + // By default, a fresh profile is not signed in, nor syncing, so no cookie + // exception should be shown. + EXPECT_FALSE(ShouldShowCookieException(profile)); + + // Sign the profile in. + EXPECT_TRUE(harness->SignInPrimaryAccount()); + + // Sign-in alone shouldn't lead to a cookie exception. + EXPECT_FALSE(ShouldShowCookieException(profile)); +#endif + + // Enable sync. + EXPECT_TRUE(harness->SetupSync()); + + // Now that we're syncing, we should offer to retain the cookie. + EXPECT_TRUE(ShouldShowCookieException(profile)); + +#if !defined(OS_CHROMEOS) + // Pause sync. + harness->SignOutPrimaryAccount(); + + // There's no point in showing the cookie exception. + EXPECT_FALSE(ShouldShowCookieException(profile)); +#endif // !defined(OS_CHROMEOS) +} + +} // namespace
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 5b2417a..005eae6 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -107,6 +107,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/task_manager/task_manager_interface.h" #include "chrome/browser/ui/ash/chrome_keyboard_controller_client.h" +#include "chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h" #include "chrome/browser/upgrade_detector/upgrade_detector_chromeos.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_constants.h" @@ -118,7 +119,6 @@ #include "chromeos/accelerometer/accelerometer_reader.h" #include "chromeos/audio/audio_devices_pref_handler_impl.h" #include "chromeos/audio/cras_audio_handler.h" -#include "chromeos/chromeos_paths.h" #include "chromeos/chromeos_switches.h" #include "chromeos/components/drivefs/fake_drivefs_launcher_client.h" #include "chromeos/cryptohome/async_method_caller.h" @@ -267,22 +267,6 @@ #endif } -void RegisterStubPathOverridesIfNecessary() { - // These overrides need to occur before BrowserPolicyConnectorChromeOS - // (for one) is created. The DCHECK ensures that is the case. - DCHECK(!g_browser_process); - - base::FilePath user_data_dir; - if (base::SysInfo::IsRunningOnChromeOS() || - !base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { - return; - } - - // Override some paths with stub locations so that cloud policy and enterprise - // enrollment work on desktop builds, for ease of development. - chromeos::RegisterStubPathOverrides(user_data_dir); -} - } // namespace namespace internal { @@ -566,8 +550,6 @@ .value(); } - RegisterStubPathOverridesIfNecessary(); - #if defined(GOOGLE_CHROME_BUILD) const char kChromeOSReleaseTrack[] = "CHROMEOS_RELEASE_TRACK"; std::string channel; @@ -680,6 +662,8 @@ chromeos::ResourceReporter::GetInstance()->StartMonitoring( task_manager::TaskManagerInterface::GetTaskManager()); + discover_manager_ = std::make_unique<DiscoverManager>(); + ChromeBrowserMainPartsLinux::PreMainMessageLoopRun(); }
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h index 5940c06..3d290ce 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -35,6 +35,7 @@ class ArcKioskAppManager; class DemoModeResourcesRemover; +class DiscoverManager; class EventRewriterDelegateImpl; class IdleActionWarningObserver; class LowDiskNotification; @@ -143,6 +144,7 @@ std::unique_ptr<DemoModeResourcesRemover> demo_mode_resources_remover_; std::unique_ptr<crostini::CrosvmMetrics> crosvm_metrics_; + std::unique_ptr<DiscoverManager> discover_manager_; DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainPartsChromeos); };
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc index 75a0736..a5fad95 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -724,6 +724,8 @@ IDS_FILE_BROWSER_MANAGE_IN_DRIVE_BUTTON_LABEL); SET_STRING("SHARE_WITH_LINUX_BUTTON_LABEL", IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL); + SET_STRING("MANAGE_LINUX_SHARING_BUTTON_LABEL", + IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL); SET_STRING("CHANGE_TO_LISTVIEW_BUTTON_LABEL", IDS_FILE_BROWSER_CHANGE_TO_LISTVIEW_BUTTON_LABEL); SET_STRING("CHANGE_TO_THUMBNAILVIEW_BUTTON_LABEL",
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc index 1ccc228..7c69ca680 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.cc
@@ -79,6 +79,9 @@ constexpr const char* kMostCommonPins[] = {"1212", "1004", "2000", "6969", "1122", "1313", "2001", "1010"}; +// QuickUnlockPrivateGetAuthTokenFunction test observer. +QuickUnlockPrivateGetAuthTokenFunction::TestObserver* test_observer; + // Returns the active set of quick unlock modes. void ComputeActiveModes(Profile* profile, ActiveModeCallback result) { user_manager::User* user = @@ -221,6 +224,12 @@ authenticator_allocator_ = allocator; } +// static +void QuickUnlockPrivateGetAuthTokenFunction::SetTestObserver( + QuickUnlockPrivateGetAuthTokenFunction::TestObserver* observer) { + test_observer = observer; +} + ExtensionFunction::ResponseAction QuickUnlockPrivateGetAuthTokenFunction::Run() { std::unique_ptr<quick_unlock_private::GetAuthToken::Params> params = @@ -233,6 +242,9 @@ chromeos::UserContext user_context(*user); user_context.SetKey(chromeos::Key(params->account_password)); + if (test_observer) + test_observer->OnGetAuthTokenCalled(params->account_password); + // Alter |user_context| if the user is supervised. if (user->GetType() == user_manager::USER_TYPE_SUPERVISED) { user_context = chromeos::ChromeUserManager::Get()
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h index 1d8b90bc..ffc7bd7 100644 --- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h +++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h
@@ -29,6 +29,11 @@ base::Callback<chromeos::ExtendedAuthenticator*( chromeos::AuthStatusConsumer* auth_status_consumer)>; + class TestObserver { + public: + virtual void OnGetAuthTokenCalled(const std::string&) = 0; + }; + QuickUnlockPrivateGetAuthTokenFunction(); // Use the given |allocator| to create an ExtendedAuthenticator instance. This @@ -36,6 +41,10 @@ void SetAuthenticatorAllocatorForTesting( const AuthenticatorAllocator& allocator); + // Test API. + static void SetTestObserver( + QuickUnlockPrivateGetAuthTokenFunction::TestObserver* observer); + DECLARE_EXTENSION_FUNCTION("quickUnlockPrivate.getAuthToken", QUICKUNLOCKPRIVATE_GETAUTHTOKEN);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index c7cdf72..8b31f902 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -390,6 +390,7 @@ ::testing::Values(TestCase("openQuickView"), TestCase("openQuickView").InGuestMode(), TestCase("openQuickView").TabletMode(), + TestCase("openQuickViewAudio"), TestCase("openQuickViewImage"), TestCase("openQuickViewVideo"), // QuickView PDF test fails on MSAN, crbug.com/768070 @@ -666,6 +667,7 @@ TestCase("hideSearchButton"), TestCase("myFilesDisplaysAndOpensEntries"), TestCase("directoryTreeRefresh"), + TestCase("myFilesFolderRename"), TestCase("myFilesUpdatesChildren"))); WRAPPED_INSTANTIATE_TEST_CASE_P(
diff --git a/chrome/browser/chromeos/file_manager/file_manager_uitest.cc b/chrome/browser/chromeos/file_manager/file_manager_uitest.cc index bfec5f1..d742644 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_uitest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_uitest.cc
@@ -61,8 +61,16 @@ RunTest("checkselect"); } -IN_PROC_BROWSER_TEST_F(FileManagerUITest, Crostini) { - RunTest("crostini"); +IN_PROC_BROWSER_TEST_F(FileManagerUITest, CrostiniMount) { + RunTest("crostiniMount"); +} + +IN_PROC_BROWSER_TEST_F(FileManagerUITest, CrostiniShare) { + RunTest("crostiniShare"); +} + +IN_PROC_BROWSER_TEST_F(FileManagerUITest, CrostiniTasks) { + RunTest("crostiniTasks"); } IN_PROC_BROWSER_TEST_F(FileManagerUITest, QuickView) {
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc index 2b826081..d366900 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
@@ -186,7 +186,7 @@ on_setup_success_ = std::move(on_setup_success); on_setup_error_ = std::move(on_setup_error); - VLOG(1) << "Starting demo mode enrollment " + VLOG(1) << "Starting demo setup " << DemoSession::DemoConfigToString(demo_config_); switch (demo_config_) { @@ -206,6 +206,7 @@ } void DemoSetupController::LoadDemoResourcesCrOSComponent() { + VLOG(1) << "Loading demo resources component"; component_updater::CrOSComponentManager* cros_component_manager = g_browser_process->platform_part()->cros_component_manager(); // In tests, use the desired error code. @@ -238,6 +239,7 @@ return; } + VLOG(1) << "Starting online enrollment"; policy::DeviceCloudPolicyManagerChromeOS* policy_manager = g_browser_process->platform_part() ->browser_policy_connector_chromeos() @@ -266,6 +268,7 @@ return; } + VLOG(1) << "Checking if offline policy exists"; std::string* message = new std::string(); base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, @@ -285,6 +288,7 @@ return; } + VLOG(1) << "Starting offline enrollment"; policy::EnrollmentConfig config; config.mode = policy::EnrollmentConfig::MODE_OFFLINE_DEMO; config.management_domain = DemoSetupController::kDemoModeDomain; @@ -323,6 +327,7 @@ // Try to load the policy for the device local account. if (demo_config_ == DemoSession::DemoModeConfig::kOffline) { + VLOG(1) << "Loading offline policy"; DCHECK(!policy_dir_.empty()); const base::FilePath file_path = policy_dir_.AppendASCII(kOfflineDeviceLocalAccountPolicyFileName); @@ -334,7 +339,7 @@ weak_ptr_factory_.GetWeakPtr())); return; } - + VLOG(1) << "Marking device registered"; StartupUtils::MarkDeviceRegistered( base::BindOnce(&DemoSetupController::OnDeviceRegistered, weak_ptr_factory_.GetWeakPtr())); @@ -394,6 +399,7 @@ return; } + VLOG(1) << "Storing offline policy"; // On the unittest, the device_local_account_policy_store_ is already // initialized. Otherwise attempts to get the store. if (!device_local_account_policy_store_) { @@ -449,6 +455,7 @@ void DemoSetupController::OnStoreLoaded(policy::CloudPolicyStore* store) { DCHECK_EQ(store, device_local_account_policy_store_); + VLOG(1) << "Marking device registered"; StartupUtils::MarkDeviceRegistered( base::BindOnce(&DemoSetupController::OnDeviceRegistered, weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc index 35d6e0b..2f34bba 100644 --- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc +++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -4,7 +4,9 @@ #include "base/command_line.h" #include "base/macros.h" +#include "base/optional.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h" #include "chrome/browser/chromeos/login/screens/gaia_view.h" #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h" #include "chrome/browser/chromeos/login/screens/update_screen.h" @@ -61,7 +63,27 @@ DISALLOW_COPY_AND_ASSIGN(JsConditionWaiter); }; -class OobeInteractiveUITest : public OobeBaseTest { +class ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver { + public: + explicit ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver( + extensions::QuickUnlockPrivateGetAuthTokenFunction::TestObserver* + observer) { + extensions::QuickUnlockPrivateGetAuthTokenFunction::SetTestObserver( + observer); + } + ~ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver() { + extensions::QuickUnlockPrivateGetAuthTokenFunction::SetTestObserver( + nullptr); + } + + private: + DISALLOW_COPY_AND_ASSIGN( + ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver); +}; + +class OobeInteractiveUITest + : public OobeBaseTest, + public extensions::QuickUnlockPrivateGetAuthTokenFunction::TestObserver { public: OobeInteractiveUITest() = default; ~OobeInteractiveUITest() override = default; @@ -72,6 +94,11 @@ OobeBaseTest::SetUpCommandLine(command_line); } + // QuickUnlockPrivateGetAuthTokenFunction::TestObserver: + void OnGetAuthTokenCalled(const std::string& password) override { + quick_unlock_private_get_auth_token_password_ = password; + } + void TearDownOnMainThread() override { // If the login display is still showing, exit gracefully. if (LoginDisplayHost::default_host()) { @@ -219,6 +246,41 @@ screen->SetProfileSyncDisabledByPolicyForTesting(true); screen->OnStateChanged(nullptr); + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id != 'sync-consent'") + .Wait(); + LOG(INFO) << "OobeInteractiveUITest: 'sync-consent' screen done."; + } + + void WaitForDiscoverScreen() { + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id == 'discover'") + .Wait(); + LOG(INFO) << "OobeInteractiveUITest: Switched to 'discover' screen."; + } + + void RunDiscoverScreenChecks() { + js_checker_.ExpectTrue("!$('discover').hidden"); + js_checker_.ExpectTrue("!$('discover-impl').hidden"); + js_checker_.ExpectTrue( + "!$('discover-impl').root.querySelector('discover-pin-setup-module')." + "hidden"); + js_checker_.ExpectTrue( + "!$('discover-impl').root.querySelector('discover-pin-setup-module').$." + "setup.hidden"); + EXPECT_TRUE(quick_unlock_private_get_auth_token_password_.has_value()); + EXPECT_EQ(quick_unlock_private_get_auth_token_password_, + OobeBaseTest::kFakeUserPassword); + } + + void ExitDiscoverPinSetupScreen() { + js_checker_.Evaluate( + "$('discover-impl').root.querySelector('discover-pin-setup-module')." + "$.setupSkipButton.click()"); + JsConditionWaiter(js_checker_, + "Oobe.getInstance().currentScreen.id != 'discover'") + .Wait(); + LOG(INFO) << "OobeInteractiveUITest: 'discover' screen done."; } void WaitForMarketingOptInScreen() { @@ -260,12 +322,16 @@ WaitForLoginDisplayHostShutdown(); } + base::Optional<std::string> quick_unlock_private_get_auth_token_password_; + private: DISALLOW_COPY_AND_ASSIGN(OobeInteractiveUITest); }; // Flakily times out: crbug.com/891484. IN_PROC_BROWSER_TEST_F(OobeInteractiveUITest, DISABLED_SimpleEndToEnd) { + ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver scoped_observer(this); + WaitForOobeWelcomeScreen(); RunWelcomeScreenChecks(); TapWelcomeNext(); @@ -291,6 +357,10 @@ ExitScreenSyncConsent(); #endif + WaitForDiscoverScreen(); + RunDiscoverScreenChecks(); + ExitDiscoverPinSetupScreen(); + WaitForMarketingOptInScreen(); RunMarketingOptInScreenChecks(); ExitMarketingOptInScreen();
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 119bf3b..0f20487 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -72,6 +72,7 @@ #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/install_attributes.h" #include "chrome/browser/chromeos/tether/tether_service.h" #include "chrome/browser/chromeos/tpm_firmware_update_notification.h" #include "chrome/browser/component_updater/crl_set_component_installer.h" @@ -93,6 +94,8 @@ #include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h" #include "chrome/browser/ui/app_list/app_list_client_impl.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" +#include "chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h" +#include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/logging_chrome.h" @@ -1185,25 +1188,31 @@ input_method::InputMethodManager::Get(); manager->SetState(GetDefaultIMEState(profile)); } + user_manager::UserManager* user_manager = user_manager::UserManager::Get(); // Set initial prefs if the user is new, or if the user was already present on // the device and the profile was re-created. This can happen e.g. in ext4 // migration in wipe mode. - if (user_manager::UserManager::Get()->IsCurrentUserNew() || - profile->IsNewProfile()) { + if (user_manager->IsCurrentUserNew() || profile->IsNewProfile()) { SetFirstLoginPrefs(profile, user_context.GetPublicSessionLocale(), user_context.GetPublicSessionInputMethod()); + + if (user_manager->GetPrimaryUser() == user && + user->GetType() == user_manager::USER_TYPE_REGULAR && + !user_manager->IsUserNonCryptohomeDataEphemeral(user->GetAccountId())) { + chromeos::DiscoverManager::Get() + ->GetModule<chromeos::DiscoverModulePinSetup>() + ->SetPrimaryUserPassword(user_context.GetPasswordKey()->GetSecret()); + } } - if (user_manager::UserManager::Get()->IsLoggedInAsSupervisedUser()) { - user_manager::User* active_user = - user_manager::UserManager::Get()->GetActiveUser(); + if (user_manager->IsLoggedInAsSupervisedUser()) { + user_manager::User* active_user = user_manager->GetActiveUser(); std::string supervised_user_sync_id = ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId( active_user->GetAccountId().GetUserEmail()); profile->GetPrefs()->SetString(prefs::kSupervisedUserId, supervised_user_sync_id); - } else if (user_manager::UserManager::Get() - ->IsLoggedInAsUserWithGaiaAccount()) { + } else if (user_manager->IsLoggedInAsUserWithGaiaAccount()) { // Get the Gaia ID from the user context. If it's not available, this may // not be available when unlocking a previously opened profile, or when // creating a supervised users. However, in these cases the gaia_id should @@ -1237,7 +1246,7 @@ /*refresh_token=*/std::string()); std::string account_id = identity_manager->GetPrimaryAccountId(); const user_manager::User* user = - user_manager::UserManager::Get()->FindUser(user_context.GetAccountId()); + user_manager->FindUser(user_context.GetAccountId()); bool is_child = user->GetType() == user_manager::USER_TYPE_CHILD; DCHECK(is_child == (user_context.GetUserType() == user_manager::USER_TYPE_CHILD));
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index cdab13c..c139a658 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -1124,6 +1124,10 @@ } void WizardController::OnSyncConsentFinished() { + ShowDiscoverScreen(); +} + +void WizardController::OnDiscoverScreenFinished() { ShowMarketingOptInScreen(); } @@ -1742,7 +1746,7 @@ OnDemoPreferencesCanceled(); break; case ScreenExitCode::DISCOVER_FINISHED: - OnOobeFlowFinished(); + OnDiscoverScreenFinished(); break; case ScreenExitCode::FINGERPRINT_SETUP_FINISHED: OnFingerprintSetupFinished();
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h index 9df4097..d94eefc 100644 --- a/chrome/browser/chromeos/login/wizard_controller.h +++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -231,6 +231,7 @@ void OnTermsOfServiceDeclined(); void OnTermsOfServiceAccepted(); void OnSyncConsentFinished(); + void OnDiscoverScreenFinished(); void OnFingerprintSetupFinished(); void OnArcTermsOfServiceSkipped(); void OnArcTermsOfServiceAccepted();
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc index aa24356..a1c6da0 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
@@ -10,8 +10,10 @@ #include "base/feature_list.h" #include "build/build_config.h" +#include "chrome/browser/data_use_measurement/chrome_data_use_measurement.h" #include "chrome/browser/data_use_measurement/chrome_data_use_recorder.h" #include "components/data_use_measurement/content/content_url_request_classifier.h" +#include "components/data_use_measurement/core/data_use_network_delegate.h" #include "components/data_use_measurement/core/data_use_recorder.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/data_use_measurement/core/url_request_classifier.h" @@ -112,8 +114,7 @@ if (service) { auto entry = CreateNewDataUseRecorder(request, DataUse::TrafficType::SERVICES); - entry->data_use().set_description( - DataUseUserData::GetServiceNameAsString(service->service_name())); + entry->data_use().set_description(""); return entry; } @@ -577,6 +578,15 @@ observer.OnPageLoadConcluded(&entry->data_use()); } +std::unique_ptr<net::NetworkDelegate> +ChromeDataUseAscriber::CreateNetworkDelegate( + std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate) { + return std::make_unique<data_use_measurement::DataUseNetworkDelegate>( + std::move(wrapped_network_delegate), this, + std::make_unique<ChromeDataUseMeasurement>(CreateURLRequestClassifier(), + this)); +} + std::unique_ptr<URLRequestClassifier> ChromeDataUseAscriber::CreateURLRequestClassifier() const { return std::make_unique<ContentURLRequestClassifier>();
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h index ca04f16a..039c8a4 100644 --- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h +++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.h
@@ -69,6 +69,8 @@ void OnBeforeUrlRequest(net::URLRequest* request) override; void OnUrlRequestCompleted(net::URLRequest* request, bool started) override; void OnUrlRequestDestroyed(net::URLRequest* request) override; + std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate( + std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate) override; std::unique_ptr<URLRequestClassifier> CreateURLRequestClassifier() const override;
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_measurement.cc b/chrome/browser/data_use_measurement/chrome_data_use_measurement.cc new file mode 100644 index 0000000..f73d7f3b --- /dev/null +++ b/chrome/browser/data_use_measurement/chrome_data_use_measurement.cc
@@ -0,0 +1,65 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/data_use_measurement/chrome_data_use_measurement.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/macros.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "chrome/browser/browser_process.h" +#include "components/data_use_measurement/core/data_use_ascriber.h" +#include "components/data_use_measurement/core/url_request_classifier.h" +#include "components/metrics/metrics_service.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" + +namespace data_use_measurement { + +namespace { +void UpdateMetricsUsagePrefs(int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // Some unit tests use IOThread but do not initialize MetricsService. In that + // case it's fine to skip the update. + auto* metrics_service = g_browser_process->metrics_service(); + if (metrics_service) { + metrics_service->UpdateMetricsUsagePrefs(total_bytes, is_cellular, + is_metrics_service_usage); + } +} + +// This function is for forwarding metrics usage pref changes to the metrics +// service on the appropriate thread. +// TODO(gayane): Reduce the frequency of posting tasks from IO to UI thread. +void UpdateMetricsUsagePrefsOnUIThread(int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + base::PostTaskWithTraits( + FROM_HERE, content::BrowserThread::UI, + base::BindOnce(UpdateMetricsUsagePrefs, total_bytes, is_cellular, + is_metrics_service_usage)); +} +} // namespace + +ChromeDataUseMeasurement::ChromeDataUseMeasurement( + std::unique_ptr<URLRequestClassifier> url_request_classifier, + DataUseAscriber* ascriber) + : DataUseMeasurement(std::move(url_request_classifier), ascriber) {} + +void ChromeDataUseMeasurement::UpdateDataUseToMetricsService( + int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) { + // Update data use of user traffic and services distinguishing cellular and + // metrics services data use. + UpdateMetricsUsagePrefsOnUIThread(total_bytes, is_cellular, + is_metrics_service_usage); +} + +} // namespace data_use_measurement
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_measurement.h b/chrome/browser/data_use_measurement/chrome_data_use_measurement.h new file mode 100644 index 0000000..d21d639 --- /dev/null +++ b/chrome/browser/data_use_measurement/chrome_data_use_measurement.h
@@ -0,0 +1,34 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DATA_USE_MEASUREMENT_CHROME_DATA_USE_MEASUREMENT_H_ +#define CHROME_BROWSER_DATA_USE_MEASUREMENT_CHROME_DATA_USE_MEASUREMENT_H_ + +#include <memory> + +#include "base/macros.h" +#include "components/data_use_measurement/core/data_use_measurement.h" +#include "components/data_use_measurement/core/url_request_classifier.h" + +namespace data_use_measurement { + +class DataUseAscriber; + +class ChromeDataUseMeasurement : public DataUseMeasurement { + public: + ChromeDataUseMeasurement( + std::unique_ptr<URLRequestClassifier> url_request_classifier, + DataUseAscriber* ascriber); + + void UpdateDataUseToMetricsService(int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeDataUseMeasurement); +}; + +} // namespace data_use_measurement + +#endif // CHROME_BROWSER_DATA_USE_MEASUREMENT_CHROME_DATA_USE_MEASUREMENT_H_
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index cefb6c3d..e38572c 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -173,29 +173,6 @@ return std::move(remapped_resolver); } -// This function is for forwarding metrics usage pref changes to the metrics -// service on the appropriate thread. -// TODO(gayane): Reduce the frequency of posting tasks from IO to UI thread. -void UpdateMetricsUsagePrefsOnUIThread(const std::string& service_name, - int message_size, - bool is_cellular) { - base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, - base::BindOnce( - [](const std::string& service_name, - int message_size, bool is_cellular) { - // Some unit tests use IOThread but do not - // initialize MetricsService. In that case it's - // fine to skip the update. - auto* metrics_service = - g_browser_process->metrics_service(); - if (metrics_service) { - metrics_service->UpdateMetricsUsagePrefs( - service_name, message_size, is_cellular); - } - }, - service_name, message_size, is_cellular)); -} - } // namespace class SystemURLRequestContextGetter : public net::URLRequestContextGetter { @@ -407,7 +384,7 @@ extension_event_router_forwarder()); builder->set_network_delegate( globals_->data_use_ascriber->CreateNetworkDelegate( - std::move(chrome_network_delegate), GetMetricsDataUseForwarder())); + std::move(chrome_network_delegate))); std::unique_ptr<net::CertVerifier> cert_verifier; if (g_cert_verifier_for_io_thread_testing) { @@ -454,7 +431,3 @@ stub_resolver_enabled_, std::move(dns_over_https_servers_)); } } - -metrics::UpdateUsagePrefCallbackType IOThread::GetMetricsDataUseForwarder() { - return base::Bind(&UpdateMetricsUsagePrefsOnUIThread); -}
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 8abc5632..95e97e8 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -25,7 +25,6 @@ #include "chrome/browser/net/chrome_network_delegate.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/common/buildflags.h" -#include "components/metrics/data_use_tracker.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread_delegate.h" #include "extensions/buildflags/buildflags.h" @@ -150,9 +149,6 @@ // thread. void DisableQuic(); - // Returns the callback for updating data use prefs. - metrics::UpdateUsagePrefCallbackType GetMetricsDataUseForwarder(); - // Configures |builder|'s ProxyResolutionService based on prefs and policies. void SetUpProxyService(network::URLRequestContextBuilderMojo* builder) const;
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc index 06eb1fe..1508ba71 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.cc +++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -12,10 +12,12 @@ #include "base/files/file_util.h" #include "base/memory/scoped_refptr.h" #include "base/path_service.h" +#include "base/sys_info.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "cc/base/switches.h" #include "chrome/browser/about_flags.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h" #include "chrome/browser/prefs/browser_prefs.h" @@ -41,7 +43,30 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/dbus/dbus_helper.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#endif +#include "chromeos/chromeos_paths.h" +#endif // defined(OS_CHROMEOS) + +namespace { + +#if defined(OS_CHROMEOS) +void RegisterStubPathOverridesIfNecessary() { + // These overrides need to occur before BrowserPolicyConnectorChromeOS + // (for one) is created. The DCHECK ensures that is the case. + DCHECK(!g_browser_process); + + base::FilePath user_data_dir; + if (base::SysInfo::IsRunningOnChromeOS() || + !base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { + return; + } + + // Override some paths with stub locations so that cloud policy and enterprise + // enrollment work on desktop builds, for ease of development. + chromeos::RegisterStubPathOverrides(user_data_dir); +} +#endif // defined(OS_CHROMEOS) + +} // namespace ChromeFeatureListCreator::ChromeFeatureListCreator() = default; @@ -88,6 +113,7 @@ RegisterLocalState(pref_registry.get()); #if defined(OS_CHROMEOS) + RegisterStubPathOverridesIfNecessary(); chromeos::PreEarlyInitDBus(); browser_policy_connector_ = std::make_unique<policy::BrowserPolicyConnectorChromeOS>();
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc index 8a4ef8f..074bbdf5 100644 --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc
@@ -37,6 +37,7 @@ #include "components/policy/core/common/policy_service.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "components/variations/variations_associated_data.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/net/system_network_context_manager.h b/chrome/browser/net/system_network_context_manager.h index e0b48d4..78224376 100644 --- a/chrome/browser/net/system_network_context_manager.h +++ b/chrome/browser/net/system_network_context_manager.h
@@ -19,6 +19,7 @@ #include "services/network/public/mojom/ssl_config.mojom.h" class PrefRegistrySimple; +class PrefService; class SSLConfigServiceManager; namespace network {
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc index ee048cf..e056598 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -1564,4 +1564,103 @@ "isPaused();", &is_paused)); EXPECT_FALSE(is_paused); } + +// Tests that the close and resize icons move properly as the window changes +// quadrants. +IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, + MovingQuadrantsMovesResizeControl) { + GURL test_page_url = ui_test_utils::GetTestUrl( + base::FilePath(base::FilePath::kCurrentDirectory), + base::FilePath( + FILE_PATH_LITERAL("media/picture-in-picture/window-size.html"))); + ui_test_utils::NavigateToURL(browser(), test_page_url); + + content::WebContents* active_web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(active_web_contents); + + SetUpWindowController(active_web_contents); + ASSERT_TRUE(window_controller()); + + content::OverlayWindow* overlay_window = + window_controller()->GetWindowForTesting(); + ASSERT_TRUE(overlay_window); + ASSERT_FALSE(overlay_window->IsVisible()); + + bool result = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + active_web_contents, "enterPictureInPicture();", &result)); + ASSERT_TRUE(result); + + OverlayWindowViews* overlay_window_views = + static_cast<OverlayWindowViews*>(overlay_window); + + // The PiP window starts in the bottom-right quadrant of the screen. + gfx::Rect bottom_right_bounds = overlay_window_views->GetBounds(); + // The relative center point of the window. + gfx::Point center(bottom_right_bounds.width() / 2, + bottom_right_bounds.height() / 2); + gfx::Point close_button_position = + overlay_window_views->close_image_position_for_testing(); + gfx::Point resize_button_position = + overlay_window_views->resize_handle_position_for_testing(); + + // The close button should be in the top right corner. + EXPECT_LT(center.x(), close_button_position.x()); + EXPECT_GT(center.y(), close_button_position.y()); + // The resize button should be in the top left corner. + EXPECT_GT(center.x(), resize_button_position.x()); + EXPECT_GT(center.y(), resize_button_position.y()); + + // Move the window to the bottom left corner. + gfx::Rect bottom_left_bounds(0, bottom_right_bounds.y(), + bottom_right_bounds.width(), + bottom_right_bounds.height()); + overlay_window_views->SetBounds(bottom_left_bounds); + close_button_position = + overlay_window_views->close_image_position_for_testing(); + resize_button_position = + overlay_window_views->resize_handle_position_for_testing(); + + // The close button should be in the top left corner. + EXPECT_GT(center.x(), close_button_position.x()); + EXPECT_GT(center.y(), close_button_position.y()); + // The resize button should be in the top right corner. + EXPECT_LT(center.x(), resize_button_position.x()); + EXPECT_GT(center.y(), resize_button_position.y()); + + // Move the window to the top right corner. + gfx::Rect top_right_bounds(bottom_right_bounds.x(), 0, + bottom_right_bounds.width(), + bottom_right_bounds.height()); + overlay_window_views->SetBounds(top_right_bounds); + close_button_position = + overlay_window_views->close_image_position_for_testing(); + resize_button_position = + overlay_window_views->resize_handle_position_for_testing(); + + // The close button should be in the top right corner. + EXPECT_LT(center.x(), close_button_position.x()); + EXPECT_GT(center.y(), close_button_position.y()); + // The resize button should be in the bottom left corner. + EXPECT_GT(center.x(), resize_button_position.x()); + EXPECT_LT(center.y(), resize_button_position.y()); + + // Move the window to the top left corner. + gfx::Rect top_left_bounds(0, 0, bottom_right_bounds.width(), + bottom_right_bounds.height()); + overlay_window_views->SetBounds(top_left_bounds); + close_button_position = + overlay_window_views->close_image_position_for_testing(); + resize_button_position = + overlay_window_views->resize_handle_position_for_testing(); + + // The close button should be in the top right corner. + EXPECT_LT(center.x(), close_button_position.x()); + EXPECT_GT(center.y(), close_button_position.y()); + // The resize button should be in the bottom right corner. + EXPECT_LT(center.x(), resize_button_position.x()); + EXPECT_LT(center.y(), resize_button_position.y()); +} + #endif // defined(OS_CHROMEOS)
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 60de178..77f4bb2 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -86,7 +86,6 @@ #include "components/flags_ui/pref_service_flags_storage.h" #include "components/gcm_driver/gcm_channel_status_syncer.h" #include "components/image_fetcher/core/storage/image_cache.h" -#include "components/invalidation/impl/invalidator_registrar_with_memory.h" #include "components/invalidation/impl/per_user_topic_registration_manager.h" #include "components/language/content/browser/geo_language_provider.h" #include "components/metrics/metrics_pref_names.h" @@ -594,7 +593,6 @@ sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(registry); syncer::SyncPrefs::RegisterProfilePrefs(registry); syncer::PerUserTopicRegistrationManager::RegisterProfilePrefs(registry); - syncer::InvalidatorRegistrarWithMemory::RegisterProfilePrefs(registry); TemplateURLPrepopulateData::RegisterProfilePrefs(registry); translate::TranslatePrefs::RegisterProfilePrefs(registry); UINetworkQualityEstimatorService::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index dede943a..9f765b5 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -428,8 +428,7 @@ return data_reduction_proxy_io_data()->CreateNetworkDelegate( io_thread->globals()->data_use_ascriber->CreateNetworkDelegate( - std::move(chrome_network_delegate), - io_thread->GetMetricsDataUseForwarder()), + std::move(chrome_network_delegate)), true); }
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_app.html b/chrome/browser/resources/chromeos/login/discover/discover_app.html index 552f3bb..0a32765 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_app.html +++ b/chrome/browser/resources/chromeos/login/discover/discover_app.html
@@ -16,6 +16,7 @@ <script src="chrome://resources/js/util.js"></script> <script src="chrome://oobe/strings.js"></script> <script src="chrome://resources/js/i18n_template.js"></script> + <link rel="import" href="chrome://resources/html/i18n_behavior.html"> </head> <body> <include src="../hd-iron-icon.html">
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_app.js b/chrome/browser/resources/chromeos/login/discover/discover_app.js index 2ebfc312..7e634d3 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_app.js +++ b/chrome/browser/resources/chromeos/login/discover/discover_app.js
@@ -56,3 +56,9 @@ document.addEventListener('DOMContentLoaded', function() { Oobe.initialize(); }); + +// In App mode Discover should not exit once last module is completed. +// It should go back to "Welcome" screen instead. +$('discoverUI').addEventListener('discover-done', function() { + $('discoverUI').onBeforeShow(); +});
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_components.html b/chrome/browser/resources/chromeos/login/discover/discover_components.html index c45c4da1..e596167 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_components.html +++ b/chrome/browser/resources/chromeos/login/discover/discover_components.html
@@ -3,6 +3,7 @@ <include src="modules/discover_module_redeem_offers.html"> <include src="modules/discover_module_launch_help_app.html"> <include src="modules/discover_module_sync_files.html"> +<include src="modules/discover_module_pin_setup.html"> <include src="discover_welcome.html"> <include src="discover_ui.html">
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_components.js b/chrome/browser/resources/chromeos/login/discover/discover_components.js index c3cc935c..031b8630 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_components.js +++ b/chrome/browser/resources/chromeos/login/discover/discover_components.js
@@ -10,6 +10,7 @@ // <include src="modules/discover_module_redeem_offers.js"> // <include src="modules/discover_module_launch_help_app.js"> // <include src="modules/discover_module_sync_files.js"> +// <include src="modules/discover_module_pin_setup.js"> // --- These depend on modules. // <include src="discover_welcome.js">
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_module_behavior.js b/chrome/browser/resources/chromeos/login/discover/discover_module_behavior.js index f527b09..cdac3fc 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_module_behavior.js +++ b/chrome/browser/resources/chromeos/login/discover/discover_module_behavior.js
@@ -18,16 +18,37 @@ /** * Discover module name. Must be set explicitly. */ - module: { - type: String, - readOnly: true, - value: '', - }, + module: String, }, - sendMessage: function(message, parameters) { + /** + * Sends one-way message to Discover API. + * @param {string} message Message to send. Must start with + * 'discover.moduleName.'. + * @param {Array<*>} parameters + */ + discoverCall: function(message, parameters) { assert(this.module.length > 0); - chrome.send('discover.' + this.module + '.' + message, parameters); + assert(message.startsWith('discover.' + this.module + '.')); + window.discoverSendImpl(message, null, parameters); + }, + + /** + * Sends Discover API message with callback to be invoked on reply. + * @param {string} message Message to send. Must start with + * 'discover.moduleName.'. + * @param {Array<*>} parameters Message parameters. + * @param {!function(*)} callback Callback to be invoked on reply. + */ + discoverCallWithReply: function(message, parameters, callback) { + assert(this.module.length > 0); + assert(message.startsWith('discover.' + this.module + '.')); + assert(callback instanceof Function); + window.discoverSendImpl(message, callback, parameters); + }, + + updateLocalizedContent: function() { + this.i18nUpdateLocale(); }, show: function() {},
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_ui.html b/chrome/browser/resources/chromeos/login/discover/discover_ui.html index 9c25ee0..53cc2cd 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_ui.html +++ b/chrome/browser/resources/chromeos/login/discover/discover_ui.html
@@ -29,6 +29,7 @@ <dom-module id="discover-ui"> <template> <link rel="stylesheet" href="discover_ui.css"> + <link rel="stylesheet" href="../oobe_fonts.css"> <discover-welcome id="discoverWelcome" on-module-continue="startLinearFlow_" on-module-skip="end_"> <discover-redeem-offers-card class="card" slot="cards" @@ -40,7 +41,12 @@ <discover-sync-files-card class="card" slot="cards" module="sync-files"> </discover-sync-files-card> + <discover-pin-setup-card class="card" slot="cards" + module="pinSetup" on-click="onCardClick_"> + </discover-pin-setup-card> </discover-welcome> - <!-- TODO (alemate): add modules --> + <discover-pin-setup-module class="module" + module="pinSetup" first-run="[[firstRun]]" hidden> + </discover-pin-setup-module> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_ui.js b/chrome/browser/resources/chromeos/login/discover/discover_ui.js index f08472c..d00393e 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_ui.js +++ b/chrome/browser/resources/chromeos/login/discover/discover_ui.js
@@ -5,6 +5,35 @@ /** * @fileoverview Polymer element for displaying Discover UI. */ +function initializeDiscoverAPI() { + let discoverCallbacks = {}; + + window.discoverSendImpl = (message, callback, parameters) => { + assert(message.startsWith('discover.')); + // Callback Id should be random to prevent triggering of incorrect + // callbacks if Id get screwed. + let callbackId; + if (callback) { + for (let i = 0; i < 10; ++i) { + callbackId = + String(Math.floor(Math.random() * 2147483647)); // 2^31 - 1 + if (callbackId && !(callbackId in discoverCallbacks)) + break; + } + assert(!(callbackId in discoverCallbacks)); + discoverCallbacks[callbackId] = callback; + } + chrome.send(message, [callbackId].concat(parameters)); + }; + + window.discoverReturn = (callbackId, value) => { + assert(callbackId in discoverCallbacks); + let callback = discoverCallbacks[callbackId]; + assert(delete (discoverCallbacks[callbackId])); + callback.call(null, value); + }; +} + { const DISCOVER_WELCOME_MODULE = 'discoverWelcome'; @@ -13,6 +42,17 @@ behaviors: [I18nBehavior, OobeDialogHostBehavior], + properties: { + /** + * When this flag is true, Discover UI is displayed as part of FirstRun + * UI. + */ + firstRun: { + type: Boolean, + value: false, + }, + }, + updateLocalizedContent: function() { this.i18nUpdateLocale(); this.propagateUpdateLocalizedContent('.card'); @@ -25,6 +65,7 @@ * @override */ attached: function() { + initializeDiscoverAPI(); // Initialize modules event handlers. let modules = Polymer.dom(this.root).querySelectorAll('.module'); for (let i = 0; i < modules.length; ++i) { @@ -54,7 +95,11 @@ this.propagateFullScreenMode('#discoverWelcome'); this.propagateFullScreenMode('.module'); - this.$.discoverWelcome.show(); + if (this.firstRun) { + this.showModule_('pinSetup'); + } else { + this.showModule_(DISCOVER_WELCOME_MODULE); + } }, /*
diff --git a/chrome/browser/resources/chromeos/login/discover/discover_welcome.css b/chrome/browser/resources/chromeos/login/discover/discover_welcome.css index e0cb7d7..de3508d 100644 --- a/chrome/browser/resources/chromeos/login/discover/discover_welcome.css +++ b/chrome/browser/resources/chromeos/login/discover/discover_welcome.css
@@ -5,7 +5,7 @@ :host { --card-box-height: 208px; --card-box-width: 312px; - --card-rows: 2; + --card-rows: 3; --card-spacing: 16px; /* Spacing between cards. */ --dialog-height: 640px; --highlight-card-box-width: 640px;
diff --git a/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.css b/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.css new file mode 100644 index 0000000..e4cc587 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.css
@@ -0,0 +1,28 @@ +/* Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#passwordInput { + margin-top: 32px; + width: 560px; +} + +setup-pin-keyboard { + --cr-input-input: { + font-size: 28px; + letter-spacing: 28px; + }; + --pin-keyboard-digit-button-letter: { + display: none; + }; + --pin-keyboard-pin-input-style: { + width: 244px; + }; + margin-top: 32px; +} + +#done-illustration { + height: 264px; + margin-top: 38px; /* 64px from subtitle baseline. */ + width: 264px; +}
diff --git a/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.html b/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.html new file mode 100644 index 0000000..7883666 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.html
@@ -0,0 +1,160 @@ +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> + +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> + +<link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"> + +<dom-module id="discover-pin-setup-card"> + <template> + <discover-card on-click="onClick_"> + <if expr="chromeos and _google_chrome"> + <div slot=background> + <div style="background: lightgreen; width: 100%; height: 100%;"></div> + </div> + </if> + <div slot="title"> + [[i18nDynamic(locale, 'discoverPinSetup')]] + </div> + </discover-card> + </template> +</dom-module> + +<iron-iconset-svg name="discover-pin-setup-32" size="32"> + <svg> + <defs> + <g id="lock"> + <defs> + <path id="a" d="M24 12h-1.333V9.333A6.67 6.67 0 0 0 16 2.667a6.67 6.67 0 0 0-6.667 6.666V12H8a2.675 2.675 0 0 0-2.667 2.667V28c0 1.467 1.2 2.667 2.667 2.667h16c1.467 0 2.667-1.2 2.667-2.667V14.667C26.667 13.2 25.467 12 24 12zM12 9.333c0-2.213 1.787-4 4-4s4 1.787 4 4V12h-8V9.333zM24 28H8V14.667h16V28zm-8-4c1.467 0 2.667-1.2 2.667-2.667 0-1.466-1.2-2.666-2.667-2.666a2.675 2.675 0 0 0-2.667 2.666C13.333 22.8 14.533 24 16 24z"> + </path> + </defs> + <g fill="none" fill-rule="evenodd"> + <use fill="#1A73E8" fill-rule="nonzero" xlink:href="#a"></use> + <path d="M0 0h32v32H0z"></path> + </g> + </g> + </defs> + </svg> +</iron-iconset-svg> + +<iron-iconset-svg name="discover-pin-setup-64" size="64"> + <svg> + <defs> + <g id="lock"> + <defs> + <path id="a" d="M48 24h-2.667v-5.333c0-7.36-5.973-13.334-13.333-13.334s-13.333 5.974-13.333 13.334V24H16c-2.933 0-5.333 2.4-5.333 5.333V56c0 2.933 2.4 5.333 5.333 5.333h32c2.933 0 5.333-2.4 5.333-5.333V29.333C53.333 26.4 50.933 24 48 24zm-24-5.333c0-4.427 3.573-8 8-8s8 3.573 8 8V24H24v-5.333zM48 56H16V29.333h32V56zm-16-8c2.933 0 5.333-2.4 5.333-5.333 0-2.934-2.4-5.334-5.333-5.334-2.933 0-5.333 2.4-5.333 5.334C26.667 45.6 29.067 48 32 48z"></path> + </defs> + <g fill="none" fill-rule="evenodd"> + <use fill="#1A73E8" fill-rule="nonzero" xlink:href="#a"></use> + <path d="M0 0h64v64H0z"></path> + </g> + </g> + </defs> + </svg> +</iron-iconset-svg> + +<dom-module id="discover-pin-setup-module"> + <template> + <link rel="stylesheet" href="../../oobe_dialog_host.css"> + <style include="iron-flex iron-flex-alignment iron-positioning + cr-shared-style"> + </style> + <style include="settings-shared"></style> + <link rel="stylesheet" href="discover_module_pin_setup.css"> + <oobe-dialog id="loading" role="dialog" no-header no-footer-padding + hidden="[[isStepHidden_(step_, 'loading')]]"> + <div slot="footer" class="flex layout vertical center center-justified"> + <throbber-notice text="Please wait"> + </throbber-notice> + </div> + </oobe-dialog> + <oobe-dialog role="dialog" has-buttons on-keypress="onKeypress_" + hidden="[[isStepHidden_(step_, 'password')]]"> + <hd-iron-icon slot="oobe-icon" icon1x="discover-pin-setup-32:lock" + icon2x="discover-pin-setup-64:lock"> + </hd-iron-icon> + <h1 slot="title"> + [[i18nDynamic(locale, 'discoverPinSetupPasswordTitle')]] + </h1> + <div slot="subtitle"> + [[i18nDynamic(locale, 'discoverPinSetupPasswordSubTitle')]] + </div> + <div slot="footer" class="flex layout horizontal"> + <cr-input id="passwordInput" type="password" + placeholder="[[i18nDynamic(locale, 'passwordPromptPasswordLabel')]]" + error-message="[[i18nDynamic(locale, + 'passwordPromptInvalidPassword')]]" + invalid="[[passwordInvalid_]]" + value="{{password_}}" + aria-disabled="false" + class="focus-on-show"> + </cr-input> + </div> + <div slot="bottom-buttons" class="flex layout horizontal end-justified"> + <oobe-text-button on-tap="onSkipButton_"> + <div>[[i18nDynamic(locale, 'discoverPinSetupSkip')]]</div> + </oobe-text-button> + <oobe-next-button inverse disabled="[[!password_]]" + on-tap="onPasswordSubmitButton_"> + <div>[[i18nDynamic(locale, 'next')]]</div> + </oobe-next-button> + </div> + </oobe-dialog> + <oobe-dialog id="setup" role="dialog" has-buttons + hidden="[[isPinSetupHidden_(step_)]]"> + <hd-iron-icon slot="oobe-icon" icon1x="discover-pin-setup-32:lock" + icon2x="discover-pin-setup-64:lock"> + </hd-iron-icon> + <h1 slot="title" hidden="[[isStepHidden_(step_, 'start')]]"> + [[i18nDynamic(locale, 'discoverPinSetupTitle1')]] + </h1> + <h1 slot="title" hidden="[[isStepHidden_(step_, 'confirm')]]"> + [[i18nDynamic(locale, 'discoverPinSetupTitle2')]] + </h1> + <h1 slot="title" hidden="[[isStepHidden_(step_, 'done')]]"> + [[i18nDynamic(locale, 'discoverPinSetupTitle3')]] + </h1> + <div slot="subtitle" hidden="[[isStepHidden_(step_, 'start')]]"> + [[i18nDynamic(locale, 'discoverPinSetupSubtitle1')]] + </div> + <div slot="subtitle" hidden="[[isStepHidden_(step_, 'done')]]"> + [[i18nDynamic(locale, 'discoverPinSetupSubtitle3')]]<BR> + </div> + <div slot="footer" class="flex layout horizontal center-justified"> + <setup-pin-keyboard id="pinKeyboard" + hidden="[[!isStepHidden_(step_, 'done')]]" + enable-submit="{{enableSubmit_}}" + is-confirm-step="{{isConfirmStep_}}" + on-pin-submit="onPinSubmit_" + on-set-pin-done="onSetPinDone_" + set-modes="{{setModes}}" + quick-unlock-private="[[quickUnlockPrivate_]]" + write-uma="[[writeUma_]]" + class="focus-on-show"> + </setup-pin-keyboard> + <img id="done-illustration" hidden="[[isStepHidden_(step_, 'done')]]" + srcset="images/pin_illustration_1x.svg 1x, + images/pin_illustration_2x.svg 2x"> + </div> + <div slot="bottom-buttons" class="flex layout horizontal end-justified"> + <oobe-text-button id="setupSkipButton" on-tap="onSkipButton_" + hidden="[[!isStepHidden_(step_, 'done')]]"> + <div>[[i18nDynamic(locale, 'discoverPinSetupSkip')]]</div> + </oobe-text-button> + <oobe-next-button inverse + disabled="[[isNextDisabled_(step_, enableSubmit_)]]" + on-tap="onNextButton_" class="focus-on-show" + hidden="[[!isStepHidden_(step_, 'done')]]"> + <div>[[i18nDynamic(locale, 'next')]]</div> + </oobe-next-button> + <oobe-text-button inverse on-tap="onDoneButton_" class="focus-on-show" + hidden="[[isStepHidden_(step_, 'done')]]"> + <div>[[i18nDynamic(locale, 'discoverPinSetupDone')]]</div> + </oobe-next-button> + </div> + </oobe-dialog> + </template> +</dom-module>
diff --git a/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.js b/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.js new file mode 100644 index 0000000..7a66fedb --- /dev/null +++ b/chrome/browser/resources/chromeos/login/discover/modules/discover_module_pin_setup.js
@@ -0,0 +1,377 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +Polymer({ + is: 'discover-pin-setup-card', + + behaviors: [DiscoverModuleBehavior], +}); + +{ + /** @const */ + let PIN_SETUP_STEPS = { + LOADING: 'loading', + PASSWORD: 'password', + START: 'start', + CONFIRM: 'confirm', + DONE: 'done', + }; + + // Time out for quickUnlock API. + let kApiTimeout = 10000; + + Polymer({ + is: 'discover-pin-setup-module', + + behaviors: [DiscoverModuleBehavior], + + properties: { + /** + * True when "Learn more" link should be hidden. + */ + learnMoreLinkHidden: { + type: Boolean, + value: false, + }, + + /** + * Flag from <setup-pin-keyboard>. + * @private + */ + enableSubmit_: { + type: Boolean, + value: false, + }, + + /** + * Flag from <setup-pin-keyboard>. + * @private + */ + isConfirmStep_: { + type: Boolean, + value: false, + observer: 'onIsConfirmStepChanged_', + }, + + /** QuickUnlockPrivate API token. */ + authToken_: { + type: String, + observer: 'onAuthTokenChanged_', + }, + + setModes: Object, + + /** @type{PIN_SETUP_STEPS} */ + step_: { + type: Number, + value: PIN_SETUP_STEPS.LOADING, + observer: 'onStepChanged_', + }, + + /** + * Interface for chrome.quickUnlockPrivate calls. May be overridden by + * tests. + * @type {QuickUnlockPrivate} + * @private + */ + quickUnlockPrivate_: {type: Object, value: chrome.quickUnlockPrivate}, + + /** + * writeUma is a function that handles writing uma stats. It may be + * overridden for tests. + * + * @type {Function} + * @private + */ + writeUma_: { + type: Object, + value: function() { + return settings.recordLockScreenProgress; + } + }, + + /** + * When this flag is true, Discover UI is displayed as part of FirstRun + * UI. + */ + firstRun: { + type: Boolean, + value: false, + }, + + /** + * Value of user password input field. + * @private + */ + password_: { + type: String, + value: '', + observer: 'onTypedPasswordChange_', + }, + + /** + * Helper property which marks password as valid/invalid. + * @private + */ + passwordInvalid_: { + type: Boolean, + value: false, + }, + }, + + /** + * True when in first run mode and primary user password has been requested. + * @private + */ + firstRunUserPasswordRequested_: false, + + /** + * Timeout ID for automatic skip timer. + * @private + */ + autoSkipTimer_: undefined, + + /** + * Starts automatic skip timer. + * @private + */ + startAutoSkipTimer_: function() { + if (this.autoSkipTimer_ !== undefined) + return; + + this.autoSkipTimer_ = setTimeout(() => { + console.error('autoSkipTimer triggered!'); + this.onSkipButton_(); + }, kApiTimeout); + }, + + /** + * Kills automatic skip timer. + * @private + */ + stopAutoSkipTimer_: function() { + if (this.autoSkipTimer_) + clearTimeout(this.autoSkipTimer_); + + this.autoSkipTimer_ = undefined; + }, + + /** + * step_ observer. Makes sure default focus follows step change, and kills + * autoskip timer if spinner is hidden. + * @private + */ + onStepChanged_: function() { + let dialogs = this.root.querySelectorAll('oobe-dialog'); + for (let dialog of dialogs) { + if (dialog.hidden) + continue; + + dialog.focus(); + break; + } + if (this.step_ == PIN_SETUP_STEPS.LOADING) + return; + + this.stopAutoSkipTimer_(); + }, + + /** @override */ + show: function() { + if (this.firstRun) { + this.getFirstRunUserPassword_(); + } else { + this.step_ = PIN_SETUP_STEPS.PASSWORD; + } + }, + + /** + * Starts fetching QuickUnlock token. + * @private + */ + getToken_: function(password) { + this.step_ = PIN_SETUP_STEPS.LOADING; + this.startAutoSkipTimer_(); + + this.quickUnlockPrivate_.getAuthToken(password, (tokenInfo) => { + if (chrome.runtime.lastError) { + console.error( + 'getAuthToken(): Failed: ' + chrome.runtime.lastError.message); + if (this.firstRun) { + // Trigger 'token expired' + this.authToken_ = ''; + } else { + this.step_ = PIN_SETUP_STEPS.PASSWORD; + this.passwordInvalid_ = true; + // Select the whole password if user entered an incorrect password. + this.$.passwordInput.select(); + } + return; + } + this.setToken(tokenInfo); + }); + }, + + /** + * Starts fetching primary user password. + * @private + */ + getFirstRunUserPassword_: function() { + this.startAutoSkipTimer_(); + this.discoverCallWithReply( + 'discover.pinSetup.getUserPassword', [], (password) => { + if (chrome.runtime.lastError) { + console.error( + 'getUserPassword() failed: ' + + chrome.runtime.lastError.message); + // Trigger 'token expired' + this.authToken_ = ''; + return; + } + this.getToken_(password); + }); + }, + + /** + * Receives new AuthToken. + * @private + */ + setToken: function(tokenInfo) { + this.authToken_ = tokenInfo.token; + // Subtract time from the expiration time to account for IPC delays. + // Treat values less than the minimum as 0 for testing. + const IPC_SECONDS = 2; + const lifetimeMs = tokenInfo.lifetimeSeconds > IPC_SECONDS ? + (tokenInfo.lifetimeSeconds - IPC_SECONDS) * 1000 : + 0; + this.clearAuthTokenTimeoutId_ = setTimeout(() => { + this.authToken_ = ''; + }, lifetimeMs); + + this.step_ = PIN_SETUP_STEPS.START; + }, + + /** + * Called when the authToken_ changes. If the authToken_ is NOT valid, + * skips module. + * @private + */ + onAuthTokenChanged_: function() { + this.password_ = ''; + if (!this.authToken_) { + this.setModes = null; + this.step_ = PIN_SETUP_STEPS.LOADING; + this.onSkipButton_(); + return; + } + this.setModes = (modes, credentials, onComplete) => { + this.quickUnlockPrivate_.setModes( + this.authToken_, modes, credentials, () => { + let result = true; + if (chrome.runtime.lastError) { + console.error( + 'setModes failed: ' + chrome.runtime.lastError.message); + result = false; + } + onComplete(result); + }); + }; + }, + + /** @private */ + onIsConfirmStepChanged_: function() { + if (this.isConfirmStep_) + this.step_ = PIN_SETUP_STEPS.CONFIRM; + }, + + /** @private */ + onPinSubmit_: function() { + this.$.pinKeyboard.doSubmit(); + }, + + /** @private */ + onSetPinDone_: function() { + this.step_ = PIN_SETUP_STEPS.DONE; + }, + + /** @private */ + onSkipButton_: function() { + this.password_ = ''; + this.authToken_ = ''; + + this.stopAutoSkipTimer_(); + this.$.pinKeyboard.resetState(); + this.fire('module-continue'); + }, + + /** @private */ + onNextButton_: function() { + this.onPinSubmit_(); + }, + + /** @private */ + onDoneButton_: function() { + this.password_ = ''; + this.authToken_ = ''; + this.$.pinKeyboard.resetState(); + this.fire('module-continue'); + }, + + /** + * Returns true if current UI step is different from expected. + * @param {PIN_SETUP_STEPS} current_step + * @param {PIN_SETUP_STEPS} expected_step + * @private + */ + isStepHidden_: function(current_step, expected_step) { + return current_step != expected_step; + }, + + /** + * Returns true if "Pin setup" dialog is hidden. + * @param {PIN_SETUP_STEPS} current_step + * @private + */ + isPinSetupHidden_: function(current_step) { + return !['start', 'confirm', 'done'].includes(current_step); + }, + + /** + * Returns true if "Next" button is disabled. + * @param {PIN_SETUP_STEPS} step this.step_ + * @param {Boolean} enableSubmit this.enableSubmit_ + * @private + */ + isNextDisabled_: function(step, enableSubmit) { + return step != PIN_SETUP_STEPS.DONE && !enableSubmit; + }, + + /** + * Triggers "Next" button if "Enter" key is pressed when entering password. + * @param {Event} e Keyboard event. + * @private + */ + onKeypress_: function(e) { + if (e.key != 'Enter') + return; + + this.onPasswordSubmitButton_(); + }, + + /** @private */ + onPasswordSubmitButton_: function() { + if (!this.password_) + return; + + let password = this.password_; + this.password_ = ''; + this.getToken_(password); + }, + + /** @private */ + onTypedPasswordChange_: function() { + this.passwordInvalid_ = false; + }, + }); +}
diff --git a/chrome/browser/resources/chromeos/login/discover/modules/images/pin_illustration_1x.svg b/chrome/browser/resources/chromeos/login/discover/modules/images/pin_illustration_1x.svg new file mode 100644 index 0000000..0d59105 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/discover/modules/images/pin_illustration_1x.svg
@@ -0,0 +1,21 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="264" height="264"> + <defs> + <path id="a" d="M0 0h228v228H0z"/> + </defs> + <g fill="none" fill-rule="evenodd"> + <g transform="translate(18 18)"> + <mask id="b" fill="#fff"> + <use xlink:href="#a"/> + </mask> + <path fill="#DADCE0" d="M114 0C51.04 0 0 51.04 0 114s51.04 114 114 114 114-51.04 114-114S176.96 0 114 0m0 4c29.382 0 57.005 11.442 77.781 32.218 20.777 20.777 32.22 48.4 32.22 77.782 0 29.382-11.443 57.005-32.22 77.782C171.005 212.558 143.382 224 114.001 224c-29.384 0-57.007-11.442-77.783-32.218C15.441 171.005 4 143.382 4 114c0-29.382 11.441-57.005 32.218-77.782C56.994 15.442 84.618 4 114 4" mask="url(#b)"/> + </g> + <path fill="#D2E3FC" d="M171.62 108H93.38C85.99 108 80 114.005 80 121.412v58.177C80 186.996 85.99 193 93.38 193h78.24c7.39 0 13.38-6.004 13.38-13.41v-58.178c0-7.407-5.99-13.412-13.38-13.412m0 8.031c2.96 0 5.367 2.414 5.367 5.38v58.178c0 2.967-2.408 5.38-5.367 5.38H93.38c-2.96 0-5.367-2.413-5.367-5.38v-58.177c0-2.967 2.408-5.38 5.367-5.38h78.24"/> + <path stroke="#4285F4" stroke-width="4" d="M88.826 193h87.348c4.875 0 8.826-3.961 8.826-8.847v-67.306c0-4.887-3.951-8.847-8.826-8.847H88.826c-4.874 0-8.826 3.96-8.826 8.847v67.306c0 4.886 3.952 8.847 8.826 8.847z"/> + <path stroke="#34A853" stroke-width="4" d="M123 55c-8.815 3.705-15 12.38-15 22.49V91"/> + <path stroke="#FBBC05" stroke-width="4" d="M153 64c-4.331-6.616-11.902-11-20.518-11-3.364 0-6.568.668-9.482 1.876"/> + <path stroke="#EA4335" stroke-width="4" d="M157 94V77.964c0-4.774-1.47-9.224-4-12.964"/> + <path stroke="#4285F4" stroke-width="4" d="M157 107V93"/> + <path stroke="#34A853" stroke-width="4" d="M120 151.996l9.002 9.004L149 141"/> + <path d="M0 0h264v264H0z"/> + </g> +</svg>
diff --git a/chrome/browser/resources/chromeos/login/discover/modules/images/pin_illustration_2x.svg b/chrome/browser/resources/chromeos/login/discover/modules/images/pin_illustration_2x.svg new file mode 100644 index 0000000..301a912 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/discover/modules/images/pin_illustration_2x.svg
@@ -0,0 +1,21 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="528" height="528"> + <defs> + <path id="a" d="M.001 0H456v456H.001z"/> + </defs> + <g fill="none" fill-rule="evenodd"> + <g transform="translate(36 36)"> + <mask id="b" fill="#fff"> + <use xlink:href="#a"/> + </mask> + <path fill="#DADCE0" d="M228 0C102.08 0 0 102.08 0 228S102.08 456 228 456c125.92 0 228-102.08 228-228S353.92 0 228 0m0 8c58.765 0 114.01 22.884 155.563 64.436C425.117 113.99 448 169.236 448 228c0 58.764-22.884 114.01-64.438 155.564C342.01 425.116 286.765 448 228 448c-58.766 0-114.012-22.884-155.564-64.436C30.883 342.01 8 286.764 8 228c0-58.764 22.882-114.01 64.436-155.564C113.989 30.884 169.235 8 228 8" mask="url(#b)"/> + </g> + <path fill="#D2E3FC" d="M343.24 216H186.76c-14.779 0-26.76 12.01-26.76 26.823v116.355C160 373.991 171.981 386 186.76 386h156.48c14.78 0 26.76-12.009 26.76-26.822V242.823C370 228.01 358.02 216 343.24 216m0 16.063c5.918 0 10.734 4.827 10.734 10.76v116.355c0 5.934-4.816 10.76-10.734 10.76H186.76c-5.918 0-10.734-4.826-10.734-10.76V242.823c0-5.933 4.816-10.76 10.734-10.76h156.48"/> + <path stroke="#4285F4" stroke-width="8" d="M177.653 386h174.696c9.749 0 17.651-7.922 17.651-17.693V233.693c0-9.772-7.902-17.693-17.651-17.693H177.653c-9.749 0-17.653 7.92-17.653 17.693v134.614c0 9.77 7.904 17.693 17.653 17.693z"/> + <path stroke="#34A853" stroke-width="8" d="M246 110c-17.63 7.41-30 24.759-30 44.98V182"/> + <path stroke="#FBBC05" stroke-width="8" d="M306 128c-8.663-13.232-23.804-22-41.036-22A49.417 49.417 0 0 0 246 109.752"/> + <path stroke="#EA4335" stroke-width="8" d="M314 188v-32.072c0-9.548-2.938-18.447-8-25.928"/> + <path stroke="#4285F4" stroke-width="8" d="M314 214v-28"/> + <path stroke="#34A853" stroke-width="8" d="M240 303.993L258.005 322 298 282"/> + <path d="M0 0h528v528H0z"/> + </g> +</svg>
diff --git a/chrome/browser/resources/chromeos/login/images/1x/reset_illustration_1x.svg b/chrome/browser/resources/chromeos/login/images/1x/reset_illustration_1x.svg new file mode 100644 index 0000000..51d4fab --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/1x/reset_illustration_1x.svg
@@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="264" height="264"> + <g fill="none" fill-rule="evenodd"> + <path fill="#EA4335" d="M96.554 122.415l6.413-6.413a2.269 2.269 0 0 1 3.207 0l6.412 6.413a2.267 2.267 0 0 1 0 3.207l-6.412 6.414a2.269 2.269 0 0 1-3.207 0l-6.413-6.413a2.269 2.269 0 0 1 0-3.208"/> + <path fill="#FBBC04" d="M133.766 101.358a5.667 5.667 0 0 1 0-8.016l4.81-4.81a5.67 5.67 0 0 1 8.016 8.016l-4.81 4.81a5.67 5.67 0 0 1-8.016 0"/> + <path fill="#34A853" d="M151.384 117.925l11.947 3.2c1.686.453 2.25 2.56 1.016 3.795l-8.745 8.745c-1.235 1.234-3.342.67-3.794-1.016l-3.2-11.947c-.453-1.686 1.09-3.23 2.776-2.777"/> + <path stroke="#4285F4" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M212 174c0 44.183-35.817 80-80 80s-80-35.817-80-80 35.817-80 80-80 80 35.817 80 80z"/> + <path fill="#4285F4" stroke="#4285F4" stroke-width="2" d="M135.125 164.625v6.25H157V149h-6.25v8.563C146.156 152.343 139.5 149 132 149c-6.906 0-13.156 2.813-17.688 7.313-4.53 4.5-7.312 10.78-7.312 17.687 0 13.813 11.188 25 25 25 6.906 0 13.156-2.813 17.688-7.313l-4.438-4.437c-3.406 3.406-8.094 5.5-13.25 5.5-10.344 0-18.75-8.406-18.75-18.75 0-5.156 2.094-9.844 5.5-13.25 3.406-3.406 8.094-5.5 13.25-5.5 6.906 0 12.969 3.781 16.219 9.375h-13.094z"/> + <path fill="#EA4335" d="M171.605 81.336l-6.413-6.413a2.268 2.268 0 0 1 0-3.206l6.413-6.413a2.269 2.269 0 0 1 3.207 0l6.412 6.413a2.266 2.266 0 0 1 0 3.206l-6.412 6.413a2.269 2.269 0 0 1-3.207 0"/> + <path fill="#FBBC04" d="M105.869 47.101l-6.413-6.413a2.268 2.268 0 0 1 0-3.206l6.413-6.413a2.269 2.269 0 0 1 3.207 0l6.413 6.413a2.268 2.268 0 0 1 0 3.206l-6.413 6.413a2.267 2.267 0 0 1-3.207 0"/> + <path fill="#4285F4" d="M129.012 64.68a5.667 5.667 0 0 1 0-8.017l4.81-4.81a5.67 5.67 0 0 1 8.016 8.016l-4.81 4.81a5.667 5.667 0 0 1-8.016 0"/> + <path fill="#34A853" d="M87.07 74.282l11.947 3.201c1.686.452 2.25 2.56 1.016 3.794l-8.745 8.745c-1.235 1.234-3.342.67-3.794-1.016L84.293 77.06c-.452-1.686 1.09-3.229 2.777-2.777M159 16a7 7 0 1 1-14 0 7 7 0 0 1 14 0"/> + <path d="M0 0h264v264H0z"/> + </g> +</svg>
diff --git a/chrome/browser/resources/chromeos/login/images/2x/reset_illustration_2x.svg b/chrome/browser/resources/chromeos/login/images/2x/reset_illustration_2x.svg new file mode 100644 index 0000000..326c80e5 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/2x/reset_illustration_2x.svg
@@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="528" height="528"> + <g fill="none" fill-rule="evenodd"> + <path fill="#EA4335" d="M193.108 244.831l12.826-12.826a4.538 4.538 0 0 1 6.414 0l12.824 12.826a4.534 4.534 0 0 1 0 6.414l-12.824 12.826a4.538 4.538 0 0 1-6.414 0l-12.826-12.826a4.538 4.538 0 0 1 0-6.414"/> + <path fill="#FBBC04" d="M267.532 202.716c-4.428-4.428-4.428-11.606 0-16.032l9.62-9.62c4.426-4.428 11.604-4.428 16.032 0 4.426 4.428 4.426 11.606 0 16.032l-9.62 9.62c-4.428 4.426-11.606 4.426-16.032 0"/> + <path fill="#34A853" d="M302.769 235.85l23.894 6.401c3.372.904 4.5 5.118 2.032 7.588l-17.49 17.49c-2.47 2.468-6.684 1.34-7.588-2.032l-6.402-23.894c-.904-3.372 2.182-6.458 5.554-5.554"/> + <path stroke="#4285F4" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" d="M424 348c0 88.366-71.634 160-160 160s-160-71.634-160-160 71.634-160 160-160 160 71.634 160 160z"/> + <path fill="#4285F4" stroke="#4285F4" stroke-width="4" d="M270.25 329.25v12.5H314V298h-12.5v17.125C292.312 304.687 279 298 264 298c-13.813 0-26.313 5.625-35.375 14.625-9.063 9-14.625 21.563-14.625 35.375 0 27.625 22.375 50 50 50 13.813 0 26.313-5.625 35.375-14.625L290.5 374.5c-6.813 6.813-16.188 11-26.5 11-20.688 0-37.5-16.813-37.5-37.5 0-10.313 4.188-19.688 11-26.5 6.813-6.813 16.188-11 26.5-11 13.813 0 25.938 7.563 32.438 18.75H270.25z"/> + <path fill="#EA4335" d="M343.21 162.672l-12.826-12.826a4.535 4.535 0 0 1 0-6.412l12.826-12.826a4.538 4.538 0 0 1 6.414 0l12.824 12.826a4.531 4.531 0 0 1 0 6.412l-12.824 12.826a4.538 4.538 0 0 1-6.414 0"/> + <path fill="#FBBC04" d="M211.737 94.202l-12.826-12.826a4.535 4.535 0 0 1 0-6.412l12.826-12.826a4.538 4.538 0 0 1 6.414 0l12.826 12.826a4.535 4.535 0 0 1 0 6.412l-12.826 12.826a4.534 4.534 0 0 1-6.414 0"/> + <path fill="#4285F4" d="M258.024 129.358c-4.428-4.426-4.428-11.604 0-16.032l9.62-9.62c4.426-4.426 11.604-4.426 16.032 0 4.426 4.428 4.426 11.606 0 16.032l-9.62 9.62c-4.428 4.428-11.606 4.428-16.032 0"/> + <path fill="#34A853" d="M174.14 148.564l23.894 6.402c3.372.904 4.5 5.118 2.032 7.588l-17.49 17.49c-2.47 2.468-6.684 1.34-7.588-2.032l-6.402-23.894c-.904-3.372 2.182-6.458 5.554-5.554M318 32c0 7.732-6.268 14-14 14s-14-6.268-14-14 6.268-14 14-14 14 6.268 14 14"/> + <path d="M0 0h528v528H0z"/> + </g> +</svg>
diff --git a/chrome/browser/resources/chromeos/login/images/reset_illustration_1x.png b/chrome/browser/resources/chromeos/login/images/reset_illustration_1x.png deleted file mode 100644 index 6966c1e..0000000 --- a/chrome/browser/resources/chromeos/login/images/reset_illustration_1x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/reset_illustration_2x.png b/chrome/browser/resources/chromeos/login/images/reset_illustration_2x.png deleted file mode 100644 index 3b2c39b..0000000 --- a/chrome/browser/resources/chromeos/login/images/reset_illustration_2x.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html index 8f8eeb8..edde59f 100644 --- a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html +++ b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html
@@ -7,6 +7,7 @@ <link rel="import" href="chrome://oobe/custom_elements.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <!-- UI for the MultiDevice setup flow when displayed after OOBE or during the @@ -24,7 +25,63 @@ --> <dom-module id="multidevice-setup-first-run"> <template> - <style include="shared-style multidevice-setup-shared"></style> + <link rel="stylesheet" href="oobe_popup_overlay.css"> + <style include="shared-style multidevice-setup-shared "> + #multidevice-help-overlay-container { + width: 768px; + } + + #multidevice-help-overlay-webview { + border: 1px solid #d9d9d9; + display: block; + height: 450px; + width: 100%; + } + + #multidevice-help-overlay-webview-container.overlay-loading > webview, + #multidevice-help-overlay-webview-container:not(.overlay-loading) > div { + display: none; + } + + #multidevice-help-overlay-webview-container { + box-sizing: border-box; + height: 482px; + margin: auto; + padding: 24px 8px 8px 8px; + width: 100%; + } + + .multidevice-help-overlay-close-top { + background-image: url(chrome://theme/IDR_CLOSE_DIALOG); + background-position: center; + background-repeat: no-repeat; + height: 14px; + position: absolute; + right: 7px; + top: 7px; + width: 14px; + z-index: 1; + } + + html[dir='rtl'] .multidevice-help-overlay-close-top { + left: 10px; + right: auto; + } + + .multidevice-help-overlay-close-top:hover { + background-image: url(chrome://theme/IDR_CLOSE_DIALOG_H); + } + + .multidevice-help-overlay-close-top:active { + background-image: url(chrome://theme/IDR_CLOSE_DIALOG_P); + } + + .multidevice-help-button-strip { + display: flex; + justify-content: flex-end; + margin: 8px; + } + </style> <multidevice-setup delegate="[[delegate_]]" on-setup-exited="onExitRequested_" forward-button-text="{{forwardButtonText_}}" @@ -38,5 +95,31 @@ <div>[[forwardButtonText_]]</div> </oobe-next-button> </multidevice-setup> + + <div id="multidevice-help-overlay" class="popup-overlay" + hidden$="[[webviewOverlayHidden_]]"> + <div id="multidevice-help-overlay-container" + class="oobe-popup not-resizable"> + <div id="multidevice-help-overlay-close-top" + class="multidevice-help-overlay-close-top + multidevice-help-overlay-close-button" + on-click="hideWebviewOverlay_" + title="[[getOverlayCloseTopTitle_()]]"> + </div> + <div id="multidevice-help-overlay-webview-container"> + <webview id="multidevice-help-overlay-webview" + src="[[webviewSrc_]]"></webview> + </div> + <div class="multidevice-help-button-strip"> + <oobe-text-button inverse id="multidevice-help-overlay-close-bottom" + class="multidevice-help-overlay-close-button" + on-click="hideWebviewOverlay_"> + <!-- TODO(crbug.com/894537): Use string that is specific to + MultiDevice. --> + <div i18n-content="arcOverlayClose"></div> + </oobe-text-button> + </div> + </div> + </div> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js index 27ba0fd..ddce54e 100644 --- a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js +++ b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
@@ -50,7 +50,7 @@ const MultiDeviceSetupFirstRun = Polymer({ is: 'multidevice-setup-first-run', - behaviors: [WebUIListenerBehavior], + behaviors: [I18nBehavior, WebUIListenerBehavior], properties: { /** @private {!multidevice_setup.MultiDeviceSetupDelegate} */ @@ -82,6 +82,25 @@ type: String, value: '', }, + + /** Whether the webview overlay should be hidden. */ + webviewOverlayHidden_: { + type: Boolean, + value: true, + }, + + /** + * URL for the webview to display. + * @private {string|undefined} + */ + webviewSrc_: { + type: String, + value: '', + }, + }, + + listeners: { + 'open-learn-more-webview-requested': 'onOpenLearnMoreWebviewRequested_', }, /** @override */ @@ -99,7 +118,38 @@ /** @private */ onExitRequested_: function() { chrome.send('login.MultiDeviceSetupScreen.userActed', ['setup-finished']); - } + }, + + /** + * @param {boolean} shouldShow + * @param {string=} opt_url + * @private + */ + setWebviewOverlayVisibility_: function(shouldShow, opt_url) { + if (opt_url) { + this.webviewSrc_ = opt_url; + } + this.webviewOverlayHidden_ = !shouldShow; + }, + + /** @private */ + hideWebviewOverlay_: function() { + this.setWebviewOverlayVisibility_(false /* shouldShow */); + }, + + /** + * @param {!{detail: string}} event + * @private + */ + onOpenLearnMoreWebviewRequested_: function(event) { + this.setWebviewOverlayVisibility_( + true /* shouldShow */, event.detail /* url */); + }, + + /** @private */ + getOverlayCloseTopTitle_: function() { + return this.i18n('arcOverlayClose'); + }, }); return {
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.css b/chrome/browser/resources/chromeos/login/oobe_reset.css index fe2f471..99415e93 100644 --- a/chrome/browser/resources/chromeos/login/oobe_reset.css +++ b/chrome/browser/resources/chromeos/login/oobe_reset.css
@@ -39,3 +39,8 @@ cursor: pointer; pointer-events: auto; } + +#illustration { + height: 264px; + width: 264px; +}
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.html b/chrome/browser/resources/chromeos/login/oobe_reset.html index bd9e9dd..188c109 100644 --- a/chrome/browser/resources/chromeos/login/oobe_reset.html +++ b/chrome/browser/resources/chromeos/login/oobe_reset.html
@@ -10,7 +10,13 @@ <svg> <defs> <g id="alert" fill-rule="evenodd"> - <path d="M16,2.66666667 C8.64,2.66666667 2.66666667,8.64 2.66666667,16 C2.66666667,23.36 8.64,29.3333333 16,29.3333333 C23.36,29.3333333 29.3333333,23.36 29.3333333,16 C29.3333333,8.64 23.36,2.66666667 16,2.66666667 L16,2.66666667 Z M17.3333333,22.6666667 L14.6666667,22.6666667 L14.6666667,20 L17.3333333,20 L17.3333333,22.6666667 L17.3333333,22.6666667 Z M17.3333333,17.3333333 L14.6666667,17.3333333 L14.6666667,9.33333333 L17.3333333,9.33333333 L17.3333333,17.3333333 L17.3333333,17.3333333 Z"></path> + <defs> + <path id="a" d="M14.667 20h2.666v2.667h-2.666V20zm0-10.667h2.666v8h-2.666v-8zm1.32-6.666C8.627 2.667 2.667 8.64 2.667 16s5.96 13.333 13.32 13.333c7.373 0 13.346-5.973 13.346-13.333S23.36 2.667 15.987 2.667zm.013 24c-5.893 0-10.667-4.774-10.667-10.667S10.107 5.333 16 5.333 26.667 10.107 26.667 16 21.893 26.667 16 26.667z"></path> + </defs> + <g fill="none" fill-rule="evenodd"> + <path d="M0 0h32v32H0z"></path> + <use fill="#1A73E8" fill-rule="nonzero" xlink:href="#a"></use> + </g> </g> </defs> </svg> @@ -20,7 +26,13 @@ <svg> <defs> <g id="alert" fill-rule="evenodd"> - <path d="M32,5.33333333 C17.28,5.33333333 5.33333333,17.28 5.33333333,32 C5.33333333,46.72 17.28,58.6666667 32,58.6666667 C46.72,58.6666667 58.6666667,46.72 58.6666667,32 C58.6666667,17.28 46.72,5.33333333 32,5.33333333 L32,5.33333333 Z M34.6666667,45.3333333 L29.3333333,45.3333333 L29.3333333,40 L34.6666667,40 L34.6666667,45.3333333 L34.6666667,45.3333333 Z M34.6666667,34.6666667 L29.3333333,34.6666667 L29.3333333,18.6666667 L34.6666667,18.6666667 L34.6666667,34.6666667 L34.6666667,34.6666667 Z"></path> + <defs> + <path id="a" d="M29.333 40h5.334v5.333h-5.334V40zm0-21.333h5.334v16h-5.334v-16zm2.64-13.334C17.253 5.333 5.333 17.28 5.333 32c0 14.72 11.92 26.667 26.64 26.667C46.72 58.667 58.667 46.72 58.667 32c0-14.72-11.947-26.667-26.694-26.667zm.027 48c-11.787 0-21.333-9.546-21.333-21.333 0-11.787 9.546-21.333 21.333-21.333 11.787 0 21.333 9.546 21.333 21.333 0 11.787-9.546 21.333-21.333 21.333z"></path> + </defs> + <g fill="none" fill-rule="evenodd"> + <path d="M0 0h64v64H0z"></path> + <use fill="#1A73E8" fill-rule="nonzero" xlink:href="#a"></use> + </g> </g> </defs> </svg> @@ -60,8 +72,8 @@ </div> </div> <div slot="footer" class="flex layout vertical center"> - <img srcset="images/reset_illustration_1x.png 1x, - images/reset_illustration_2x.png 2x" + <img id="illustration" srcset="images/1x/reset_illustration_1x.svg 1x, + images/2x/reset_illustration_2x.svg 2x" i18n-values="alt:resetScreenIllustrationTitle"> <div id="tpmFirmwareUpdate" class="layout horizontal" hidden="[[!tpmFirmwareUpdateAvailable_]]">
diff --git a/chrome/browser/resources/chromeos/login/screen_discover.html b/chrome/browser/resources/chromeos/login/screen_discover.html index 8239f8d..a436903 100644 --- a/chrome/browser/resources/chromeos/login/screen_discover.html +++ b/chrome/browser/resources/chromeos/login/screen_discover.html
@@ -1,3 +1,3 @@ <div class="step right hidden" id="discover" hidden> - <discover-ui id="discover-impl"></discover> + <discover-ui id="discover-impl" first-run></discover> </div>
diff --git a/chrome/browser/resources/chromeos/login/screen_multidevice_setup.html b/chrome/browser/resources/chromeos/login/screen_multidevice_setup.html index 7293931..31a4b95 100644 --- a/chrome/browser/resources/chromeos/login/screen_multidevice_setup.html +++ b/chrome/browser/resources/chromeos/login/screen_multidevice_setup.html
@@ -2,6 +2,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> <link rel="import" href="chrome://oobe/custom_elements.html"> +<link rel="stylesheet" href="chrome://resources/css/overlay.css"> <div class="step right hidden" id="multidevice-setup" hidden> <multidevice-setup-first-run id="multidevice-setup-impl">
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index d1e99ea..07ea937 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -455,25 +455,16 @@ aria-label="$i18n{encryptWithGoogleCredentialsLabel}"> $i18n{encryptWithGoogleCredentialsLabel} </cr-radio-button> - <template is="dom-if" if="[[syncPrefs.fullEncryptionBody]]"> - <cr-radio-button name="encrypt-with-passphrase" - class="list-item" disabled="[[syncPrefs.encryptAllData]]" - aria-labelledby="fullEncryptionBody"> - <span id="fullEncryptionBody"> - [[syncPrefs.fullEncryptionBody]] - </span> - </cr-radio-button> - </template> - <template is="dom-if" if="[[!syncPrefs.fullEncryptionBody]]"> - <cr-radio-button name="encrypt-with-passphrase" - class="list-item" disabled="[[syncPrefs.encryptAllData]]" - aria-labelledby="encryptWithSyncPassphraseLabel"> - <span id="encryptWithSyncPassphraseLabel" - on-click="onLearnMoreTap_"> - $i18nRaw{encryptWithSyncPassphraseLabel} - </span> - </cr-radio-button> - </template> + <cr-radio-button name="encrypt-with-passphrase" + class="list-item" disabled="[[syncPrefs.encryptAllData]]"> + <span hidden="[[!syncPrefs.fullEncryptionBody]]"> + [[syncPrefs.fullEncryptionBody]] + </span> + <span on-click="onLearnMoreTap_" + hidden="[[syncPrefs.fullEncryptionBody]]"> + $i18nRaw{encryptWithSyncPassphraseLabel} + </span> + </cr-radio-button> </paper-radio-group> </div>
diff --git a/chrome/browser/signin/signin_global_error.cc b/chrome/browser/signin/signin_global_error.cc index e1b7b53..8e03c89 100644 --- a/chrome/browser/signin/signin_global_error.cc +++ b/chrome/browser/signin/signin_global_error.cc
@@ -9,7 +9,7 @@ #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_pages.h" @@ -23,9 +23,9 @@ #include "chrome/grit/generated_resources.h" #include "components/signin/core/browser/profile_management_switches.h" #include "components/signin/core/browser/signin_header_helper.h" -#include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_metrics.h" #include "net/base/url_util.h" +#include "services/identity/public/cpp/identity_manager.h" #include "ui/base/l10n/l10n_util.h" #if !defined(OS_ANDROID) @@ -116,10 +116,10 @@ std::vector<base::string16> messages; // If the user isn't signed in, no need to display an error bubble. - SigninManagerBase* signin_manager = - SigninManagerFactory::GetForProfileIfExists(profile_); - if (signin_manager && !signin_manager->IsAuthenticated()) - return messages; + auto* identity_manager = + IdentityManagerFactory::GetForProfileIfExists(profile_); + if (identity_manager && !identity_manager->HasPrimaryAccount()) + return messages; if (!error_controller_->HasError()) return messages;
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc index 23547e2..b633d2c 100644 --- a/chrome/browser/sync/test/integration/bookmarks_helper.cc +++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -45,6 +45,7 @@ #include "components/history/core/browser/history_db_task.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" +#include "components/sync/test/fake_server/entity_builder_factory.h" #include "components/sync_bookmarks/bookmark_change_processor.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -957,6 +958,15 @@ return base::StringPrintf("Subsubfolder Name %d", i); } +std::unique_ptr<syncer::LoopbackServerEntity> CreateBookmarkServerEntity( + const std::string& title, + const GURL& url) { + fake_server::EntityBuilderFactory entity_builder_factory; + fake_server::BookmarkEntityBuilder bookmark_builder = + entity_builder_factory.NewBookmarkEntityBuilder(title); + return bookmark_builder.BuildBookmark(url); +} + } // namespace bookmarks_helper BookmarksMatchChecker::BookmarksMatchChecker() @@ -1004,6 +1014,64 @@ return "Waiting for bookmark count to match"; } +ServerBookmarksEqualityChecker::ServerBookmarksEqualityChecker( + browser_sync::ProfileSyncService* service, + fake_server::FakeServer* fake_server, + const std::vector<ExpectedBookmark>& expected_bookmarks, + syncer::Cryptographer* cryptographer) + : SingleClientStatusChangeChecker(service), + fake_server_(fake_server), + cryptographer_(cryptographer), + expected_bookmarks_(expected_bookmarks) {} + +bool ServerBookmarksEqualityChecker::IsExitConditionSatisfied() { + std::vector<sync_pb::SyncEntity> entities = + fake_server_->GetSyncEntitiesByModelType(syncer::BOOKMARKS); + if (expected_bookmarks_.size() != entities.size()) { + return false; + } + + // Make a copy so we can remove bookmarks that were found. + std::vector<ExpectedBookmark> expected = expected_bookmarks_; + for (const sync_pb::SyncEntity& entity : entities) { + // If the cryptographer was provided, we expect the specifics to have + // encrypted data. + EXPECT_EQ(entity.specifics().has_encrypted(), cryptographer_ != nullptr); + + sync_pb::BookmarkSpecifics actual_specifics; + if (entity.specifics().has_encrypted()) { + sync_pb::EntitySpecifics entity_specifics; + EXPECT_TRUE(cryptographer_->Decrypt(entity.specifics().encrypted(), + &entity_specifics)); + actual_specifics = entity_specifics.bookmark(); + } else { + actual_specifics = entity.specifics().bookmark(); + } + + auto it = + std::find_if(expected.begin(), expected.end(), + [actual_specifics](const ExpectedBookmark& bookmark) { + return actual_specifics.title() == bookmark.title && + actual_specifics.url() == bookmark.url; + }); + if (it != expected.end()) { + expected.erase(it); + } else { + ADD_FAILURE() << "Could not find expected bookmark with title '" + << actual_specifics.title() << "' and URL '" + << actual_specifics.url() << "'"; + } + } + + return true; +} + +std::string ServerBookmarksEqualityChecker::GetDebugMessage() const { + return "Waiting for server-side bookmarks to match expected."; +} + +ServerBookmarksEqualityChecker::~ServerBookmarksEqualityChecker() {} + namespace { bool BookmarkCountsByUrlMatch(int profile,
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.h b/chrome/browser/sync/test/integration/bookmarks_helper.h index a149ed80..ab030fee 100644 --- a/chrome/browser/sync/test/integration/bookmarks_helper.h +++ b/chrome/browser/sync/test/integration/bookmarks_helper.h
@@ -5,13 +5,19 @@ #ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_BOOKMARKS_HELPER_H_ #define CHROME_BROWSER_SYNC_TEST_INTEGRATION_BOOKMARKS_HELPER_H_ +#include <memory> #include <string> +#include <vector> #include "base/compiler_specific.h" #include "chrome/browser/sync/test/integration/await_match_status_change_checker.h" #include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" +#include "components/sync/base/cryptographer.h" +#include "components/sync/engine_impl/loopback_server/loopback_server_entity.h" +#include "components/sync/test/fake_server/fake_server.h" #include "third_party/skia/include/core/SkColor.h" +#include "url/gurl.h" class GURL; @@ -223,6 +229,12 @@ // Returns a subsubfolder name identifiable by |i|. std::string IndexedSubsubfolderName(int i); +// Creates a server-side entity representing a bookmark with the given title and +// URL. +std::unique_ptr<syncer::LoopbackServerEntity> CreateBookmarkServerEntity( + const std::string& title, + const GURL& url); + } // namespace bookmarks_helper // Checker used to block until bookmarks match on all clients. @@ -265,6 +277,37 @@ const int expected_count_; }; +// Checker used to block until the bookmarks on the server match a given set of +// expected bookmarks. +class ServerBookmarksEqualityChecker : public SingleClientStatusChangeChecker { + public: + struct ExpectedBookmark { + std::string title; + GURL url; + }; + + // If a |cryptographer| is provided (i.e. is not nullptr), it is assumed that + // the server-side data should be encrypted, and the provided cryptographer + // will be used to decrypt the data prior to checking for equality. + ServerBookmarksEqualityChecker( + browser_sync::ProfileSyncService* service, + fake_server::FakeServer* fake_server, + const std::vector<ExpectedBookmark>& expected_bookmarks, + syncer::Cryptographer* cryptographer); + + bool IsExitConditionSatisfied() override; + std::string GetDebugMessage() const override; + + ~ServerBookmarksEqualityChecker() override; + + private: + fake_server::FakeServer* fake_server_; + syncer::Cryptographer* cryptographer_; + const std::vector<ExpectedBookmark> expected_bookmarks_; + + DISALLOW_COPY_AND_ASSIGN(ServerBookmarksEqualityChecker); +}; + // Checker used to block until the actual number of bookmarks with the given url // match the expected count. class BookmarksUrlChecker : public AwaitMatchStatusChangeChecker {
diff --git a/chrome/browser/sync/test/integration/encryption_helper.cc b/chrome/browser/sync/test/integration/encryption_helper.cc new file mode 100644 index 0000000..66a1096 --- /dev/null +++ b/chrome/browser/sync/test/integration/encryption_helper.cc
@@ -0,0 +1,176 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> +#include <vector> + +#include "base/base64.h" +#include "chrome/browser/sync/test/integration/encryption_helper.h" +#include "components/browser_sync/profile_sync_service.h" +#include "components/sync/base/passphrase_enums.h" +#include "components/sync/base/system_encryptor.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace encryption_helper { + +bool GetServerNigori(fake_server::FakeServer* fake_server, + sync_pb::NigoriSpecifics* nigori) { + std::vector<sync_pb::SyncEntity> entity_list = + fake_server->GetPermanentSyncEntitiesByModelType(syncer::NIGORI); + if (entity_list.size() != 1U) { + return false; + } + + *nigori = entity_list[0].specifics().nigori(); + return true; +} + +void InitCustomPassphraseCryptographerFromNigori( + const sync_pb::NigoriSpecifics& nigori, + syncer::Cryptographer* cryptographer, + const std::string& passphrase) { + sync_pb::EncryptedData keybag = nigori.encryption_keybag(); + cryptographer->SetPendingKeys(keybag); + + std::string decoded_salt; + switch (syncer::ProtoKeyDerivationMethodToEnum( + nigori.custom_passphrase_key_derivation_method())) { + case syncer::KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003: + ASSERT_TRUE(cryptographer->DecryptPendingKeys( + {syncer::KeyDerivationParams::CreateForPbkdf2(), passphrase})); + break; + case syncer::KeyDerivationMethod::SCRYPT_8192_8_11: + ASSERT_TRUE(base::Base64Decode( + nigori.custom_passphrase_key_derivation_salt(), &decoded_salt)); + ASSERT_TRUE(cryptographer->DecryptPendingKeys( + {syncer::KeyDerivationParams::CreateForScrypt(decoded_salt), + passphrase})); + break; + case syncer::KeyDerivationMethod::UNSUPPORTED: + // This test cannot pass since we wouldn't know how to decrypt data + // encrypted using an unsupported method. + FAIL() << "Unsupported key derivation method encountered: " + << nigori.custom_passphrase_key_derivation_method(); + } +} + +sync_pb::NigoriSpecifics CreateCustomPassphraseNigori( + const syncer::KeyParams& params) { + syncer::KeyDerivationMethod method = params.derivation_params.method(); + + sync_pb::NigoriSpecifics nigori; + nigori.set_keybag_is_frozen(true); + nigori.set_keystore_migration_time(1U); + nigori.set_encrypt_everything(true); + nigori.set_passphrase_type(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE); + nigori.set_custom_passphrase_key_derivation_method( + EnumKeyDerivationMethodToProto(method)); + + std::string encoded_salt; + switch (method) { + case syncer::KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003: + // Nothing to do; no further information needs to be extracted from + // Nigori. + break; + case syncer::KeyDerivationMethod::SCRYPT_8192_8_11: + base::Base64Encode(params.derivation_params.scrypt_salt(), &encoded_salt); + nigori.set_custom_passphrase_key_derivation_salt(encoded_salt); + break; + case syncer::KeyDerivationMethod::UNSUPPORTED: + ADD_FAILURE() + << "Unsupported method in KeyParams, cannot construct Nigori."; + break; + } + + // Nigori also contains a keybag, which is an encrypted collection of all keys + // that the data might be encrypted with. To create it, we construct a + // cryptographer, add our key to it, and use GetKeys() to dump it to the + // keybag (in encrypted form). So, in our case, the keybag is simply the + // passphrase-derived key encrypted with itself. Note that this is usually + // also the case during normal Sync operation, and so the keybag from Nigori + // only helps the encryption machinery to know if a given key is correct (e.g. + // checking if a user's passphrase is correct is done by trying to decrypt the + // keybag using a key derived from that passphrase). However, in some migrated + // states, the keybag might also additionally contain an old, pre-migration + // key. + syncer::SystemEncryptor encryptor; + syncer::Cryptographer cryptographer(&encryptor); + bool add_key_result = cryptographer.AddKey(params); + DCHECK(add_key_result); + bool get_keys_result = + cryptographer.GetKeys(nigori.mutable_encryption_keybag()); + DCHECK(get_keys_result); + + return nigori; +} + +sync_pb::EntitySpecifics GetEncryptedBookmarkEntitySpecifics( + const sync_pb::BookmarkSpecifics& bookmark_specifics, + const syncer::KeyParams& key_params) { + sync_pb::EntitySpecifics new_specifics; + + sync_pb::EntitySpecifics wrapped_entity_specifics; + *wrapped_entity_specifics.mutable_bookmark() = bookmark_specifics; + syncer::SystemEncryptor encryptor; + syncer::Cryptographer cryptographer(&encryptor); + bool add_key_result = cryptographer.AddKey(key_params); + DCHECK(add_key_result); + bool encrypt_result = cryptographer.Encrypt( + wrapped_entity_specifics, new_specifics.mutable_encrypted()); + DCHECK(encrypt_result); + + new_specifics.mutable_bookmark()->set_title("encrypted"); + new_specifics.mutable_bookmark()->set_url("encrypted"); + + return new_specifics; +} + +void SetNigoriInFakeServer(fake_server::FakeServer* fake_server, + const sync_pb::NigoriSpecifics& nigori) { + std::string nigori_entity_id = + fake_server->GetTopLevelPermanentItemId(syncer::NIGORI); + ASSERT_NE(nigori_entity_id, ""); + sync_pb::EntitySpecifics nigori_entity_specifics; + *nigori_entity_specifics.mutable_nigori() = nigori; + fake_server->ModifyEntitySpecifics(nigori_entity_id, nigori_entity_specifics); +} + +} // namespace encryption_helper + +ServerNigoriChecker::ServerNigoriChecker( + browser_sync::ProfileSyncService* service, + fake_server::FakeServer* fake_server, + syncer::PassphraseType expected_passphrase_type) + : SingleClientStatusChangeChecker(service), + fake_server_(fake_server), + expected_passphrase_type_(expected_passphrase_type) {} + +bool ServerNigoriChecker::IsExitConditionSatisfied() { + std::vector<sync_pb::SyncEntity> nigori_entities = + fake_server_->GetPermanentSyncEntitiesByModelType(syncer::NIGORI); + EXPECT_LE(nigori_entities.size(), 1U); + return !nigori_entities.empty() && + syncer::ProtoPassphraseTypeToEnum( + nigori_entities[0].specifics().nigori().passphrase_type()) == + expected_passphrase_type_; +} + +std::string ServerNigoriChecker::GetDebugMessage() const { + return "Waiting for a Nigori node with the proper passphrase type to become " + "available on the server."; +} + +PassphraseRequiredStateChecker::PassphraseRequiredStateChecker( + browser_sync::ProfileSyncService* service, + bool desired_state) + : SingleClientStatusChangeChecker(service), desired_state_(desired_state) {} + +bool PassphraseRequiredStateChecker::IsExitConditionSatisfied() { + return service()->IsPassphraseRequiredForDecryption() == desired_state_; +} + +std::string PassphraseRequiredStateChecker::GetDebugMessage() const { + return "Waiting until decryption passphrase is " + + std::string(desired_state_ ? "required" : "not required"); +}
diff --git a/chrome/browser/sync/test/integration/encryption_helper.h b/chrome/browser/sync/test/integration/encryption_helper.h new file mode 100644 index 0000000..5b560c1 --- /dev/null +++ b/chrome/browser/sync/test/integration/encryption_helper.h
@@ -0,0 +1,79 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_ENCRYPTION_HELPER_H_ +#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_ENCRYPTION_HELPER_H_ + +#include <string> + +#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" +#include "components/sync/base/cryptographer.h" +#include "components/sync/protocol/nigori_specifics.pb.h" +#include "components/sync/test/fake_server/fake_server.h" + +namespace encryption_helper { + +// Given a |fake_server|, fetches its Nigori node and writes it to the +// proto pointed to by |nigori|. Returns false if the server does not contain +// exactly one Nigori node. +bool GetServerNigori(fake_server::FakeServer* fake_server, + sync_pb::NigoriSpecifics* nigori); + +// Given a |fake_server|, sets the Nigori instance stored in it to |nigori|. +void SetNigoriInFakeServer(fake_server::FakeServer* fake_server, + const sync_pb::NigoriSpecifics& nigori); + +// Given a |nigori| with CUSTOM_PASSPHRASE passphrase type, initializes the +// given |cryptographer| with the key described in it. Since the key inside the +// Nigori is encrypted (by design), the provided |passphrase| will be used to +// decrypt it. This function will fail the test (using ASSERT) if the Nigori is +// not a custom passphrase one, or if the key cannot be decrypted. +void InitCustomPassphraseCryptographerFromNigori( + const sync_pb::NigoriSpecifics& nigori, + syncer::Cryptographer* cryptographer, + const std::string& passphrase); + +// Returns an EntitySpecifics containing encrypted data corresponding to the +// provided BookmarkSpecifics and encrypted using the given |key_params|. +sync_pb::EntitySpecifics GetEncryptedBookmarkEntitySpecifics( + const sync_pb::BookmarkSpecifics& specifics, + const syncer::KeyParams& key_params); + +// Creates a NigoriSpecifics that describes encryption using a custom passphrase +// with the given key parameters. +sync_pb::NigoriSpecifics CreateCustomPassphraseNigori( + const syncer::KeyParams& params); + +} // namespace encryption_helper + +// Checker used to block until a Nigori with a given passphrase type is +// available on the server. +class ServerNigoriChecker : public SingleClientStatusChangeChecker { + public: + ServerNigoriChecker(browser_sync::ProfileSyncService* service, + fake_server::FakeServer* fake_server, + syncer::PassphraseType expected_passphrase_type); + + bool IsExitConditionSatisfied() override; + std::string GetDebugMessage() const override; + + private: + fake_server::FakeServer* fake_server_; + syncer::PassphraseType expected_passphrase_type_; +}; + +// Checker used to block until Sync requires or stops requiring a passphrase. +class PassphraseRequiredStateChecker : public SingleClientStatusChangeChecker { + public: + PassphraseRequiredStateChecker(browser_sync::ProfileSyncService* service, + bool desired_state); + + bool IsExitConditionSatisfied() override; + std::string GetDebugMessage() const override; + + private: + bool desired_state_; +}; + +#endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_ENCRYPTION_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc index 5814613..5e99091f 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -182,7 +182,7 @@ #endif // !OS_CHROMEOS bool ProfileSyncServiceHarness::SetupSync() { - bool result = SetupSync(syncer::UserSelectableTypes(), false); + bool result = SetupSync(syncer::UserSelectableTypes()); if (!result) { LOG(ERROR) << profile_debug_name_ << ": SetupSync failed. Syncer status:\n" << GetServiceStatus(); @@ -193,7 +193,9 @@ } bool ProfileSyncServiceHarness::SetupSyncForClearingServerData() { - bool result = SetupSync(syncer::UserSelectableTypes(), true); + bool result = SetupSyncImpl(syncer::UserSelectableTypes(), + /*skip_passphrase_verification=*/true, + /*encryption_passphrase=*/base::nullopt); if (!result) { LOG(ERROR) << profile_debug_name_ << ": SetupSyncForClear failed. Syncer status:\n" @@ -204,8 +206,47 @@ return result; } -bool ProfileSyncServiceHarness::SetupSync(syncer::ModelTypeSet synced_datatypes, - bool skip_passphrase_verification) { +bool ProfileSyncServiceHarness::SetupSync( + syncer::ModelTypeSet synced_datatypes) { + return SetupSyncImpl(synced_datatypes, /*skip_passphrase_verification=*/false, + /*encryption_passphrase=*/base::nullopt); +} + +bool ProfileSyncServiceHarness::SetupSyncWithEncryptionPassphrase( + syncer::ModelTypeSet synced_datatypes, + const std::string& passphrase) { + return SetupSyncImpl(synced_datatypes, /*skip_passphrase_verification=*/false, + passphrase); +} + +bool ProfileSyncServiceHarness::SetupSyncWithDecryptionPassphrase( + syncer::ModelTypeSet synced_datatypes, + const std::string& passphrase) { + if (!SetupSyncImpl(synced_datatypes, /*skip_passphrase_verification=*/true, + /*encryption_passphrase=*/base::nullopt)) { + return false; + } + + DVLOG(1) << "Setting decryption passphrase."; + if (!service_->SetDecryptionPassphrase(passphrase)) { + // This is not a fatal failure, as some tests intentionally pass an + // incorrect passphrase. If this happens, Sync will be set up but will have + // encountered cryptographer errors for the passphrase-encrypted datatypes. + LOG(INFO) << "SetDecryptionPassphrase() failed."; + } + // Since SetupSyncImpl() was called with skip_passphrase_verification == true, + // it will not have called FinishSyncSetup(). FinishSyncSetup() is in charge + // of calling ProfileSyncService::SetFirstSetupComplete(), and without that, + // Sync will still be in setup mode and Sync-the-feature will be disabled. + // Therefore, we call FinishSyncSetup() here explicitly. + FinishSyncSetup(); + return true; +} + +bool ProfileSyncServiceHarness::SetupSyncImpl( + syncer::ModelTypeSet synced_datatypes, + bool skip_passphrase_verification, + const base::Optional<std::string>& encryption_passphrase) { DCHECK(!profile_->IsLegacySupervised()) << "SetupSync should not be used for legacy supervised users."; @@ -243,6 +284,12 @@ service()->OnUserChoseDatatypes(sync_everything, synced_datatypes); } + if (encryption_passphrase.has_value()) { + service()->SetEncryptionPassphrase( + encryption_passphrase.value(), + syncer::SyncService::PassphraseType::EXPLICIT); + } + // Notify ProfileSyncService that we are done with configuration. if (skip_passphrase_verification) { sync_blocker_.reset();
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.h b/chrome/browser/sync/test/integration/profile_sync_service_harness.h index dff401d..f38d1d5 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.h +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/optional.h" #include "components/browser_sync/profile_sync_service.h" #include "components/sync/base/model_type.h" #include "components/sync/engine/cycle/sync_cycle_snapshot.h" @@ -62,11 +63,21 @@ // StopSyncService(), StartSyncService() directly after. bool SetupSyncForClearingServerData(); - // Both SetupSync and SetupSyncForClearingServerData call into this method. - // Same as the above method, but enables sync only for the datatypes contained - // in |synced_datatypes|. - bool SetupSync(syncer::ModelTypeSet synced_datatypes, - bool skip_passphrase_verification = false); + // Enables and configures sync only for the given |synced_datatypes|. Returns + // true only after sync has been fully initialized and authenticated, and we + // are ready to process changes. + bool SetupSync(syncer::ModelTypeSet synced_datatypes); + + // Same as SetupSync(), but also sets the given encryption passphrase during + // setup. + bool SetupSyncWithEncryptionPassphrase(syncer::ModelTypeSet synced_datatypes, + const std::string& passphrase); + + // Same as SetupSync(), but also sets the given decryption passphrase during + // setup. If the passphrase is incorrect, this method will still return true + // and Sync will be operational but with undecryptable datatypes disabled. + bool SetupSyncWithDecryptionPassphrase(syncer::ModelTypeSet synced_datatypes, + const std::string& passphrase); // Signals that sync setup is complete, and that PSS may begin syncing. // Typically SetupSync does this automatically, but if that returned false, @@ -146,6 +157,16 @@ const std::string& password, SigninType signin_type); + // If |encryption_passphrase| has a value, it will be set during setup. If + // not, no custom passphrase will be set. If |skip_passphrase_verification| is + // true and Sync requires a passphrase, FinishSyncSetup() will not be called, + // in order to give the caller a chance to provide the passphrase using + // SetDecryptionPassphrase(). After that, the caller needs to call + // FinishSyncSetup() manually. + bool SetupSyncImpl(syncer::ModelTypeSet synced_datatypes, + bool skip_passphrase_verification, + const base::Optional<std::string>& encryption_passphrase); + // Gets detailed status from |service_| in pretty-printable form. std::string GetServiceStatus();
diff --git a/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc new file mode 100644 index 0000000..d9d59a95 --- /dev/null +++ b/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc
@@ -0,0 +1,364 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/sync/test/integration/bookmarks_helper.h" +#include "chrome/browser/sync/test/integration/encryption_helper.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "components/browser_sync/profile_sync_service.h" +#include "components/sync/base/cryptographer.h" +#include "components/sync/base/passphrase_enums.h" +#include "components/sync/base/sync_base_switches.h" +#include "components/sync/base/system_encryptor.h" +#include "components/sync/engine/sync_engine_switches.h" + +namespace { + +using bookmarks_helper::AddURL; +using bookmarks_helper::CreateBookmarkServerEntity; +using encryption_helper::CreateCustomPassphraseNigori; +using encryption_helper::GetEncryptedBookmarkEntitySpecifics; +using encryption_helper::GetServerNigori; +using encryption_helper::InitCustomPassphraseCryptographerFromNigori; +using encryption_helper::SetNigoriInFakeServer; +using fake_server::FakeServer; +using sync_pb::EncryptedData; +using sync_pb::NigoriSpecifics; +using sync_pb::SyncEntity; +using syncer::Cryptographer; +using syncer::KeyDerivationParams; +using syncer::KeyParams; +using syncer::LoopbackServerEntity; +using syncer::ModelType; +using syncer::ModelTypeSet; +using syncer::PassphraseType; +using syncer::ProtoPassphraseTypeToEnum; +using syncer::SyncService; +using syncer::SystemEncryptor; + +class DatatypeCommitCountingFakeServerObserver : public FakeServer::Observer { + public: + explicit DatatypeCommitCountingFakeServerObserver(FakeServer* fake_server) + : fake_server_(fake_server) { + fake_server->AddObserver(this); + } + + void OnCommit(const std::string& committer_id, + ModelTypeSet committed_model_types) override { + for (ModelType type : committed_model_types) { + ++datatype_commit_counts_[type]; + } + } + + int GetCommitCountForDatatype(ModelType type) { + return datatype_commit_counts_[type]; + } + + ~DatatypeCommitCountingFakeServerObserver() override { + fake_server_->RemoveObserver(this); + } + + private: + FakeServer* fake_server_; + std::map<syncer::ModelType, int> datatype_commit_counts_; +}; + +// These tests use a gray-box testing approach to verify that the data committed +// to the server is encrypted properly, and that properly-encrypted data from +// the server is successfully decrypted by the client. They also verify that the +// key derivation methods are set, read and handled properly. They do not, +// however, directly ensure that two clients syncing through the same account +// will be able to access each others' data in the presence of a custom +// passphrase. For this, a separate two-client test will be used. +// +// TODO(davidovic): Add two-client tests and update the above comment. +class SingleClientCustomPassphraseSyncTest : public SyncTest { + public: + SingleClientCustomPassphraseSyncTest() : SyncTest(SINGLE_CLIENT) {} + ~SingleClientCustomPassphraseSyncTest() override {} + + // Waits until the given set of bookmarks appears on the server, encrypted + // according to the server-side Nigori and with the given passphrase. + bool WaitForEncryptedServerBookmarks( + const std::vector<ServerBookmarksEqualityChecker::ExpectedBookmark>& + expected_bookmarks, + const std::string& passphrase) { + auto cryptographer = CreateCryptographerFromServerNigori(passphrase); + return ServerBookmarksEqualityChecker(GetSyncService(), GetFakeServer(), + expected_bookmarks, + cryptographer.get()) + .Wait(); + } + + // Waits until the given set of bookmarks appears on the server, encrypted + // with the precise KeyParams given. + bool WaitForEncryptedServerBookmarks( + const std::vector<ServerBookmarksEqualityChecker::ExpectedBookmark>& + expected_bookmarks, + const KeyParams& key_params) { + auto cryptographer = CreateCryptographerWithKeyParams(key_params); + return ServerBookmarksEqualityChecker(GetSyncService(), GetFakeServer(), + expected_bookmarks, + cryptographer.get()) + .Wait(); + } + + bool WaitForUnencryptedServerBookmarks( + const std::vector<ServerBookmarksEqualityChecker::ExpectedBookmark>& + expected_bookmarks) { + return ServerBookmarksEqualityChecker(GetSyncService(), GetFakeServer(), + expected_bookmarks, + /*cryptographer=*/nullptr) + .Wait(); + } + + bool WaitForNigori(PassphraseType expected_passphrase_type) { + return ServerNigoriChecker(GetSyncService(), GetFakeServer(), + expected_passphrase_type) + .Wait(); + } + + bool WaitForPassphraseRequiredState(bool desired_state) { + return PassphraseRequiredStateChecker(GetSyncService(), desired_state) + .Wait(); + } + + bool WaitForClientBookmarkWithTitle(std::string title) { + return BookmarksTitleChecker(/*profile_index=*/0, title, + /*expected_count=*/1) + .Wait(); + } + + browser_sync::ProfileSyncService* GetSyncService() { + return SyncTest::GetSyncService(0); + } + + // When the cryptographer is initialized with a passphrase, it uses the key + // derivation method and other parameters from the server-side Nigori. Thus, + // checking that the server-side Nigori contains the desired key derivation + // method and checking that the server-side encrypted bookmarks can be + // decrypted using a cryptographer initialized with this function is + // sufficient to determine that a given key derivation method is being + // correctly used for encryption. + std::unique_ptr<Cryptographer> CreateCryptographerFromServerNigori( + const std::string& passphrase) { + NigoriSpecifics nigori; + EXPECT_TRUE(GetServerNigori(GetFakeServer(), &nigori)); + EXPECT_EQ(ProtoPassphraseTypeToEnum(nigori.passphrase_type()), + PassphraseType::CUSTOM_PASSPHRASE); + auto cryptographer = std::make_unique<Cryptographer>(&system_encryptor_); + InitCustomPassphraseCryptographerFromNigori(nigori, cryptographer.get(), + passphrase); + return cryptographer; + } + + // A cryptographer initialized with the given KeyParams has not "seen" the + // server-side Nigori, and so any data decryptable by such a cryptographer + // does not depend on external info. + std::unique_ptr<Cryptographer> CreateCryptographerWithKeyParams( + const KeyParams& key_params) { + auto cryptographer = std::make_unique<Cryptographer>(&system_encryptor_); + cryptographer->AddKey(key_params); + return cryptographer; + } + + void SetScryptFeaturesState(bool force_disabled, + bool use_for_new_passphrases) { + std::vector<base::Feature> enabled_features; + std::vector<base::Feature> disabled_features; + if (force_disabled) { + enabled_features.push_back( + switches::kSyncForceDisableScryptForCustomPassphrase); + } else { + disabled_features.push_back( + switches::kSyncForceDisableScryptForCustomPassphrase); + } + if (use_for_new_passphrases) { + enabled_features.push_back( + switches::kSyncUseScryptForNewCustomPassphrases); + } else { + disabled_features.push_back( + switches::kSyncUseScryptForNewCustomPassphrases); + } + feature_list_.InitWithFeatures(enabled_features, disabled_features); + } + + void InjectEncryptedServerBookmark(const std::string& title, + const GURL& url, + const KeyParams& key_params) { + std::unique_ptr<LoopbackServerEntity> server_entity = + CreateBookmarkServerEntity(title, url); + server_entity->SetSpecifics(GetEncryptedBookmarkEntitySpecifics( + server_entity->GetSpecifics().bookmark(), key_params)); + GetFakeServer()->InjectEntity(std::move(server_entity)); + } + + private: + SystemEncryptor system_encryptor_; + base::test::ScopedFeatureList feature_list_; + + DISALLOW_COPY_AND_ASSIGN(SingleClientCustomPassphraseSyncTest); +}; + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + CommitsEncryptedData) { + SetEncryptionPassphraseForClient(/*index=*/0, "hunter2"); + ASSERT_TRUE(SetupSync()); + + ASSERT_TRUE( + AddURL(/*profile=*/0, "Hello world", GURL("https://google.com/"))); + ASSERT_TRUE( + AddURL(/*profile=*/0, "Bookmark #2", GURL("https://example.com/"))); + ASSERT_TRUE(WaitForNigori(PassphraseType::CUSTOM_PASSPHRASE)); + + EXPECT_TRUE(WaitForEncryptedServerBookmarks( + {{"Hello world", GURL("https://google.com/")}, + {"Bookmark #2", GURL("https://example.com/")}}, + /*passphrase=*/"hunter2")); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + CommitsEncryptedDataUsingPbkdf2WhenScryptDisabled) { + SetScryptFeaturesState(/*force_disabled=*/false, + /*use_for_new_passphrases=*/false); + SetEncryptionPassphraseForClient(/*index=*/0, "hunter2"); + ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(AddURL(/*profile=*/0, "PBKDF2 encrypted", + GURL("https://google.com/pbkdf2-encrypted"))); + + ASSERT_TRUE(WaitForNigori(PassphraseType::CUSTOM_PASSPHRASE)); + NigoriSpecifics nigori; + EXPECT_TRUE(GetServerNigori(GetFakeServer(), &nigori)); + EXPECT_EQ(nigori.custom_passphrase_key_derivation_method(), + sync_pb::NigoriSpecifics::PBKDF2_HMAC_SHA1_1003); + EXPECT_TRUE(WaitForEncryptedServerBookmarks( + {{"PBKDF2 encrypted", GURL("https://google.com/pbkdf2-encrypted")}}, + /*passphrase=*/"hunter2")); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + CommitsEncryptedDataUsingScryptWhenScryptEnabled) { + SetScryptFeaturesState(/*force_disabled=*/false, + /*use_for_new_passphrases=*/true); + SetEncryptionPassphraseForClient(/*index=*/0, "hunter2"); + ASSERT_TRUE(SetupSync()); + + ASSERT_TRUE(AddURL(/*profile=*/0, "scrypt encrypted", + GURL("https://google.com/scrypt-encrypted"))); + + ASSERT_TRUE(WaitForNigori(PassphraseType::CUSTOM_PASSPHRASE)); + NigoriSpecifics nigori; + EXPECT_TRUE(GetServerNigori(GetFakeServer(), &nigori)); + EXPECT_EQ(nigori.custom_passphrase_key_derivation_method(), + sync_pb::NigoriSpecifics::SCRYPT_8192_8_11); + EXPECT_TRUE(WaitForEncryptedServerBookmarks( + {{"scrypt encrypted", GURL("https://google.com/scrypt-encrypted")}}, + /*passphrase=*/"hunter2")); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + CanDecryptPbkdf2KeyEncryptedData) { + KeyParams key_params = {KeyDerivationParams::CreateForPbkdf2(), "hunter2"}; + InjectEncryptedServerBookmark("PBKDF2-encrypted bookmark", + GURL("http://example.com/doesnt-matter"), + key_params); + SetNigoriInFakeServer(GetFakeServer(), + CreateCustomPassphraseNigori(key_params)); + SetDecryptionPassphraseForClient(/*index=*/0, "hunter2"); + + ASSERT_TRUE(SetupSync()); + EXPECT_TRUE(WaitForPassphraseRequiredState(/*desired_state=*/false)); + + EXPECT_TRUE(WaitForClientBookmarkWithTitle("PBKDF2-encrypted bookmark")); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + CanDecryptScryptKeyEncryptedDataWhenScryptNotDisabled) { + SetScryptFeaturesState(/*force_disabled=*/false, + /*used_for_new_passphrases_=*/false); + KeyParams key_params = { + KeyDerivationParams::CreateForScrypt("someConstantSalt"), "hunter2"}; + InjectEncryptedServerBookmark("scypt-encrypted bookmark", + GURL("http://example.com/doesnt-matter"), + key_params); + SetNigoriInFakeServer(GetFakeServer(), + CreateCustomPassphraseNigori(key_params)); + SetDecryptionPassphraseForClient(/*index=*/0, "hunter2"); + + ASSERT_TRUE(SetupSync()); + EXPECT_TRUE(WaitForPassphraseRequiredState(/*desired_state=*/false)); + + EXPECT_TRUE(WaitForClientBookmarkWithTitle("scypt-encrypted bookmark")); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled) { + KeyParams key_params = { + KeyDerivationParams::CreateForScrypt("someConstantSalt"), "hunter2"}; + sync_pb::NigoriSpecifics nigori = CreateCustomPassphraseNigori(key_params); + InjectEncryptedServerBookmark("scypt-encrypted bookmark", + GURL("http://example.com/doesnt-matter"), + key_params); + // Can only set feature state now because creating a Nigori and injecting an + // encrypted bookmark both require key derivation using scrypt. + SetScryptFeaturesState(/*force_disabled=*/true, + /*used_for_new_passphrases_=*/false); + SetNigoriInFakeServer(GetFakeServer(), nigori); + SetDecryptionPassphraseForClient(/*index=*/0, "hunter2"); + + ASSERT_TRUE(SetupSync()); + + EXPECT_TRUE(WaitForPassphraseRequiredState(/*desired_state=*/true)); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + DoesNotLeakUnencryptedData) { + SetScryptFeaturesState(/*force_disabled=*/false, + /*use_for_new_passphrases=*/false); + SetEncryptionPassphraseForClient(/*index=*/0, "hunter2"); + DatatypeCommitCountingFakeServerObserver observer(GetFakeServer()); + ASSERT_TRUE(SetupSync()); + + ASSERT_TRUE(AddURL(/*profile=*/0, "Should be encrypted", + GURL("https://google.com/encrypted"))); + + ASSERT_TRUE(WaitForNigori(PassphraseType::CUSTOM_PASSPHRASE)); + // If WaitForEncryptedServerBookmarks() succeeds, that means that a + // cryptographer initialized with only the key params was able to decrypt the + // data, so the data must be encrypted using a passphrase-derived key (and not + // e.g. a keystore key), because that cryptographer has never seen the + // server-side Nigori. Furthermore, if a bookmark commit has happened only + // once, we are certain that no bookmarks other than those we've verified to + // be encrypted have been committed. + EXPECT_TRUE(WaitForEncryptedServerBookmarks( + {{"Should be encrypted", GURL("https://google.com/encrypted")}}, + {KeyDerivationParams::CreateForPbkdf2(), "hunter2"})); + EXPECT_EQ(observer.GetCommitCountForDatatype(syncer::BOOKMARKS), 1); +} + +IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest, + ReencryptsDataWhenPassphraseIsSet) { + SetScryptFeaturesState(/*force_disabled=*/false, + /*use_for_new_passphrases=*/false); + ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(WaitForNigori(PassphraseType::KEYSTORE_PASSPHRASE)); + ASSERT_TRUE(AddURL(/*profile=*/0, "Re-encryption is great", + GURL("https://google.com/re-encrypted"))); + std::vector<ServerBookmarksEqualityChecker::ExpectedBookmark> expected = { + {"Re-encryption is great", GURL("https://google.com/re-encrypted")}}; + ASSERT_TRUE(WaitForUnencryptedServerBookmarks(expected)); + + GetSyncService()->SetEncryptionPassphrase( + "hunter2", SyncService::PassphraseType::EXPLICIT); + ASSERT_TRUE(WaitForNigori(PassphraseType::CUSTOM_PASSPHRASE)); + + // If WaitForEncryptedServerBookmarks() succeeds, that means that a + // cryptographer initialized with only the key params was able to decrypt the + // data, so the data must be encrypted using a passphrase-derived key (and not + // e.g. the previous keystore key which was stored in the Nigori keybag), + // because that cryptographer has never seen the server-side Nigori. + EXPECT_TRUE(WaitForEncryptedServerBookmarks( + expected, {KeyDerivationParams::CreateForPbkdf2(), "hunter2"})); +} + +} // namespace
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index 328a8ef8..cc0e9f0 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -643,6 +643,20 @@ fake_server_->RemoveObserver(fake_server_invalidation_services_[index]); } +void SyncTest::SetEncryptionPassphraseForClient(int index, + const std::string& passphrase) { + // Must be called before client initialization. + DCHECK(clients_.empty()); + client_encryption_passphrases_[index] = passphrase; +} + +void SyncTest::SetDecryptionPassphraseForClient(int index, + const std::string& passphrase) { + // Must be called before client initialization. + DCHECK(clients_.empty()); + client_decryption_passphrases_[index] = passphrase; +} + void SyncTest::SetupMockGaiaResponsesForProfile(Profile* profile) { ChromeSigninClient* signin_client = static_cast<ChromeSigninClient*>( ChromeSigninClientFactory::GetForProfile(profile)); @@ -782,8 +796,35 @@ // Sync each of the profiles. for (; clientIndex < num_clients_; clientIndex++) { + ProfileSyncServiceHarness* client = GetClient(clientIndex); DVLOG(1) << "Setting up " << clientIndex << " client"; - if (!GetClient(clientIndex)->SetupSync()) { + + auto decryption_passphrase_it = + client_decryption_passphrases_.find(clientIndex); + auto encryption_passphrase_it = + client_encryption_passphrases_.find(clientIndex); + bool decryption_passphrase_provided = + (decryption_passphrase_it != client_decryption_passphrases_.end()); + bool encryption_passphrase_provided = + (encryption_passphrase_it != client_encryption_passphrases_.end()); + if (decryption_passphrase_provided && encryption_passphrase_provided) { + LOG(FATAL) << "Both an encryption and decryption passphrase were " + "provided for the client. This is disallowed."; + return false; + } + + bool setup_succeeded; + if (encryption_passphrase_provided) { + setup_succeeded = client->SetupSyncWithEncryptionPassphrase( + syncer::UserSelectableTypes(), encryption_passphrase_it->second); + } else if (decryption_passphrase_provided) { + setup_succeeded = client->SetupSyncWithDecryptionPassphrase( + syncer::UserSelectableTypes(), decryption_passphrase_it->second); + } else { + setup_succeeded = client->SetupSync(syncer::UserSelectableTypes()); + } + + if (!setup_succeeded) { LOG(FATAL) << "SetupSync() failed."; return false; }
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h index ec474802..41e8ea51 100644 --- a/chrome/browser/sync/test/integration/sync_test.h +++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -292,6 +292,23 @@ // Stops notificatinos being sent to a client. void DisableNotificationsForClient(int index); + // Sets a decryption passphrase to be used for a client. The passphrase will + // be provided to the client during initialization, before Sync starts. It is + // an error to provide both a decryption and encryption passphrases for one + // client. + void SetDecryptionPassphraseForClient(int index, + const std::string& passphrase); + + // Sets an explicit encryption passphrase to be used for a client. The + // passphrase will be set for the client during initialization, before Sync + // starts. An encryption passphrase can be also enabled after initialization, + // but using this method ensures that Sync is never enabled when there is no + // passphrase, which allows tests to check for unencrypted data leaks. It is + // an error to provide both a decryption and encryption passphrases for one + // client. + void SetEncryptionPassphraseForClient(int index, + const std::string& passphrase); + // Sets up fake responses for kClientLoginUrl, kIssueAuthTokenUrl, // kGetUserInfoUrl and kSearchDomainCheckUrl in order to mock out calls to // GAIA servers. @@ -443,6 +460,12 @@ // profile with the server. std::vector<std::unique_ptr<ProfileSyncServiceHarness>> clients_; + // Mapping from client indexes to encryption passphrases to use for them. + std::map<int, std::string> client_encryption_passphrases_; + + // Mapping from client indexes to decryption passphrases to use for them. + std::map<int, std::string> client_decryption_passphrases_; + // A set of objects to listen for commit activity and broadcast notifications // of this activity to its peer sync clients. std::vector<std::unique_ptr<P2PInvalidationForwarder>>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 57bfb5a2..e9f7ebd 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1532,6 +1532,8 @@ "webui/chromeos/login/discover/discover_window_manager_observer.h", "webui/chromeos/login/discover/modules/discover_module_launch_help_app.cc", "webui/chromeos/login/discover/modules/discover_module_launch_help_app.h", + "webui/chromeos/login/discover/modules/discover_module_pin_setup.cc", + "webui/chromeos/login/discover/modules/discover_module_pin_setup.h", "webui/chromeos/login/discover/modules/discover_module_redeem_offers.cc", "webui/chromeos/login/discover/modules/discover_module_redeem_offers.h", "webui/chromeos/login/discover/modules/discover_module_sync_files.cc", @@ -2634,6 +2636,8 @@ "views/overlay/control_image_button.h", "views/overlay/overlay_window_views.cc", "views/overlay/overlay_window_views.h", + "views/overlay/resize_handle_button.cc", + "views/overlay/resize_handle_button.h", "views/page_action/page_action_icon_container_view.cc", "views/page_action/page_action_icon_container_view.h", "views/page_action/page_action_icon_view.cc",
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index ae98c5f..0649a4c5 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -1297,7 +1297,7 @@ return; command_updater_.UpdateCommandEnabled( - IDC_SHOW_SYNC_SETUP, show_main_ui && pref_signin_allowed_.GetValue()); + IDC_SHOW_SIGNIN, show_main_ui && pref_signin_allowed_.GetValue()); } // static
diff --git a/chrome/browser/ui/browser_command_controller_unittest.cc b/chrome/browser/ui/browser_command_controller_unittest.cc index 14c5ed3..edb839e 100644 --- a/chrome/browser/ui/browser_command_controller_unittest.cc +++ b/chrome/browser/ui/browser_command_controller_unittest.cc
@@ -342,6 +342,7 @@ // Command ID | tab mode | fullscreen | // | enabled | reserved | enabled | reserved | + // clang-format off { IDC_OPEN_CURRENT_URL, true, false, false, false }, { IDC_FOCUS_TOOLBAR, true, false, false, false }, { IDC_FOCUS_LOCATION, true, false, false, false }, @@ -370,6 +371,8 @@ { IDC_SELECT_PREVIOUS_TAB, true, true, true, false }, { IDC_EXIT, true, true, true, true }, { IDC_SHOW_AS_TAB, false, false, false, false }, + { IDC_SHOW_SIGNIN, true, false, true, false }, + // clang-format on }; const content::NativeWebKeyboardEvent key_event( blink::WebInputEvent::kTypeFirst, 0, @@ -488,9 +491,9 @@ const CommandUpdater* command_updater = &command_controller; // Check that the SYNC_SETUP command is updated on preference change. - EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SYNC_SETUP)); + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN)); profile1->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false); - EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_SYNC_SETUP)); + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN)); } TEST_F(BrowserCommandControllerTest, OnSigninAllowedPrefChange) { @@ -498,7 +501,7 @@ const CommandUpdater* command_updater = &command_controller; // Check that the SYNC_SETUP command is updated on preference change. - EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SYNC_SETUP)); + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN)); profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false); - EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_SYNC_SETUP)); + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN)); }
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm index 33bc698..9a596d05 100644 --- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm +++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm
@@ -28,15 +28,18 @@ - (BOOL)isFullscreenTransitionInProgress { views::BridgedNativeWidgetImpl* bridge_widget = views::BridgedNativeWidgetImpl::GetFromNativeWindow([self window]); - return bridge_widget->in_fullscreen_transition(); + if (bridge_widget) + return bridge_widget->in_fullscreen_transition(); + return NO; } - (NSWindow*)window { NSWindow* ns_window = browserView_->GetNativeWindow(); if (!ns_view_) { - ns_view_.reset( - [views::BridgedNativeWidgetImpl::GetFromNativeWindow(ns_window) - ->ns_view() retain]); + views::BridgedNativeWidgetImpl* bridge_widget = + views::BridgedNativeWidgetImpl::GetFromNativeWindow(ns_window); + if (bridge_widget) + ns_view_.reset([bridge_widget->ns_view() retain]); } return ns_window; }
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index 5db023f3..aa93308 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -534,7 +534,7 @@ } LogMenuAction(MENU_ACTION_SHOW_DOWNLOADS); break; - case IDC_SHOW_SYNC_SETUP: + case IDC_SHOW_SIGNIN: if (!uma_action_recorded_) { UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowSyncSetup", delta);
diff --git a/chrome/browser/ui/views/overlay/close_image_button.cc b/chrome/browser/ui/views/overlay/close_image_button.cc index cb898b1..65e0eb97 100644 --- a/chrome/browser/ui/views/overlay/close_image_button.cc +++ b/chrome/browser/ui/views/overlay/close_image_button.cc
@@ -68,7 +68,17 @@ SetBackgroundImage(kCloseBgColor, nullptr, nullptr); } -void CloseImageButton::SetPosition(const gfx::Size& size) { +void CloseImageButton::SetPosition( + const gfx::Size& size, + OverlayWindowViews::WindowQuadrant quadrant) { +#if defined(OS_CHROMEOS) + if (quadrant == OverlayWindowViews::WindowQuadrant::kBottomLeft) { + ImageButton::SetPosition( + gfx::Point(kCloseButtonMargin, kCloseButtonMargin)); + return; + } +#endif + ImageButton::SetPosition( gfx::Point(size.width() - kCloseButtonSize - kCloseButtonMargin, kCloseButtonMargin));
diff --git a/chrome/browser/ui/views/overlay/close_image_button.h b/chrome/browser/ui/views/overlay/close_image_button.h index 5f14ac8..6ff8e9a 100644 --- a/chrome/browser/ui/views/overlay/close_image_button.h +++ b/chrome/browser/ui/views/overlay/close_image_button.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_CLOSE_IMAGE_BUTTON_H_ #define CHROME_BROWSER_UI_VIEWS_OVERLAY_CLOSE_IMAGE_BUTTON_H_ +#include "chrome/browser/ui/views/overlay/overlay_window_views.h" #include "ui/views/controls/button/image_button.h" namespace views { @@ -24,7 +25,8 @@ void OnBlur() override; // Sets the position of itself with an offset from the given window size. - void SetPosition(const gfx::Size& size); + void SetPosition(const gfx::Size& size, + OverlayWindowViews::WindowQuadrant quadrant); private: const gfx::ImageSkia close_background_;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc index 01fa670b4..a149b038 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.cc +++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -14,6 +14,7 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/overlay/close_image_button.h" #include "chrome/browser/ui/views/overlay/control_image_button.h" +#include "chrome/browser/ui/views/overlay/resize_handle_button.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/picture_in_picture_window_controller.h" #include "content/public/browser/web_contents.h" @@ -52,6 +53,30 @@ // Colors for the control buttons. SkColor kBgColor = SK_ColorWHITE; SkColor kControlIconColor = SK_ColorBLACK; + +// Returns the quadrant the OverlayWindowViews is primarily in on the current +// work area. +OverlayWindowViews::WindowQuadrant GetCurrentWindowQuadrant( + const gfx::Rect window_bounds, + content::PictureInPictureWindowController* controller) { + gfx::Rect work_area = + display::Screen::GetScreen() + ->GetDisplayNearestWindow( + controller->GetInitiatorWebContents()->GetTopLevelNativeWindow()) + .work_area(); + gfx::Point window_center = window_bounds.CenterPoint(); + + // Check which quadrant the center of the window appears in. + if (window_center.x() < work_area.width() / 2) { + return (window_center.y() < work_area.height() / 2) + ? OverlayWindowViews::WindowQuadrant::kTopLeft + : OverlayWindowViews::WindowQuadrant::kBottomLeft; + } + return (window_center.y() < work_area.height() / 2) + ? OverlayWindowViews::WindowQuadrant::kTopRight + : OverlayWindowViews::WindowQuadrant::kBottomRight; +} + } // namespace // OverlayWindow implementation of NonClientFrameView. @@ -142,6 +167,9 @@ controls_scrim_view_(new views::View()), controls_parent_view_(new views::View()), close_controls_view_(new views::CloseImageButton(this)), +#if defined(OS_CHROMEOS) + resize_handle_view_(new views::ResizeHandleButton(this)), +#endif play_pause_controls_view_(new views::ToggleImageButton(this)), hide_controls_timer_( FROM_HERE, @@ -266,6 +294,13 @@ play_pause_controls_view_->SetToggled(controller_->IsPlayerActive()); play_pause_controls_view_->set_owned_by_client(); +#if defined(OS_CHROMEOS) + // views::View that shows the affordance that the window can be resized. ---- + resize_handle_view_->SetPaintToLayer(ui::LAYER_TEXTURED); + resize_handle_view_->layer()->SetFillsBoundsOpaquely(false); + resize_handle_view_->set_owned_by_client(); +#endif + // Accessibility. play_pause_controls_view_->SetFocusForPlatform(); // Make button focusable. const base::string16 play_pause_accessible_button_label( @@ -286,6 +321,9 @@ GetContentsView()->AddChildView(controls_scrim_view_.get()); GetContentsView()->AddChildView(controls_parent_view_.get()); GetContentsView()->AddChildView(close_controls_view_.get()); +#if defined(OS_CHROMEOS) + GetContentsView()->AddChildView(resize_handle_view_.get()); +#endif UpdatePlayPauseControlsSize(); UpdateControlsVisibility(false); @@ -323,6 +361,11 @@ play_pause_controls_view_->SetVisible(false); GetCloseControlsLayer()->SetVisible(is_visible); + +#if defined(OS_CHROMEOS) + GetResizeHandleLayer()->SetVisible(is_visible); +#endif + GetControlsScrimLayer()->SetVisible( (playback_state_ == kNoVideo) ? false : is_visible); GetControlsParentLayer()->SetVisible( @@ -337,7 +380,11 @@ controls_scrim_view_->SetBoundsRect( gfx::Rect(gfx::Point(0, 0), larger_window_bounds.size())); - close_controls_view_->SetPosition(GetBounds().size()); + WindowQuadrant quadrant = GetCurrentWindowQuadrant(GetBounds(), controller_); + close_controls_view_->SetPosition(GetBounds().size(), quadrant); +#if defined(OS_CHROMEOS) + resize_handle_view_->SetPosition(GetBounds().size(), quadrant); +#endif controls_parent_view_->SetBoundsRect( gfx::Rect(gfx::Point(0, 0), GetBounds().size())); @@ -609,6 +656,13 @@ // the window to reappear with the same origin point when a new video is // shown. window_bounds_ = GetBounds(); + +#if defined(OS_CHROMEOS) + // Update the positioning of some icons when the window is moved. + WindowQuadrant quadrant = GetCurrentWindowQuadrant(GetBounds(), controller_); + close_controls_view_->SetPosition(GetBounds().size(), quadrant); + resize_handle_view_->SetPosition(GetBounds().size(), quadrant); +#endif } void OverlayWindowViews::OnNativeWidgetSizeChanged(const gfx::Size& new_size) { @@ -771,6 +825,10 @@ return close_controls_view_->layer(); } +ui::Layer* OverlayWindowViews::GetResizeHandleLayer() { + return resize_handle_view_->layer(); +} + ui::Layer* OverlayWindowViews::GetControlsParentLayer() { return controls_parent_view_->layer(); } @@ -788,6 +846,14 @@ return play_pause_controls_view_.get(); } +gfx::Point OverlayWindowViews::close_image_position_for_testing() const { + return close_controls_view_->origin(); +} + +gfx::Point OverlayWindowViews::resize_handle_position_for_testing() const { + return resize_handle_view_->origin(); +} + views::View* OverlayWindowViews::controls_parent_view_for_testing() const { return controls_parent_view_.get(); }
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h index 7431f5f..b1f714d 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.h +++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -14,6 +14,7 @@ namespace views { class ControlImageButton; class CloseImageButton; +class ResizeHandleButton; class ToggleImageButton; } // namespace views @@ -27,6 +28,8 @@ content::PictureInPictureWindowController* controller); ~OverlayWindowViews() override; + enum class WindowQuadrant { kBottomLeft, kBottomRight, kTopLeft, kTopRight }; + // OverlayWindow: bool IsActive() const override; void Close() override; @@ -67,6 +70,8 @@ gfx::Rect GetSecondCustomControlsBounds(); views::ToggleImageButton* play_pause_controls_view_for_testing() const; + gfx::Point close_image_position_for_testing() const; + gfx::Point resize_handle_position_for_testing() const; views::View* controls_parent_view_for_testing() const; OverlayWindowViews::PlaybackState playback_state_for_testing() const; @@ -118,6 +123,7 @@ ui::Layer* GetControlsScrimLayer(); ui::Layer* GetCloseControlsLayer(); + ui::Layer* GetResizeHandleLayer(); ui::Layer* GetControlsParentLayer(); // Toggles the play/pause control through the |controller_| and updates the @@ -174,6 +180,7 @@ // the close view. std::unique_ptr<views::View> controls_parent_view_; std::unique_ptr<views::CloseImageButton> close_controls_view_; + std::unique_ptr<views::ResizeHandleButton> resize_handle_view_; std::unique_ptr<views::ToggleImageButton> play_pause_controls_view_; std::unique_ptr<views::ControlImageButton> first_custom_controls_view_; std::unique_ptr<views::ControlImageButton> second_custom_controls_view_;
diff --git a/chrome/browser/ui/views/overlay/resize_handle_button.cc b/chrome/browser/ui/views/overlay/resize_handle_button.cc new file mode 100644 index 0000000..9fca4a8 --- /dev/null +++ b/chrome/browser/ui/views/overlay/resize_handle_button.cc
@@ -0,0 +1,101 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/overlay/resize_handle_button.h" + +#include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/grit/generated_resources.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/image/image_skia_operations.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/skbitmap_operations.h" +#include "ui/views/vector_icons.h" + +namespace { + +const int kResizeHandleButtonSize = 16; + +constexpr SkColor kResizeHandleIconColor = SK_ColorWHITE; + +} // namespace + +namespace views { + +ResizeHandleButton::ResizeHandleButton(ButtonListener* listener) + : ImageButton(listener) { + SetImageAlignment(views::ImageButton::ALIGN_CENTER, + views::ImageButton::ALIGN_MIDDLE); + SetSize(gfx::Size(kResizeHandleButtonSize, kResizeHandleButtonSize)); + SetImageForQuadrant(OverlayWindowViews::WindowQuadrant::kBottomRight); + + // Accessibility. + SetFocusForPlatform(); + const base::string16 resize_button_label( + l10n_util::GetStringUTF16(IDS_PICTURE_IN_PICTURE_RESIZE_HANDLE_TEXT)); + SetAccessibleName(resize_button_label); + SetTooltipText(resize_button_label); + SetInstallFocusRingOnFocus(true); +} + +ResizeHandleButton::~ResizeHandleButton() = default; + +void ResizeHandleButton::SetPosition( + const gfx::Size& size, + OverlayWindowViews::WindowQuadrant quadrant) { + // The resize handle should appear towards the center of the working area. + // This is determined as the opposite quadrant on the window. + switch (quadrant) { + case OverlayWindowViews::WindowQuadrant::kBottomLeft: + ImageButton::SetPosition( + gfx::Point(size.width() - kResizeHandleButtonSize, 0)); + break; + case OverlayWindowViews::WindowQuadrant::kBottomRight: + ImageButton::SetPosition(gfx::Point(0, 0)); + break; + case OverlayWindowViews::WindowQuadrant::kTopLeft: + ImageButton::SetPosition( + gfx::Point(size.width() - kResizeHandleButtonSize, + size.height() - kResizeHandleButtonSize)); + break; + case OverlayWindowViews::WindowQuadrant::kTopRight: + ImageButton::SetPosition( + gfx::Point(0, size.height() - kResizeHandleButtonSize)); + break; + } + + // Also rotate the icon to match the new corner. + SetImageForQuadrant(quadrant); +} + +void ResizeHandleButton::SetImageForQuadrant( + OverlayWindowViews::WindowQuadrant quadrant) { + if (current_quadrant_ == quadrant) + return; + current_quadrant_ = quadrant; + + gfx::ImageSkia icon = gfx::CreateVectorIcon( + kResizeHandleIcon, kResizeHandleButtonSize, kResizeHandleIconColor); + switch (quadrant) { + case OverlayWindowViews::WindowQuadrant::kBottomLeft: + break; + case OverlayWindowViews::WindowQuadrant::kBottomRight: + icon = gfx::ImageSkiaOperations::CreateRotatedImage( + icon, SkBitmapOperations::ROTATION_270_CW); + break; + case OverlayWindowViews::WindowQuadrant::kTopLeft: + icon = gfx::ImageSkiaOperations::CreateRotatedImage( + icon, SkBitmapOperations::ROTATION_90_CW); + break; + case OverlayWindowViews::WindowQuadrant::kTopRight: + icon = gfx::ImageSkiaOperations::CreateRotatedImage( + icon, SkBitmapOperations::ROTATION_180_CW); + break; + } + + SetImage(views::Button::STATE_NORMAL, icon); +} + +} // namespace views
diff --git a/chrome/browser/ui/views/overlay/resize_handle_button.h b/chrome/browser/ui/views/overlay/resize_handle_button.h new file mode 100644 index 0000000..1b3646f --- /dev/null +++ b/chrome/browser/ui/views/overlay/resize_handle_button.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_OVERLAY_RESIZE_HANDLE_BUTTON_H_ +#define CHROME_BROWSER_UI_VIEWS_OVERLAY_RESIZE_HANDLE_BUTTON_H_ + +#include "chrome/browser/ui/views/overlay/overlay_window_views.h" +#include "ui/views/controls/button/image_button.h" + +namespace views { + +// An image button representing a white resize handle affordance. +class ResizeHandleButton : public views::ImageButton { + public: + explicit ResizeHandleButton(ButtonListener* listener); + ~ResizeHandleButton() override; + + void SetPosition(const gfx::Size& size, + OverlayWindowViews::WindowQuadrant quadrant); + + private: + void SetImageForQuadrant(OverlayWindowViews::WindowQuadrant quadrant); + + base::Optional<OverlayWindowViews::WindowQuadrant> current_quadrant_; + + DISALLOW_COPY_AND_ASSIGN(ResizeHandleButton); +}; + +} // namespace views + +#endif // CHROME_BROWSER_UI_VIEWS_OVERLAY_RESIZE_HANDLE_BUTTON_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.cc b/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.cc index 0a205aa253..389e69a 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.cc
@@ -9,17 +9,35 @@ #include "base/logging.h" #include "chrome/browser/ui/webui/chromeos/login/discover/discover_handler.h" #include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.h" +#include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.h" #include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.h" #include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.h" #include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.h" namespace chromeos { +namespace { + +// Owned by ChromeBrowserMainPartsChromeos. +DiscoverManager* g_discover_manager = nullptr; + +} // namespace DiscoverManager::DiscoverManager() { + DCHECK(!g_discover_manager); + g_discover_manager = this; + CreateModules(); } -DiscoverManager::~DiscoverManager() = default; +DiscoverManager::~DiscoverManager() { + DCHECK_EQ(g_discover_manager, this); + g_discover_manager = nullptr; +} + +// static +DiscoverManager* DiscoverManager::Get() { + return g_discover_manager; +} bool DiscoverManager::IsCompleted() const { // Returns true if all of the modules are completed. @@ -38,6 +56,8 @@ std::make_unique<DiscoverModuleSyncFiles>(); modules_[DiscoverModuleWelcome::kModuleName] = std::make_unique<DiscoverModuleWelcome>(); + modules_[DiscoverModulePinSetup::kModuleName] = + std::make_unique<DiscoverModulePinSetup>(); } std::vector<std::unique_ptr<DiscoverHandler>> @@ -49,4 +69,10 @@ return handlers; } +DiscoverModule* DiscoverManager::GetModuleByName( + const std::string& module_name) const { + const auto it = modules_.find(module_name); + return it == modules_.end() ? nullptr : it->second.get(); +} + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h b/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h index bd0fa04..8ac51be 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h +++ b/chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h
@@ -25,17 +25,29 @@ DiscoverManager(); ~DiscoverManager(); + // Returns object instance from platform_parts. + static DiscoverManager* Get(); + // Returns true if there are no modules to be displayed. bool IsCompleted() const; // Returns vector of WebUI message handlers for visible modules. std::vector<std::unique_ptr<DiscoverHandler>> CreateWebUIHandlers() const; + template <typename T> + T* GetModule() { + return static_cast<T*>(GetModuleByName(T::kModuleName)); + } + const ModulesMap& get_modules() const { return modules_; } private: // Creates all needed modules. void CreateModules(); + + // Returns module by name. + DiscoverModule* GetModuleByName(const std::string& module_name) const; + ModulesMap modules_; DISALLOW_COPY_AND_ASSIGN(DiscoverManager);
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/discover_module.h b/chrome/browser/ui/webui/chromeos/login/discover/discover_module.h index add727f..e97a5ad 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/discover_module.h +++ b/chrome/browser/ui/webui/chromeos/login/discover/discover_module.h
@@ -24,7 +24,7 @@ virtual bool IsCompleted() const = 0; // Creates and returns WebUI handler for the module. - virtual std::unique_ptr<DiscoverHandler> CreateWebUIHandler() const = 0; + virtual std::unique_ptr<DiscoverHandler> CreateWebUIHandler() = 0; // Module is also expected to provide static method: // static const char* kModuleName;
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/discover_ui.cc b/chrome/browser/ui/webui/chromeos/login/discover/discover_ui.cc index 553853e..426e678 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/discover_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/discover_ui.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/webui/chromeos/login/discover/discover_ui.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/ui/webui/chromeos/login/discover/discover_handler.h" #include "chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h" #include "content/public/browser/web_ui.h" @@ -17,9 +16,7 @@ void DiscoverUI::RegisterMessages(content::WebUI* web_ui) { std::vector<std::unique_ptr<DiscoverHandler>> handlers = - g_browser_process->platform_part() - ->GetDiscoverManager() - ->CreateWebUIHandlers(); + DiscoverManager::Get()->CreateWebUIHandlers(); for (auto& handler : handlers) { handlers_.push_back(handler.get()); web_ui->AddMessageHandler(std::move(handler));
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.cc b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.cc index cd3e89c..37ea54d 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.cc
@@ -70,7 +70,7 @@ } std::unique_ptr<DiscoverHandler> -DiscoverModuleLaunchHelpApp::CreateWebUIHandler() const { +DiscoverModuleLaunchHelpApp::CreateWebUIHandler() { return std::make_unique<DiscoverModuleLaunchHelpAppHandler>(); }
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.h b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.h index 7a386ab..78774b3 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.h +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app.h
@@ -19,7 +19,7 @@ // DiscoverModule: bool IsCompleted() const override; - std::unique_ptr<DiscoverHandler> CreateWebUIHandler() const override; + std::unique_ptr<DiscoverHandler> CreateWebUIHandler() override; // Module name. static const char kModuleName[];
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.cc b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.cc new file mode 100644 index 0000000..3586320 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.cc
@@ -0,0 +1,137 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.h" + +#include <vector> + +#include "base/i18n/number_formatting.h" +#include "base/values.h" +#include "chrome/browser/ui/webui/chromeos/login/discover/discover_handler.h" +#include "chrome/grit/browser_resources.h" +#include "chrome/grit/generated_resources.h" +#include "components/login/localized_values_builder.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" + +namespace chromeos { + +namespace { + +class DiscoverModulePinSetupHandler : public DiscoverHandler { + public: + explicit DiscoverModulePinSetupHandler( + base::WeakPtr<DiscoverModulePinSetup> module); + ~DiscoverModulePinSetupHandler() override = default; + + // BaseWebUIHandler + void DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) override; + void Initialize() override; + void RegisterMessages() override; + + private: + // Message handlers. + void HandleGetUserPassword(const std::string& callbackId); + + base::WeakPtr<DiscoverModulePinSetup> module_; + + DISALLOW_COPY_AND_ASSIGN(DiscoverModulePinSetupHandler); +}; + +DiscoverModulePinSetupHandler::DiscoverModulePinSetupHandler( + base::WeakPtr<DiscoverModulePinSetup> module) + : DiscoverHandler(DiscoverModulePinSetup::kModuleName), module_(module) {} + +void DiscoverModulePinSetupHandler::DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) { + builder->Add("discoverPinSetup", IDS_DISCOVER_PIN_SETUP); + + builder->Add("back", IDS_EULA_BACK_BUTTON); + builder->Add("next", IDS_EULA_NEXT_BUTTON); + builder->Add("discoverPinSetupDone", IDS_DISCOVER_PIN_SETUP_DONE); + + builder->Add("discoverPinSetupTitle1", IDS_DISCOVER_PIN_SETUP_TITLE1); + builder->Add("discoverPinSetupSubtitle1", IDS_DISCOVER_PIN_SETUP_SUBTITLE1); + builder->Add("discoverPinSetupSkip", IDS_DISCOVER_PIN_SETUP_SKIP); + builder->Add("discoverPinSetupTitle2", IDS_DISCOVER_PIN_SETUP_TITLE2); + builder->Add("discoverPinSetupTitle3", IDS_DISCOVER_PIN_SETUP_TITLE3); + builder->Add("discoverPinSetupSubtitle3", IDS_DISCOVER_PIN_SETUP_SUBTITLE3); + builder->Add("discoverPinSetupPasswordTitle", + IDS_DISCOVER_PIN_SETUP_PASSWORD_TITLE); + builder->Add("discoverPinSetupPasswordSubTitle", + IDS_DISCOVER_PIN_SETUP_PASSWORD_SUBTITLE); + + builder->Add("passwordPromptInvalidPassword", + IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_INVALID_PASSWORD); + builder->Add("passwordPromptPasswordLabel", + IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_PASSWORD_LABEL); + + // Format numbers to be used on the pin keyboard. + for (int j = 0; j <= 9; j++) { + builder->Add("pinKeyboard" + base::IntToString(j), + base::FormatNumber(int64_t{j})); + } + builder->Add("pinKeyboardPlaceholderPin", IDS_PIN_KEYBOARD_HINT_TEXT_PIN); + builder->Add("pinKeyboardPlaceholderPinPassword", + IDS_PIN_KEYBOARD_HINT_TEXT_PIN_PASSWORD); + builder->Add("pinKeyboardDeleteAccessibleName", + IDS_PIN_KEYBOARD_DELETE_ACCESSIBLE_NAME); + builder->Add("configurePinMismatched", + IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED); + builder->Add("configurePinTooShort", + IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT); + builder->Add("configurePinTooLong", + IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG); + builder->Add("configurePinWeakPin", + IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN); +} + +void DiscoverModulePinSetupHandler::Initialize() {} + +void DiscoverModulePinSetupHandler::RegisterMessages() { + AddCallback("discover.pinSetup.getUserPassword", + &DiscoverModulePinSetupHandler::HandleGetUserPassword); +} + +void DiscoverModulePinSetupHandler::HandleGetUserPassword( + const std::string& callbackId) { + web_ui()->CallJavascriptFunctionUnsafe( + "window.discoverReturn", base::Value(callbackId), + base::Value(module_->ConsumePrimaryUserPassword())); + return; +} + +} // anonymous namespace + +/* ***************************************************************** */ +/* Discover PinSetup module implementation below. */ + +const char DiscoverModulePinSetup::kModuleName[] = "pinSetup"; + +DiscoverModulePinSetup::DiscoverModulePinSetup() {} + +DiscoverModulePinSetup::~DiscoverModulePinSetup() = default; + +bool DiscoverModulePinSetup::IsCompleted() const { + return false; +} + +std::unique_ptr<DiscoverHandler> DiscoverModulePinSetup::CreateWebUIHandler() { + return std::make_unique<DiscoverModulePinSetupHandler>( + weak_ptr_factory_.GetWeakPtr()); +} + +std::string DiscoverModulePinSetup::ConsumePrimaryUserPassword() { + std::string result; + std::swap(primary_user_password_, result); + return result; +} + +void DiscoverModulePinSetup::SetPrimaryUserPassword( + const std::string& password) { + primary_user_password_ = password; +} + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.h b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.h new file mode 100644 index 0000000..e0e9421 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_pin_setup.h
@@ -0,0 +1,43 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DISCOVER_MODULES_DISCOVER_MODULE_PIN_SETUP_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DISCOVER_MODULES_DISCOVER_MODULE_PIN_SETUP_H_ + +#include <memory> + +#include "base/containers/flat_map.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/webui/chromeos/login/discover/discover_module.h" + +namespace chromeos { + +class DiscoverModulePinSetup : public DiscoverModule { + public: + // Module name. + static const char kModuleName[]; + + DiscoverModulePinSetup(); + ~DiscoverModulePinSetup() override; + + // Returns primary user password, or empty string if not known. + // Password is kept for newly created user only, and is returned only once. + // (Empty string will be returned for subsequent calls.) + std::string ConsumePrimaryUserPassword(); + void SetPrimaryUserPassword(const std::string& password); + + // DiscoverModule: + bool IsCompleted() const override; + std::unique_ptr<DiscoverHandler> CreateWebUIHandler() override; + + private: + std::string primary_user_password_; + + base::WeakPtrFactory<DiscoverModulePinSetup> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(DiscoverModulePinSetup); +}; + +} // namespace chromeos +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_DISCOVER_MODULES_DISCOVER_MODULE_PIN_SETUP_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.cc b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.cc index 300586e..cf44c276 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.cc
@@ -56,7 +56,7 @@ } std::unique_ptr<DiscoverHandler> -DiscoverModuleRedeemOffers::CreateWebUIHandler() const { +DiscoverModuleRedeemOffers::CreateWebUIHandler() { return std::make_unique<DiscoverModuleRedeemOffersHandler>(); }
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.h b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.h index ac4d91b..7060b55 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.h +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_redeem_offers.h
@@ -19,7 +19,7 @@ // DiscoverModule: bool IsCompleted() const override; - std::unique_ptr<DiscoverHandler> CreateWebUIHandler() const override; + std::unique_ptr<DiscoverHandler> CreateWebUIHandler() override; // Module name. static const char kModuleName[];
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.cc b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.cc index cb910b7..00e8d236 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.cc
@@ -55,8 +55,7 @@ return false; } -std::unique_ptr<DiscoverHandler> DiscoverModuleSyncFiles::CreateWebUIHandler() - const { +std::unique_ptr<DiscoverHandler> DiscoverModuleSyncFiles::CreateWebUIHandler() { return std::make_unique<DiscoverModuleSyncFilesHandler>(); }
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.h b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.h index 2eccb23..d1efcc5 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.h +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_sync_files.h
@@ -19,7 +19,7 @@ // DiscoverModule: bool IsCompleted() const override; - std::unique_ptr<DiscoverHandler> CreateWebUIHandler() const override; + std::unique_ptr<DiscoverHandler> CreateWebUIHandler() override; // Module name. static const char kModuleName[];
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.cc b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.cc index c5c8cb6e..b5f75cd 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.cc +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.cc
@@ -57,8 +57,7 @@ return false; } -std::unique_ptr<DiscoverHandler> DiscoverModuleWelcome::CreateWebUIHandler() - const { +std::unique_ptr<DiscoverHandler> DiscoverModuleWelcome::CreateWebUIHandler() { return std::make_unique<DiscoverModuleWelcomeHandler>(); }
diff --git a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.h b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.h index bdde6246..dcb1d66 100644 --- a/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.h +++ b/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_welcome.h
@@ -19,7 +19,7 @@ // DiscoverModule: bool IsCompleted() const override; - std::unique_ptr<DiscoverHandler> CreateWebUIHandler() const override; + std::unique_ptr<DiscoverHandler> CreateWebUIHandler() override; // Module name. static const char kModuleName[];
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index 27535a2..edcbdbb7 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -658,7 +658,8 @@ "contexts": ["webui"], "matches": [ "chrome://multidevice-setup/*", - "chrome://settings/*" + "chrome://settings/*", + "chrome://oobe/*" ], "platforms": ["chromeos"] },
diff --git a/chrome/credential_provider/gaiacp/BUILD.gn b/chrome/credential_provider/gaiacp/BUILD.gn index 46f6393..4d8d07f 100644 --- a/chrome/credential_provider/gaiacp/BUILD.gn +++ b/chrome/credential_provider/gaiacp/BUILD.gn
@@ -38,9 +38,7 @@ # Needed in order to include the win32 header security.h. "SECURITY_WIN32", ] - libs = [ - "secur32.lib", # For LsaXXX functions - ] + libs = [ "secur32.lib" ] # For LsaXXX functions } # This static library is shared with the test code. @@ -74,7 +72,9 @@ "win_http_url_fetcher.h", ] public_configs = [ ":gaiacp_config" ] - public_deps = [ ":common" ] + public_deps = [ + ":common", + ] deps = [ ":gaia_credential_provider_idl", ":resources", @@ -129,6 +129,60 @@ "google_logo_small.bmp", ] outputs = [ + "gaia_resources_am.pak", + "gaia_resources_ar.pak", + "gaia_resources_bg.pak", + "gaia_resources_bn.pak", + "gaia_resources_ca.pak", + "gaia_resources_cs.pak", + "gaia_resources_da.pak", + "gaia_resources_de.pak", + "gaia_resources_el.pak", + "gaia_resources_en-GB.pak", + "gaia_resources_en-US.pak", + "gaia_resources_es-419.pak", + "gaia_resources_es.pak", + "gaia_resources_et.pak", + "gaia_resources_fa.pak", + "gaia_resources_fake-bidi.pak", + "gaia_resources_fi.pak", + "gaia_resources_fil.pak", + "gaia_resources_fr.pak", + "gaia_resources_gu.pak", + "gaia_resources_he.pak", + "gaia_resources_hi.pak", + "gaia_resources_hr.pak", + "gaia_resources_hu.pak", + "gaia_resources_id.pak", + "gaia_resources_it.pak", + "gaia_resources_ja.pak", + "gaia_resources_kn.pak", + "gaia_resources_ko.pak", + "gaia_resources_lt.pak", + "gaia_resources_lv.pak", + "gaia_resources_ml.pak", + "gaia_resources_mr.pak", + "gaia_resources_ms.pak", + "gaia_resources_nb.pak", + "gaia_resources_nl.pak", + "gaia_resources_pl.pak", + "gaia_resources_pt-BR.pak", + "gaia_resources_pt-PT.pak", + "gaia_resources_ro.pak", + "gaia_resources_ru.pak", + "gaia_resources_sk.pak", + "gaia_resources_sl.pak", + "gaia_resources_sr.pak", + "gaia_resources_sv.pak", + "gaia_resources_sw.pak", + "gaia_resources_ta.pak", + "gaia_resources_te.pak", + "gaia_resources_th.pak", + "gaia_resources_tr.pak", + "gaia_resources_uk.pak", + "gaia_resources_vi.pak", + "gaia_resources_zh-CN.pak", + "gaia_resources_zh-TW.pak", "grit/gaia_resources.h", "grit/gaia_resources.rc", ] @@ -155,7 +209,5 @@ ":version", "//chrome/common:version_header", ] - configs += [ - "//build/config/win:windowed", - ] + configs += [ "//build/config/win:windowed" ] }
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc index 07f10e12..c9f1eb82 100644 --- a/chrome/renderer/extensions/cast_streaming_native_handler.cc +++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -43,7 +43,6 @@ #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/web/web_dom_media_stream_track.h" -#include "third_party/blink/public/web/web_media_stream_registry.h" #include "url/gurl.h" using content::V8ValueConverter; @@ -61,10 +60,7 @@ constexpr char kInvalidAesIvMask[] = "Invalid value for AES IV mask"; constexpr char kInvalidAesKey[] = "Invalid value for AES key"; -constexpr char kInvalidAudioParams[] = "Invalid audio params"; constexpr char kInvalidDestination[] = "Invalid destination"; -constexpr char kInvalidFPS[] = "Invalid FPS"; -constexpr char kInvalidMediaStreamURL[] = "Invalid MediaStream URL"; constexpr char kInvalidRtpParams[] = "Invalid value for RTP params"; constexpr char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)"; constexpr char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)"; @@ -377,10 +373,6 @@ RouteHandlerFunction("GetStats", "cast.streaming.rtpStream", base::Bind(&CastStreamingNativeHandler::GetStats, weak_factory_.GetWeakPtr())); - RouteHandlerFunction( - "StartCastRtpReceiver", "cast.streaming.receiverSession", - base::Bind(&CastStreamingNativeHandler::StartCastRtpReceiver, - weak_factory_.GetWeakPtr())); } void CastStreamingNativeHandler::Invalidate() { @@ -913,117 +905,6 @@ return true; } -void CastStreamingNativeHandler::StartCastRtpReceiver( - const v8::FunctionCallbackInfo<v8::Value>& args) { - if (args.Length() < 8 || args.Length() > 9 || - !args[0]->IsObject() || - !args[1]->IsObject() || - !args[2]->IsObject() || - !args[3]->IsInt32() || - !args[4]->IsInt32() || - !args[5]->IsNumber() || - !args[6]->IsString()) { - args.GetIsolate()->ThrowException(v8::Exception::TypeError( - v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs, - v8::NewStringType::kNormal) - .ToLocalChecked())); - return; - } - - v8::Isolate* isolate = context()->v8_context()->GetIsolate(); - - scoped_refptr<CastReceiverSession> session( - new CastReceiverSession()); - media::cast::FrameReceiverConfig audio_config; - media::cast::FrameReceiverConfig video_config; - net::IPEndPoint local_endpoint; - net::IPEndPoint remote_endpoint; - - if (!FrameReceiverConfigFromArg(isolate, args[0], &audio_config) || - !FrameReceiverConfigFromArg(isolate, args[1], &video_config) || - !IPEndPointFromArg(isolate, args[2], &local_endpoint)) { - return; - } - - const int max_width = args[3]->ToInt32(args.GetIsolate())->Value(); - const int max_height = args[4]->ToInt32(args.GetIsolate())->Value(); - const double fps = args[5].As<v8::Number>()->Value(); - - if (fps <= 1) { - args.GetIsolate()->ThrowException(v8::Exception::TypeError( - v8::String::NewFromUtf8(args.GetIsolate(), kInvalidFPS, - v8::NewStringType::kNormal) - .ToLocalChecked())); - return; - } - - const std::string url = *v8::String::Utf8Value(isolate, args[6]); - blink::WebMediaStream stream = - blink::WebMediaStreamRegistry::LookupMediaStreamDescriptor(GURL(url)); - - if (stream.IsNull()) { - args.GetIsolate()->ThrowException(v8::Exception::TypeError( - v8::String::NewFromUtf8(args.GetIsolate(), kInvalidMediaStreamURL, - v8::NewStringType::kNormal) - .ToLocalChecked())); - return; - } - - media::VideoCaptureFormat capture_format(gfx::Size(max_width, max_height), - fps, media::PIXEL_FORMAT_I420); - - video_config.target_frame_rate = fps; - audio_config.target_frame_rate = 100; - - media::AudioParameters params( - media::AudioParameters::AUDIO_PCM_LINEAR, - media::GuessChannelLayout(audio_config.channels), - audio_config.rtp_timebase, // sampling rate - static_cast<int>(audio_config.rtp_timebase / - audio_config.target_frame_rate)); - - if (!params.IsValid()) { - args.GetIsolate()->ThrowException(v8::Exception::TypeError( - v8::String::NewFromUtf8(args.GetIsolate(), kInvalidAudioParams, - v8::NewStringType::kNormal) - .ToLocalChecked())); - return; - } - - std::unique_ptr<base::DictionaryValue> options; - if (args.Length() >= 9) { - std::unique_ptr<base::Value> options_value = - V8ValueConverter::Create()->FromV8Value(args[8], - context()->v8_context()); - if (!options_value->is_none()) { - options = base::DictionaryValue::From(std::move(options_value)); - if (!options) { - args.GetIsolate()->ThrowException(v8::Exception::TypeError( - v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs, - v8::NewStringType::kNormal) - .ToLocalChecked())); - return; - } - } - } - - if (!options) { - options.reset(new base::DictionaryValue()); - } - - v8::CopyablePersistentTraits<v8::Function>::CopyablePersistent error_callback; - error_callback.Reset(args.GetIsolate(), - v8::Local<v8::Function>(args[7].As<v8::Function>())); - - session->Start( - audio_config, video_config, local_endpoint, remote_endpoint, - std::move(options), capture_format, - base::Bind(&CastStreamingNativeHandler::AddTracksToMediaStream, - weak_factory_.GetWeakPtr(), url, params), - base::Bind(&CastStreamingNativeHandler::CallReceiverErrorCallback, - weak_factory_.GetWeakPtr(), error_callback)); -} - void CastStreamingNativeHandler::CallReceiverErrorCallback( v8::CopyablePersistentTraits<v8::Function>::CopyablePersistent function, const std::string& error_message) { @@ -1036,27 +917,4 @@ 1, &arg); } -void CastStreamingNativeHandler::AddTracksToMediaStream( - const std::string& url, - const media::AudioParameters& params, - scoped_refptr<media::AudioCapturerSource> audio, - std::unique_ptr<media::VideoCapturerSource> video) { - blink::WebMediaStream web_stream = - blink::WebMediaStreamRegistry::LookupMediaStreamDescriptor(GURL(url)); - if (web_stream.IsNull()) { - LOG(DFATAL) << "Stream not found."; - return; - } - if (!content::AddAudioTrackToMediaStream( - audio, params.sample_rate(), params.channel_layout(), - params.frames_per_buffer(), true, // is_remote - &web_stream)) { - LOG(ERROR) << "Failed to add Cast audio track to media stream."; - } - if (!content::AddVideoTrackToMediaStream(std::move(video), true, // is_remote - &web_stream)) { - LOG(ERROR) << "Failed to add Cast video track to media stream."; - } -} - } // namespace extensions
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.h b/chrome/renderer/extensions/cast_streaming_native_handler.h index 4d4c41fb..6ba698b 100644 --- a/chrome/renderer/extensions/cast_streaming_native_handler.h +++ b/chrome/renderer/extensions/cast_streaming_native_handler.h
@@ -26,9 +26,6 @@ } namespace media { -class AudioCapturerSource; -class AudioParameters; -class VideoCapturerSource; namespace cast { struct FrameReceiverConfig; } @@ -76,9 +73,6 @@ void StopCastUdpTransport( const v8::FunctionCallbackInfo<v8::Value>& args); - void StartCastRtpReceiver( - const v8::FunctionCallbackInfo<v8::Value>& args); - void ToggleLogging(const v8::FunctionCallbackInfo<v8::Value>& args); void GetRawEvents(const v8::FunctionCallbackInfo<v8::Value>& args); void GetStats(const v8::FunctionCallbackInfo<v8::Value>& args); @@ -93,14 +87,6 @@ void CallStopCallback(int stream_id) const; void CallErrorCallback(int stream_id, const std::string& message) const; - // Callback called after a cast receiver has been started. Adds the - // output audio/video streams to the MediaStream specified by |url|. - void AddTracksToMediaStream( - const std::string& url, - const media::AudioParameters& params, - scoped_refptr<media::AudioCapturerSource> audio, - std::unique_ptr<media::VideoCapturerSource> video); - // |function| is a javascript function that will take |error_message| as // an argument. Called when something goes wrong in a cast receiver. void CallReceiverErrorCallback(
diff --git a/chrome/renderer/resources/extensions/cast_streaming_receiver_session_custom_bindings.js b/chrome/renderer/resources/extensions/cast_streaming_receiver_session_custom_bindings.js index 7510ace..3dadf0e 100644 --- a/chrome/renderer/resources/extensions/cast_streaming_receiver_session_custom_bindings.js +++ b/chrome/renderer/resources/extensions/cast_streaming_receiver_session_custom_bindings.js
@@ -14,8 +14,6 @@ apiFunctions.setHandleRequest( 'createAndBind', function(ap, vp, local, weidgth, height, fr, url, cb, op) { - natives.StartCastRtpReceiver( - ap, vp, local, weidgth, height, fr, url, cb, op); }); });
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index bfe2180..2b76bbc 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -525,6 +525,7 @@ "../browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc", "../browser/browsing_data/browsing_data_remover_browsertest.cc", "../browser/browsing_data/counters/autofill_counter_browsertest.cc", + "../browser/browsing_data/counters/browsing_data_counter_utils_browsertest.cc", "../browser/browsing_data/counters/cache_counter_browsertest.cc", "../browser/browsing_data/counters/conditional_cache_counting_helper_browsertest.cc", "../browser/browsing_data/counters/downloads_counter_browsertest.cc", @@ -5187,6 +5188,8 @@ "../browser/sync/test/integration/dictionary_helper.h", "../browser/sync/test/integration/dictionary_load_observer.cc", "../browser/sync/test/integration/dictionary_load_observer.h", + "../browser/sync/test/integration/encryption_helper.cc", + "../browser/sync/test/integration/encryption_helper.h", "../browser/sync/test/integration/extension_settings_helper.cc", "../browser/sync/test/integration/extension_settings_helper.h", "../browser/sync/test/integration/extensions_helper.cc", @@ -5322,6 +5325,7 @@ "../browser/sync/test/integration/single_client_apps_sync_test.cc", "../browser/sync/test/integration/single_client_arc_package_sync_test.cc", "../browser/sync/test/integration/single_client_bookmarks_sync_test.cc", + "../browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc", "../browser/sync/test/integration/single_client_dictionary_sync_test.cc", "../browser/sync/test/integration/single_client_directory_sync_test.cc", "../browser/sync/test/integration/single_client_extensions_sync_test.cc",
diff --git a/components/data_use_measurement/core/BUILD.gn b/components/data_use_measurement/core/BUILD.gn index c4342d25..7e2c5b0 100644 --- a/components/data_use_measurement/core/BUILD.gn +++ b/components/data_use_measurement/core/BUILD.gn
@@ -33,10 +33,6 @@ "//google_apis", "//net", ] - - if (!is_ios) { - deps += [ "//components/domain_reliability" ] - } } source_set("unit_tests") {
diff --git a/components/data_use_measurement/core/DEPS b/components/data_use_measurement/core/DEPS index 0b56a36..de111298 100644 --- a/components/data_use_measurement/core/DEPS +++ b/components/data_use_measurement/core/DEPS
@@ -1,6 +1,4 @@ include_rules = [ "+net", "+components/metrics", - "+components/domain_reliability", - "+google_apis/gaia", ]
diff --git a/components/data_use_measurement/core/data_use_ascriber.cc b/components/data_use_measurement/core/data_use_ascriber.cc index 2f1b664..462d320 100644 --- a/components/data_use_measurement/core/data_use_ascriber.cc +++ b/components/data_use_measurement/core/data_use_ascriber.cc
@@ -7,9 +7,7 @@ #include <memory> #include <utility> -#include "components/data_use_measurement/core/data_use_network_delegate.h" #include "components/data_use_measurement/core/data_use_recorder.h" -#include "components/data_use_measurement/core/url_request_classifier.h" #include "net/http/http_response_headers.h" namespace data_use_measurement { @@ -17,14 +15,6 @@ DataUseAscriber::DataUseAscriber() {} DataUseAscriber::~DataUseAscriber() {} -std::unique_ptr<net::NetworkDelegate> DataUseAscriber::CreateNetworkDelegate( - std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate, - const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder) { - return std::make_unique<data_use_measurement::DataUseNetworkDelegate>( - std::move(wrapped_network_delegate), this, CreateURLRequestClassifier(), - metrics_data_use_forwarder); -} - void DataUseAscriber::OnBeforeUrlRequest(net::URLRequest* request) { DataUseRecorder* recorder = GetOrCreateDataUseRecorder(request); if (!recorder)
diff --git a/components/data_use_measurement/core/data_use_ascriber.h b/components/data_use_measurement/core/data_use_ascriber.h index c20e927..984bec89 100644 --- a/components/data_use_measurement/core/data_use_ascriber.h +++ b/components/data_use_measurement/core/data_use_ascriber.h
@@ -12,7 +12,6 @@ #include "base/observer_list.h" #include "base/threading/thread_checker.h" #include "components/data_use_measurement/core/data_use_measurement.h" -#include "components/metrics/data_use_tracker.h" #include "url/gurl.h" namespace net { @@ -69,9 +68,8 @@ virtual ~DataUseAscriber(); // Creates a network delegate that will be used to track data use. - std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate( - std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate, - const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder); + virtual std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate( + std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate) = 0; // Returns the DataUseRecorder to which data usage for the given URL should // be ascribed. If no existing DataUseRecorder exists, a new one will be
diff --git a/components/data_use_measurement/core/data_use_measurement.cc b/components/data_use_measurement/core/data_use_measurement.cc index 7005768..c786ced0 100644 --- a/components/data_use_measurement/core/data_use_measurement.cc +++ b/components/data_use_measurement/core/data_use_measurement.cc
@@ -16,8 +16,6 @@ #include "components/data_use_measurement/core/data_use_recorder.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/data_use_measurement/core/url_request_classifier.h" -#include "components/domain_reliability/uploader.h" -#include "google_apis/gaia/gaia_auth_util.h" #include "net/base/network_change_notifier.h" #include "net/base/upload_data_stream.h" #include "net/http/http_response_headers.h" @@ -75,10 +73,8 @@ DataUseMeasurement::DataUseMeasurement( std::unique_ptr<URLRequestClassifier> url_request_classifier, - const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder, DataUseAscriber* ascriber) : url_request_classifier_(std::move(url_request_classifier)), - metrics_data_use_forwarder_(metrics_data_use_forwarder), ascriber_(ascriber) #if defined(OS_ANDROID) , @@ -112,20 +108,7 @@ DataUseUserData* data_use_user_data = reinterpret_cast<DataUseUserData*>( request->GetUserData(DataUseUserData::kUserDataKey)); if (!data_use_user_data) { - DataUseUserData::ServiceName service_name = - DataUseUserData::ServiceName::NOT_TAGGED; - if (!IsUserRequest(*request) && - domain_reliability::DomainReliabilityUploader:: - OriginatedFromDomainReliability(*request)) { - // Detect if the request originated from DomainReliability. - // DataUseUserData::AttachToFetcher() cannot be called from domain - // reliability, since it sets userdata on URLFetcher for its purposes. - service_name = DataUseUserData::ServiceName::DOMAIN_RELIABILITY; - } else if (gaia::RequestOriginatedFromGaia(*request)) { - service_name = DataUseUserData::ServiceName::GAIA; - } - - data_use_user_data = new DataUseUserData(service_name, CurrentAppState()); + data_use_user_data = new DataUseUserData(CurrentAppState()); request->SetUserData(DataUseUserData::kUserDataKey, base::WrapUnique(data_use_user_data)); } else { @@ -137,7 +120,12 @@ const GURL& new_location) { // Recording data use of request on redirects. // TODO(rajendrant): May not be needed when http://crbug/651957 is fixed. - UpdateDataUsePrefs(request); + UpdateDataUseToMetricsService( + request.GetTotalSentBytes() + request.GetTotalReceivedBytes(), + net::NetworkChangeNotifier::IsConnectionCellular( + net::NetworkChangeNotifier::GetConnectionType()), + IsMetricsServiceRequest( + request.traffic_annotation().unique_id_hash_code)); ReportServicesMessageSizeUMA(request); if (url_request_classifier_->IsFavIconRequest(request)) RecordFavIconDataUse(request); @@ -176,7 +164,12 @@ bool started) { // TODO(amohammadkhan): Verify that there is no double recording in data use // of redirected requests. - UpdateDataUsePrefs(request); + UpdateDataUseToMetricsService( + request.GetTotalSentBytes() + request.GetTotalReceivedBytes(), + net::NetworkChangeNotifier::IsConnectionCellular( + net::NetworkChangeNotifier::GetConnectionType()), + IsMetricsServiceRequest( + request.traffic_annotation().unique_id_hash_code)); ReportServicesMessageSizeUMA(request); RecordPageTransitionUMA(request); #if defined(OS_ANDROID) @@ -261,30 +254,6 @@ } } -void DataUseMeasurement::UpdateDataUsePrefs( - const net::URLRequest& request) const { - bool is_connection_cellular = - net::NetworkChangeNotifier::IsConnectionCellular( - net::NetworkChangeNotifier::GetConnectionType()); - - DataUseUserData* attached_service_data = static_cast<DataUseUserData*>( - request.GetUserData(DataUseUserData::kUserDataKey)); - DataUseUserData::ServiceName service_name = - attached_service_data ? attached_service_data->service_name() - : DataUseUserData::NOT_TAGGED; - - // Update data use prefs for cellular connections. - // TODO(rajendrant): Change this to only report data use of user-initiated - // traffic and metrics services (UMA, UKM). This will help to remove the - // DataUseUserData::ServiceName enum. - if (!metrics_data_use_forwarder_.is_null()) { - metrics_data_use_forwarder_.Run( - DataUseUserData::GetServiceNameAsString(service_name), - request.GetTotalSentBytes() + request.GetTotalReceivedBytes(), - is_connection_cellular); - } -} - #if defined(OS_ANDROID) void DataUseMeasurement::OnApplicationStateChangeForTesting( base::android::ApplicationState application_state) { @@ -490,4 +459,16 @@ kUserInitiatedTrafficAnnotations.end(); } +// static +bool DataUseMeasurement::IsMetricsServiceRequest( + int32_t network_traffic_annotation_hash_id) { + static const std::set<int32_t> kMetricsServiceTrafficAnnotations = { + COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("metrics_report_uma"), + COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("metrics_report_ukm"), + }; + return kMetricsServiceTrafficAnnotations.find( + network_traffic_annotation_hash_id) != + kMetricsServiceTrafficAnnotations.end(); +} + } // namespace data_use_measurement
diff --git a/components/data_use_measurement/core/data_use_measurement.h b/components/data_use_measurement/core/data_use_measurement.h index 0dee70c..31951de8 100644 --- a/components/data_use_measurement/core/data_use_measurement.h +++ b/components/data_use_measurement/core/data_use_measurement.h
@@ -44,6 +44,10 @@ // Returns true if the |request| is initiated by user traffic. static bool IsUserRequest(const net::URLRequest& request); + // Returns true if the NTA hash is one used by metrics (UMA, UKM) component. + static bool IsMetricsServiceRequest( + int32_t network_traffic_annotation_hash_id); + // Returns the content-type saved in the request userdata when the response // headers were received. static DataUseUserData::DataUseContentType GetContentTypeForRequest( @@ -51,9 +55,8 @@ DataUseMeasurement( std::unique_ptr<URLRequestClassifier> url_request_classifier, - const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder, DataUseAscriber* ascriber); - ~DataUseMeasurement(); + virtual ~DataUseMeasurement(); // Called before a request is sent. void OnBeforeURLRequest(net::URLRequest* request); @@ -81,6 +84,12 @@ base::android::ApplicationState application_state); #endif + // Updates the data use to metrics service. |is_metrics_service_usage| + // indicates if the data use is from metrics component. + virtual void UpdateDataUseToMetricsService(int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) = 0; + private: friend class DataUseMeasurementTest; FRIEND_TEST_ALL_PREFIXES(DataUseMeasurementTest, @@ -134,9 +143,6 @@ TrafficDirection dir, int64_t bytes); - // Updates the data use of the |request|, thus |request| must be non-null. - void UpdateDataUsePrefs(const net::URLRequest& request) const; - // Reports the message size of the service requests. void ReportServicesMessageSizeUMA(const net::URLRequest& request); @@ -171,12 +177,6 @@ // Classifier for identifying if an URL request is user initiated. std::unique_ptr<URLRequestClassifier> url_request_classifier_; - // Callback for updating metrics about data use of user traffic and services. - // TODO(rajendrant): Change this to not report data use service name. Instead - // pass a bool to distinguish if the data use is for metrics services - // (UMA, UKM). - metrics::UpdateUsagePrefCallbackType metrics_data_use_forwarder_; - // DataUseAscriber used to get the attributes of data use. DataUseAscriber* ascriber_;
diff --git a/components/data_use_measurement/core/data_use_measurement_unittest.cc b/components/data_use_measurement/core/data_use_measurement_unittest.cc index cf6c15ec..8101408 100644 --- a/components/data_use_measurement/core/data_use_measurement_unittest.cc +++ b/components/data_use_measurement/core/data_use_measurement_unittest.cc
@@ -71,6 +71,11 @@ return &recorder_; } + std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate( + std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate) override { + return nullptr; + } + std::unique_ptr<URLRequestClassifier> CreateURLRequestClassifier() const override { return nullptr; @@ -82,6 +87,22 @@ DataUseRecorder recorder_; }; +class TestDataUseMeasurement : public DataUseMeasurement { + public: + TestDataUseMeasurement( + std::unique_ptr<URLRequestClassifier> url_request_classifier, + DataUseAscriber* ascriber) + : DataUseMeasurement(std::move(url_request_classifier), ascriber) {} + + void UpdateDataUseToMetricsService(int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) override { + is_data_use_forwarder_called_ = true; + } + + bool is_data_use_forwarder_called_ = false; +}; + // The more usual initialization of kUserDataKey would be along the lines of // const void* const TestURLRequestClassifier::kUserDataKey = // &TestURLRequestClassifier::kUserDataKey; @@ -104,8 +125,6 @@ : url_request_classifier_(new TestURLRequestClassifier()), data_use_measurement_( std::unique_ptr<URLRequestClassifier>(url_request_classifier_), - base::Bind(&DataUseMeasurementTest::FakeDataUseforwarder, - base::Unretained(this)), &ascriber_) { // During the test it is expected to not have cellular connection. DCHECK(!net::NetworkChangeNotifier::IsConnectionCellular( @@ -140,7 +159,6 @@ request->SetUserData( data_use_measurement::DataUseUserData::kUserDataKey, std::make_unique<data_use_measurement::DataUseUserData>( - data_use_measurement::DataUseUserData::SUGGESTIONS, data_use_measurement_.CurrentAppState())); } @@ -196,7 +214,9 @@ DataUseMeasurement* data_use_measurement() { return &data_use_measurement_; } - bool IsDataUseForwarderCalled() { return is_data_use_forwarder_called_; } + bool IsDataUseForwarderCalled() { + return data_use_measurement_.is_data_use_forwarder_called_; + } protected: void InitializeContext() { @@ -206,22 +226,15 @@ context_->Init(); } - void FakeDataUseforwarder(const std::string& service_name, - int message_size, - bool is_celllular) { - is_data_use_forwarder_called_ = true; - } - base::MessageLoopForIO loop_; TestDataUseAscriber ascriber_; TestURLRequestClassifier* url_request_classifier_; - DataUseMeasurement data_use_measurement_; + TestDataUseMeasurement data_use_measurement_; std::unique_ptr<net::MockClientSocketFactory> socket_factory_; std::unique_ptr<net::TestURLRequestContext> context_; const std::string kConnectionType = "NotCellular"; - bool is_data_use_forwarder_called_ = false; DISALLOW_COPY_AND_ASSIGN(DataUseMeasurementTest); };
diff --git a/components/data_use_measurement/core/data_use_network_delegate.cc b/components/data_use_measurement/core/data_use_network_delegate.cc index 0ab9e375..f78130b 100644 --- a/components/data_use_measurement/core/data_use_network_delegate.cc +++ b/components/data_use_measurement/core/data_use_network_delegate.cc
@@ -15,13 +15,10 @@ DataUseNetworkDelegate::DataUseNetworkDelegate( std::unique_ptr<NetworkDelegate> nested_network_delegate, DataUseAscriber* ascriber, - std::unique_ptr<URLRequestClassifier> url_request_classifier, - const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder) + std::unique_ptr<DataUseMeasurement> data_use_measurement) : net::LayeredNetworkDelegate(std::move(nested_network_delegate)), ascriber_(ascriber), - data_use_measurement_(std::move(url_request_classifier), - metrics_data_use_forwarder, - ascriber_) { + data_use_measurement_(std::move(data_use_measurement)) { DCHECK(ascriber); } @@ -31,13 +28,13 @@ net::URLRequest* request, GURL* new_url) { ascriber_->OnBeforeUrlRequest(request); - data_use_measurement_.OnBeforeURLRequest(request); + data_use_measurement_->OnBeforeURLRequest(request); } void DataUseNetworkDelegate::OnBeforeRedirectInternal( net::URLRequest* request, const GURL& new_location) { - data_use_measurement_.OnBeforeRedirect(*request, new_location); + data_use_measurement_->OnBeforeRedirect(*request, new_location); } void DataUseNetworkDelegate::OnHeadersReceivedInternal( @@ -45,28 +42,28 @@ const net::HttpResponseHeaders* original_response_headers, scoped_refptr<net::HttpResponseHeaders>* override_response_headers, GURL* allowed_unsafe_redirect_url) { - data_use_measurement_.OnHeadersReceived(request, original_response_headers); + data_use_measurement_->OnHeadersReceived(request, original_response_headers); } void DataUseNetworkDelegate::OnNetworkBytesReceivedInternal( net::URLRequest* request, int64_t bytes_received) { ascriber_->OnNetworkBytesReceived(request, bytes_received); - data_use_measurement_.OnNetworkBytesReceived(*request, bytes_received); + data_use_measurement_->OnNetworkBytesReceived(*request, bytes_received); } void DataUseNetworkDelegate::OnNetworkBytesSentInternal( net::URLRequest* request, int64_t bytes_sent) { ascriber_->OnNetworkBytesSent(request, bytes_sent); - data_use_measurement_.OnNetworkBytesSent(*request, bytes_sent); + data_use_measurement_->OnNetworkBytesSent(*request, bytes_sent); } void DataUseNetworkDelegate::OnCompletedInternal(net::URLRequest* request, bool started, int net_error) { ascriber_->OnUrlRequestCompleted(request, started); - data_use_measurement_.OnCompleted(*request, started); + data_use_measurement_->OnCompleted(*request, started); } void DataUseNetworkDelegate::OnURLRequestDestroyedInternal(
diff --git a/components/data_use_measurement/core/data_use_network_delegate.h b/components/data_use_measurement/core/data_use_network_delegate.h index 5a80d9aa..adf9366 100644 --- a/components/data_use_measurement/core/data_use_network_delegate.h +++ b/components/data_use_measurement/core/data_use_network_delegate.h
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "components/data_use_measurement/core/data_use_measurement.h" -#include "components/metrics/data_use_tracker.h" #include "net/base/completion_callback.h" #include "net/base/layered_network_delegate.h" @@ -32,8 +31,7 @@ DataUseNetworkDelegate( std::unique_ptr<net::NetworkDelegate> nested_network_delegate, DataUseAscriber* ascriber, - std::unique_ptr<URLRequestClassifier> url_request_classifier, - const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder); + std::unique_ptr<DataUseMeasurement> data_use_measurement); ~DataUseNetworkDelegate() override; @@ -66,7 +64,8 @@ DataUseAscriber* ascriber_; // Component to report data use UMA. - data_use_measurement::DataUseMeasurement data_use_measurement_; + std::unique_ptr<data_use_measurement::DataUseMeasurement> + data_use_measurement_; }; } // namespace data_use_measurement
diff --git a/components/data_use_measurement/core/data_use_network_delegate_unittest.cc b/components/data_use_measurement/core/data_use_network_delegate_unittest.cc index 077f0cf..07bc4dc8 100644 --- a/components/data_use_measurement/core/data_use_network_delegate_unittest.cc +++ b/components/data_use_measurement/core/data_use_network_delegate_unittest.cc
@@ -54,12 +54,29 @@ return nullptr; } + std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate( + std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate) override { + return nullptr; + } + std::unique_ptr<URLRequestClassifier> CreateURLRequestClassifier() const override { return nullptr; } }; +class TestDataUseMeasurement : public DataUseMeasurement { + public: + TestDataUseMeasurement( + std::unique_ptr<URLRequestClassifier> url_request_classifier, + DataUseAscriber* ascriber) + : DataUseMeasurement(std::move(url_request_classifier), ascriber) {} + + void UpdateDataUseToMetricsService(int64_t total_bytes, + bool is_cellular, + bool is_metrics_service_usage) override {} +}; + // static const void* const TestURLRequestClassifier::kUserDataKey = &TestURLRequestClassifier::kUserDataKey; @@ -108,7 +125,6 @@ request->SetUserData( data_use_measurement::DataUseUserData::kUserDataKey, std::make_unique<data_use_measurement::DataUseUserData>( - data_use_measurement::DataUseUserData::SUGGESTIONS, data_use_measurement::DataUseUserData::FOREGROUND)); } request->Start(); @@ -120,10 +136,12 @@ public: DataUseNetworkDelegateTest() : context_(true), - data_use_network_delegate_(std::make_unique<net::TestNetworkDelegate>(), - &test_data_use_ascriber_, - std::make_unique<TestURLRequestClassifier>(), - metrics::UpdateUsagePrefCallbackType()) { + data_use_network_delegate_( + std::make_unique<net::TestNetworkDelegate>(), + &test_data_use_ascriber_, + std::make_unique<TestDataUseMeasurement>( + std::make_unique<TestURLRequestClassifier>(), + &test_data_use_ascriber_)) { context_.set_client_socket_factory(&mock_socket_factory_); context_.set_network_delegate(&data_use_network_delegate_); context_.Init();
diff --git a/components/data_use_measurement/core/data_use_user_data.cc b/components/data_use_measurement/core/data_use_user_data.cc index ca3bb4f..9887faa 100644 --- a/components/data_use_measurement/core/data_use_user_data.cc +++ b/components/data_use_measurement/core/data_use_user_data.cc
@@ -30,10 +30,8 @@ } // namespace -DataUseUserData::DataUseUserData(ServiceName service_name, AppState app_state) - : service_name_(service_name), - app_state_(app_state), - content_type_(DataUseContentType::OTHER) {} +DataUseUserData::DataUseUserData(AppState app_state) + : app_state_(app_state), content_type_(DataUseContentType::OTHER) {} DataUseUserData::~DataUseUserData() {} @@ -44,105 +42,12 @@ // static std::unique_ptr<base::SupportsUserData::Data> DataUseUserData::Create( ServiceName service_name) { - return std::make_unique<DataUseUserData>(service_name, GetCurrentAppState()); -} - -// static -std::string DataUseUserData::GetServiceNameAsString(ServiceName service_name) { - switch (service_name) { - case SUGGESTIONS: - return "Suggestions"; - case NOT_TAGGED: - return "NotTagged"; - case TRANSLATE: - return "Translate"; - case SYNC: - return "Sync"; - case OMNIBOX: - return "Omnibox"; - case INVALIDATION: - return "Invalidation"; - case RAPPOR: - return "Rappor"; - case VARIATIONS: - return "Variations"; - case UMA: - return "UMA"; - case DOMAIN_RELIABILITY: - return "DomainReliability"; - case PROFILE_DOWNLOADER: - return "ProfileDownloader"; - case GOOGLE_URL_TRACKER: - return "GoogleURLTracker"; - case AUTOFILL: - return "Autofill"; - case POLICY: - return "Policy"; - case SPELL_CHECKER: - return "SpellChecker"; - case NTP_SNIPPETS_OBSOLETE: - return "NTPSnippetsObsolete"; - case SAFE_BROWSING: - return "SafeBrowsing"; - case DATA_REDUCTION_PROXY: - return "DataReductionProxy"; - case PRECACHE: - return "Precache"; - case NTP_TILES: - return "NTPTiles"; - case FEEDBACK_UPLOADER: - return "FeedbackUploader"; - case TRACING_UPLOADER: - return "TracingUploader"; - case DOM_DISTILLER: - return "DOMDistiller"; - case CLOUD_PRINT: - return "CloudPrint"; - case SEARCH_PROVIDER_LOGOS: - return "SearchProviderLogos"; - case UPDATE_CLIENT: - return "UpdateClient"; - case GCM_DRIVER: - return "GCMDriver"; - case WEB_HISTORY_SERVICE: - return "WebHistoryService"; - case NETWORK_TIME_TRACKER: - return "NetworkTimeTracker"; - case SUPERVISED_USER: - return "SupervisedUser"; - case IMAGE_FETCHER_UNTAGGED: - return "ImageFetcherUntagged"; - case GAIA: - return "GAIA"; - case CAPTIVE_PORTAL: - return "CaptivePortal"; - case WEB_RESOURCE_SERVICE: - return "WebResourceService"; - case SIGNIN: - return "Signin"; - case NTP_SNIPPETS_SUGGESTIONS: - return "NTPSnippetsSuggestions"; - case NTP_SNIPPETS_THUMBNAILS: - return "NTPSnippetsThumbnails"; - case DOODLE: - return "Doodle"; - case UKM: - return "UKM"; - case PAYMENTS: - return "Payments"; - case LARGE_ICON_SERVICE: - return "LargeIconService"; - case MACHINE_INTELLIGENCE: - return "MachineIntelligence"; - } - return "INVALID"; + return std::make_unique<DataUseUserData>(GetCurrentAppState()); } // static void DataUseUserData::AttachToFetcher(net::URLFetcher* fetcher, ServiceName service_name) { - fetcher->SetURLRequestUserData(kUserDataKey, - base::Bind(&Create, service_name)); } } // namespace data_use_measurement
diff --git a/components/data_use_measurement/core/data_use_user_data.h b/components/data_use_measurement/core/data_use_user_data.h index a6e110d..522f84b 100644 --- a/components/data_use_measurement/core/data_use_user_data.h +++ b/components/data_use_measurement/core/data_use_user_data.h
@@ -25,6 +25,8 @@ // Please keep them synced after any updates. Also add service name to // GetServiceNameAsString function and the same service name to // DataUse.Service.Types histogram suffixes in histograms.xml + // TODO(rajendrant): Remove this once all AttachToFetcher() callsites are + // removed. enum ServiceName { NOT_TAGGED, SUGGESTIONS, @@ -95,7 +97,7 @@ // platforms it is always FOREGROUND. enum AppState { UNKNOWN, BACKGROUND, FOREGROUND }; - DataUseUserData(ServiceName service_name, AppState app_state); + explicit DataUseUserData(AppState app_state); ~DataUseUserData() override; // Helper function to create DataUseUserData. @@ -107,11 +109,10 @@ // Services should use this function to attach their |service_name| to the // URLFetcher serving them. + // TODO(rajendrant): Remove this once all callsites are removed. static void AttachToFetcher(net::URLFetcher* fetcher, ServiceName service_name); - ServiceName service_name() const { return service_name_; } - AppState app_state() const { return app_state_; } void set_app_state(AppState app_state) { app_state_ = app_state; } @@ -126,8 +127,6 @@ static const void* const kUserDataKey; private: - const ServiceName service_name_; - // App state when network access was performed for the request previously. AppState app_state_;
diff --git a/components/domain_reliability/uploader.cc b/components/domain_reliability/uploader.cc index 1bda01b..1f109a5 100644 --- a/components/domain_reliability/uploader.cc +++ b/components/domain_reliability/uploader.cc
@@ -215,12 +215,6 @@ } // static -bool DomainReliabilityUploader::OriginatedFromDomainReliability( - const net::URLRequest& request) { - return request.GetUserData(UploadUserData::kUserDataKey) != nullptr; -} - -// static int DomainReliabilityUploader::GetURLRequestUploadDepth( const net::URLRequest& request) { UploadUserData* data = static_cast<UploadUserData*>(
diff --git a/components/domain_reliability/uploader.h b/components/domain_reliability/uploader.h index 90c9d1e13..51ff64c 100644 --- a/components/domain_reliability/uploader.h +++ b/components/domain_reliability/uploader.h
@@ -55,9 +55,6 @@ const scoped_refptr<net::URLRequestContextGetter>& url_request_context_getter); - // Returns true if the request originated from domain reliability uploader. - static bool OriginatedFromDomainReliability(const net::URLRequest& request); - // Uploads |report_json| to |upload_url| and calls |callback| when the upload // has either completed or failed. virtual void UploadReport(const std::string& report_json,
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc index 2f4d9d7..17a5d0f 100644 --- a/components/exo/client_controlled_shell_surface.cc +++ b/components/exo/client_controlled_shell_surface.cc
@@ -770,13 +770,7 @@ GetWindowState()->is_dragged() && !is_display_move_pending; - // Android PIP windows can be dismissed by swiping off the screen. Let them be - // positioned off-screen. Apart from swipe to dismiss, the PIP window will be - // kept on screen. - // TODO(edcourtney): This should be done as a client controlled move, not a - // special case. - if (set_bounds_locally || client_controlled_state_->set_bounds_locally() || - GetWindowState()->IsPip()) { + if (set_bounds_locally || client_controlled_state_->set_bounds_locally()) { // Convert from screen to display coordinates. gfx::Point origin = bounds.origin(); wm::ConvertPointFromScreen(window->parent(), &origin); @@ -881,8 +875,15 @@ } ash::wm::WindowState* window_state = GetWindowState(); - if (window_state->GetStateType() == pending_window_state_) + if (window_state->GetStateType() == pending_window_state_) { + // Animate PIP window movement unless it is being dragged. + if (window_state->IsPip() && !window_state->is_dragged()) { + client_controlled_state_->set_next_bounds_change_animation_type( + ash::wm::ClientControlledState::kAnimationAnimated); + } + return true; + } if (IsPinned(window_state)) { VLOG(1) << "State change was requested while pinned"; @@ -920,8 +921,12 @@ widget_->widget_delegate()->set_can_activate(true); } - client_controlled_state_->EnterNextState(window_state, pending_window_state_, - animation_type); + if (client_controlled_state_->EnterNextState(window_state, + pending_window_state_)) { + client_controlled_state_->set_next_bounds_change_animation_type( + animation_type); + } + return true; }
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index 0c32c268..a627f0a 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -47,6 +47,8 @@ #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_targeter.h" #include "ui/aura/window_tree_host.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor_extra/shadow.h" #include "ui/display/display.h" #include "ui/display/test/display_manager_test_api.h" @@ -1826,31 +1828,6 @@ EXPECT_TRUE(shell_surface->GetWidget()->CanActivate()); } -TEST_F(ClientControlledShellSurfaceTest, MovingPipWindowOffDisplayIsAllowed) { - UpdateDisplay("500x500"); - - gfx::Size buffer_size(256, 256); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface( - exo_test_helper()->CreateClientControlledShellSurface(surface.get())); - surface->Attach(buffer.get()); - surface->Commit(); - - // Use the PIP window state type. - shell_surface->SetPip(); - shell_surface->GetWidget()->Show(); - - // Set an off-screen geometry. - gfx::Rect bounds(-200, 0, 100, 100); - shell_surface->SetGeometry(bounds); - surface->Commit(); - - EXPECT_EQ(gfx::Rect(-200, 0, 100, 100), - shell_surface->GetWidget()->GetWindowBoundsInScreen()); -} - TEST_F(ClientControlledShellSurfaceDisplayTest, NoBoundsChangeEventInMinimized) { gfx::Size buffer_size(100, 100); @@ -1885,4 +1862,51 @@ ASSERT_EQ(1, bounds_change_count()); } +TEST_F(ClientControlledShellSurfaceTest, SetPipWindowBoundsAnimates) { + const gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface()); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + surface->Attach(buffer.get()); + surface->Commit(); + shell_surface->SetPip(); + surface->Commit(); + shell_surface->GetWidget()->Show(); + + ui::ScopedAnimationDurationScaleMode animation_scale_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + window->SetBounds(gfx::Rect(10, 10, 256, 256)); + EXPECT_EQ(gfx::Rect(10, 10, 256, 256), window->layer()->GetTargetBounds()); + EXPECT_EQ(gfx::Rect(0, 0, 256, 256), window->layer()->bounds()); +} + +TEST_F(ClientControlledShellSurfaceTest, PipWindowDragDoesNotAnimate) { + const gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface()); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + surface->Attach(buffer.get()); + surface->Commit(); + shell_surface->SetPip(); + surface->Commit(); + shell_surface->GetWidget()->Show(); + + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + ui::ScopedAnimationDurationScaleMode animation_scale_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + std::unique_ptr<ash::WindowResizer> resizer(ash::CreateWindowResizer( + window, gfx::Point(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_MOUSE)); + resizer->Drag(gfx::Point(10, 0), 0); + EXPECT_EQ(gfx::Rect(10, 0, 256, 256), window->layer()->GetTargetBounds()); + EXPECT_EQ(gfx::Rect(10, 0, 256, 256), window->layer()->bounds()); + resizer->CompleteDrag(); +} + } // namespace exo
diff --git a/components/feed/core/feed_logging_metrics.cc b/components/feed/core/feed_logging_metrics.cc index cd1bb4c..10ec926 100644 --- a/components/feed/core/feed_logging_metrics.cc +++ b/components/feed/core/feed_logging_metrics.cc
@@ -53,9 +53,6 @@ base::UmaHistogramExactLinear(histogram_name, bucket, kNumBuckets); UMA_HISTOGRAM_EXACT_LINEAR(kHistogramArticlesUsageTimeLocal, bucket, kNumBuckets); - - base::RecordAction( - base::UserMetricsAction("NewTabPage_ContentSuggestions_ArticlesUsage")); } int ToUMAScore(float score) { @@ -114,8 +111,7 @@ void FeedLoggingMetrics::OnSuggestionOpened(int position, base::Time publish_date, - float score, - WindowOpenDisposition disposition) { + float score) { UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.Opened", position, kMaxSuggestionsTotal); @@ -128,16 +124,17 @@ "NewTabPage.ContentSuggestions.OpenedScoreNormalized.Articles", ToUMAScore(score), 11); + RecordContentSuggestionsUsage(); +} + +void FeedLoggingMetrics::OnSuggestionWindowOpened( + WindowOpenDisposition disposition) { // We use WindowOpenDisposition::MAX_VALUE + 1 for |value_max| since MAX_VALUE // itself is a valid (and used) enum value. UMA_HISTOGRAM_EXACT_LINEAR( "NewTabPage.ContentSuggestions.OpenDisposition.Articles", static_cast<int>(disposition), static_cast<int>(WindowOpenDisposition::MAX_VALUE) + 1); - - RecordContentSuggestionsUsage(); - - base::RecordAction(base::UserMetricsAction("Suggestions.Content.Opened")); } void FeedLoggingMetrics::OnSuggestionMenuOpened(int position, @@ -168,6 +165,12 @@ "NewTabPage.ContentSuggestions.VisitDuration.Articles", visit_time); } +void FeedLoggingMetrics::OnSuggestionOfflinePageVisited( + base::TimeDelta visit_time) { + base::UmaHistogramLongTimes( + "NewTabPage.ContentSuggestions.VisitDuration.Downloads", visit_time); +} + void FeedLoggingMetrics::OnMoreButtonShown(int position) { // The "more" card can appear in addition to the actual suggestions, so add // one extra bucket to this histogram.
diff --git a/components/feed/core/feed_logging_metrics.h b/components/feed/core/feed_logging_metrics.h index b714aed2..0033b55 100644 --- a/components/feed/core/feed_logging_metrics.h +++ b/components/feed/core/feed_logging_metrics.h
@@ -5,6 +5,9 @@ #ifndef COMPONENTS_FEED_CORE_FEED_LOGGING_METRICS_H_ #define COMPONENTS_FEED_CORE_FEED_LOGGING_METRICS_H_ +#include <memory> +#include <utility> + #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -43,10 +46,9 @@ float score, base::Time fetch_date); - void OnSuggestionOpened(int position, - base::Time publish_date, - float score, - WindowOpenDisposition disposition); + void OnSuggestionOpened(int position, base::Time publish_date, float score); + + void OnSuggestionWindowOpened(WindowOpenDisposition disposition); void OnSuggestionMenuOpened(int position, base::Time publish_date, @@ -56,6 +58,8 @@ void OnSuggestionArticleVisited(base::TimeDelta visit_time); + void OnSuggestionOfflinePageVisited(base::TimeDelta visit_time); + // Should only be called once per NTP for each "more" button. void OnMoreButtonShown(int position);
diff --git a/components/feed/core/feed_logging_metrics_unittest.cc b/components/feed/core/feed_logging_metrics_unittest.cc index 2b37250..cf8c7f6 100644 --- a/components/feed/core/feed_logging_metrics_unittest.cc +++ b/components/feed/core/feed_logging_metrics_unittest.cc
@@ -96,20 +96,20 @@ ElementsAre(base::Bucket(/*min=*/10, /*count=*/1))); } -TEST_F(FeedLoggingMetricsTest, ShouldLogPrefetchedSuggestionsWhenOpened) { +TEST_F(FeedLoggingMetricsTest, ShouldLogOnSuggestionOpened) { base::HistogramTester histogram_tester; feed_logging_metrics()->OnSuggestionOpened( /*position=*/11, base::Time::Now(), - /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB); + /*score=*/1.0f); feed_logging_metrics()->OnSuggestionOpened( /*position=*/13, base::Time::Now(), - /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB); + /*score=*/1.0f); feed_logging_metrics()->OnSuggestionOpened( /*position=*/15, base::Time::Now(), - /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB); + /*score=*/1.0f); feed_logging_metrics()->OnSuggestionOpened( /*position=*/23, base::Time::Now(), - /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB); + /*score=*/1.0f); EXPECT_THAT( histogram_tester.GetAllSamples("NewTabPage.ContentSuggestions.Opened"), @@ -119,6 +119,25 @@ base::Bucket(/*min=*/23, /*count=*/1))); } +TEST_F(FeedLoggingMetricsTest, ShouldLogOnSuggestionWindowOpened) { + base::HistogramTester histogram_tester; + feed_logging_metrics()->OnSuggestionWindowOpened( + WindowOpenDisposition::CURRENT_TAB); + feed_logging_metrics()->OnSuggestionWindowOpened( + WindowOpenDisposition::CURRENT_TAB); + feed_logging_metrics()->OnSuggestionWindowOpened( + WindowOpenDisposition::CURRENT_TAB); + feed_logging_metrics()->OnSuggestionWindowOpened( + WindowOpenDisposition::CURRENT_TAB); + + EXPECT_THAT(histogram_tester.GetAllSamples( + "NewTabPage.ContentSuggestions.OpenDisposition.Articles"), + ElementsAre(base::Bucket( + /*WindowOpenDisposition::CURRENT_TAB=*/static_cast<int>( + WindowOpenDisposition::CURRENT_TAB), + /*count=*/4))); +} + TEST_F(FeedLoggingMetricsTest, ShouldLogOnSuggestionDismissedIfVisited) { base::HistogramTester histogram_tester; feed_logging_metrics()->OnSuggestionDismissed(/*position=*/10, VISITED_URL);
diff --git a/components/invalidation/impl/BUILD.gn b/components/invalidation/impl/BUILD.gn index 5da2b03..32b90362 100644 --- a/components/invalidation/impl/BUILD.gn +++ b/components/invalidation/impl/BUILD.gn
@@ -25,8 +25,6 @@ "invalidator.h", "invalidator_registrar.cc", "invalidator_registrar.h", - "invalidator_registrar_with_memory.cc", - "invalidator_registrar_with_memory.h", "invalidator_storage.cc", "invalidator_storage.h", "mock_ack_handler.cc",
diff --git a/components/invalidation/impl/fcm_fake_invalidator.cc b/components/invalidation/impl/fcm_fake_invalidator.cc index 63d6fc7..6e99a0b 100644 --- a/components/invalidation/impl/fcm_fake_invalidator.cc +++ b/components/invalidation/impl/fcm_fake_invalidator.cc
@@ -16,7 +16,7 @@ bool FCMFakeInvalidator::IsHandlerRegistered( InvalidationHandler* handler) const { - return registrar_.IsHandlerRegistered(handler); + return registrar_.IsHandlerRegisteredForTest(handler); } ObjectIdSet FCMFakeInvalidator::GetRegisteredIds(
diff --git a/components/invalidation/impl/fcm_invalidation_listener.cc b/components/invalidation/impl/fcm_invalidation_listener.cc index a36b663..dc466a01 100644 --- a/components/invalidation/impl/fcm_invalidation_listener.cc +++ b/components/invalidation/impl/fcm_invalidation_listener.cc
@@ -52,9 +52,11 @@ } void FCMInvalidationListener::UpdateRegisteredTopics(const TopicSet& topics) { - ids_update_requested_ = true; registered_topics_ = topics; - DoRegistrationUpdate(); + if (ticl_state_ == INVALIDATIONS_ENABLED && + per_user_topic_registration_manager_ && !token_.empty()) { + DoRegistrationUpdate(); + } } void FCMInvalidationListener::Ready(InvalidationClient* client) { @@ -139,11 +141,6 @@ } void FCMInvalidationListener::DoRegistrationUpdate() { - if (ticl_state_ != INVALIDATIONS_ENABLED || - !per_user_topic_registration_manager_ || token_.empty() || - !ids_update_requested_) { - return; - } per_user_topic_registration_manager_->UpdateRegisteredTopics( registered_topics_, token_);
diff --git a/components/invalidation/impl/fcm_invalidation_listener.h b/components/invalidation/impl/fcm_invalidation_listener.h index 1ae08b4..e8febad0 100644 --- a/components/invalidation/impl/fcm_invalidation_listener.h +++ b/components/invalidation/impl/fcm_invalidation_listener.h
@@ -129,18 +129,13 @@ // Stored to pass to |per_user_topic_registration_manager_| on start. TopicSet registered_topics_; - // The states of the ticl and FCM channel. + // The states of the ticl and FCN channel. InvalidatorState ticl_state_; InvalidatorState fcm_network_state_; std::unique_ptr<PerUserTopicRegistrationManager> per_user_topic_registration_manager_; std::string token_; - // Prevents call to DoRegistrationUpdate in cases when - // UpdateRegisteredTopics wasn't called. For example, InformTokenRecieved - // can trigger DoRegistrationUpdate before any invalidation handler has - // requested registration for topics. - bool ids_update_requested_ = false; base::WeakPtrFactory<FCMInvalidationListener> weak_factory_;
diff --git a/components/invalidation/impl/fcm_invalidation_service.cc b/components/invalidation/impl/fcm_invalidation_service.cc index 78236363..cbf8435e 100644 --- a/components/invalidation/impl/fcm_invalidation_service.cc +++ b/components/invalidation/impl/fcm_invalidation_service.cc
@@ -29,14 +29,12 @@ PrefService* pref_service, const syncer::ParseJSONCallback& parse_json, network::mojom::URLLoaderFactory* loader_factory) - : invalidator_registrar_(pref_service), - gcm_driver_(gcm_driver), + : gcm_driver_(gcm_driver), instance_id_driver_(instance_id_driver), identity_provider_(identity_provider), pref_service_(pref_service), parse_json_(parse_json), - loader_factory_(loader_factory), - update_was_requested_(false) {} + loader_factory_(loader_factory) {} FCMInvalidationService::~FCMInvalidationService() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -63,7 +61,8 @@ invalidator_.reset(invalidator); invalidator_->RegisterHandler(this); - DoUpdateRegisteredIdsIfNeeded(); + CHECK(invalidator_->UpdateRegisteredIds( + this, invalidator_registrar_.GetAllRegisteredIds())); } void FCMInvalidationService::RegisterInvalidationHandler( @@ -78,12 +77,14 @@ syncer::InvalidationHandler* handler, const syncer::ObjectIdSet& ids) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - update_was_requested_ = true; DVLOG(2) << "Registering ids: " << ids.size(); syncer::TopicSet topics = ConvertIdsToTopics(ids); if (!invalidator_registrar_.UpdateRegisteredTopics(handler, topics)) return false; - DoUpdateRegisteredIdsIfNeeded(); + if (invalidator_) { + CHECK(invalidator_->UpdateRegisteredIds( + this, invalidator_registrar_.GetAllRegisteredIds())); + } logger_.OnUpdateTopics(invalidator_registrar_.GetSanitizedHandlersIdsMap()); return true; } @@ -93,6 +94,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(2) << "Unregistering"; invalidator_registrar_.UnregisterHandler(handler); + if (invalidator_) { + CHECK(invalidator_->UpdateRegisteredIds( + this, invalidator_registrar_.GetAllRegisteredIds())); + } logger_.OnUnregistration(handler->GetOwnerName()); } @@ -185,8 +190,10 @@ invalidator_ = std::make_unique<syncer::FCMInvalidator>( std::move(network), identity_provider_, pref_service_, loader_factory_, parse_json_); + invalidator_->RegisterHandler(this); - DoUpdateRegisteredIdsIfNeeded(); + CHECK(invalidator_->UpdateRegisteredIds( + this, invalidator_registrar_.GetAllRegisteredIds())); } void FCMInvalidationService::StopInvalidator() { @@ -226,12 +233,4 @@ // TODO(meandory): report metric in case of unsucesfull deletion. } -void FCMInvalidationService::DoUpdateRegisteredIdsIfNeeded() { - if (!invalidator_ || !update_was_requested_) - return; - auto registered_ids = invalidator_registrar_.GetAllRegisteredIds(); - CHECK(invalidator_->UpdateRegisteredIds(this, registered_ids)); - update_was_requested_ = false; -} - } // namespace invalidation
diff --git a/components/invalidation/impl/fcm_invalidation_service.h b/components/invalidation/impl/fcm_invalidation_service.h index 65b1314..67dcb15 100644 --- a/components/invalidation/impl/fcm_invalidation_service.h +++ b/components/invalidation/impl/fcm_invalidation_service.h
@@ -9,7 +9,7 @@ #include "base/timer/timer.h" #include "components/gcm_driver/instance_id/instance_id.h" #include "components/invalidation/impl/invalidation_logger.h" -#include "components/invalidation/impl/invalidator_registrar_with_memory.h" +#include "components/invalidation/impl/invalidator_registrar.h" #include "components/invalidation/public/identity_provider.h" #include "components/invalidation/public/invalidation_handler.h" #include "components/invalidation/public/invalidation_service.h" @@ -93,9 +93,7 @@ void OnInstanceIdRecieved(const std::string& id); void OnDeleteIDCompleted(instance_id::InstanceID::Result); - void DoUpdateRegisteredIdsIfNeeded(); - - syncer::InvalidatorRegistrarWithMemory invalidator_registrar_; + syncer::InvalidatorRegistrar invalidator_registrar_; std::unique_ptr<syncer::Invalidator> invalidator_; // The invalidation logger object we use to record state changes @@ -110,7 +108,6 @@ PrefService* pref_service_; syncer::ParseJSONCallback parse_json_; network::mojom::URLLoaderFactory* loader_factory_; - bool update_was_requested_ = false; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/components/invalidation/impl/fcm_invalidation_service_unittest.cc b/components/invalidation/impl/fcm_invalidation_service_unittest.cc index edcf1abd..6cb50c9 100644 --- a/components/invalidation/impl/fcm_invalidation_service_unittest.cc +++ b/components/invalidation/impl/fcm_invalidation_service_unittest.cc
@@ -90,8 +90,6 @@ pref_service_.registry()->RegisterStringPref( prefs::kFCMInvalidationClientIDCache, /*default_value=*/std::string()); - syncer::InvalidatorRegistrarWithMemory::RegisterProfilePrefs( - pref_service_.registry()); } ~FCMInvalidationServiceTestDelegate() {}
diff --git a/components/invalidation/impl/invalidator_registrar.cc b/components/invalidation/impl/invalidator_registrar.cc index 502c7a60..45bc920 100644 --- a/components/invalidation/impl/invalidator_registrar.cc +++ b/components/invalidation/impl/invalidator_registrar.cc
@@ -134,7 +134,7 @@ return clean_handlers_to_topics; } -bool InvalidatorRegistrar::IsHandlerRegistered( +bool InvalidatorRegistrar::IsHandlerRegisteredForTest( const InvalidationHandler* handler) const { DCHECK(thread_checker_.CalledOnValidThread()); return handlers_.HasObserver(handler);
diff --git a/components/invalidation/impl/invalidator_registrar.h b/components/invalidation/impl/invalidator_registrar.h index 5e816f26..d1f28b7 100644 --- a/components/invalidation/impl/invalidator_registrar.h +++ b/components/invalidation/impl/invalidator_registrar.h
@@ -33,24 +33,23 @@ // and it must already be registered. void RegisterHandler(InvalidationHandler* handler); + // Updates the set of topics associated with |handler|. |handler| must + // not be NULL, and must already be registered. A topic must be registered + // for at most one handler. If topic is already registered function returns + // false. + bool UpdateRegisteredTopics(InvalidationHandler* handler, + const TopicSet& topics) WARN_UNUSED_RESULT; + // Stops sending notifications to |handler|. |handler| must not be NULL, and // it must already be registered. Note that this doesn't unregister the IDs // associated with |handler|. void UnregisterHandler(InvalidationHandler* handler); - // Updates the set of topics associated with |handler|. |handler| must - // not be NULL, and must already be registered. A topic must be registered - // for at most one handler. If topic is already registered function returns - // false. - virtual bool UpdateRegisteredTopics(InvalidationHandler* handler, - const TopicSet& topics) - WARN_UNUSED_RESULT; - - virtual TopicSet GetRegisteredTopics(InvalidationHandler* handler) const; + TopicSet GetRegisteredTopics(InvalidationHandler* handler) const; // Returns the set of all IDs that are registered to some handler (even // handlers that have been unregistered). - virtual TopicSet GetAllRegisteredIds() const; + TopicSet GetAllRegisteredIds() const; // Sorts incoming invalidations into a bucket for each handler and then // dispatches the batched invalidations to the corresponding handler. @@ -74,7 +73,7 @@ // to display every registered handlers and its objectsIds. std::map<std::string, TopicSet> GetSanitizedHandlersIdsMap(); - bool IsHandlerRegistered(const InvalidationHandler* handler) const; + bool IsHandlerRegisteredForTest(const InvalidationHandler* handler) const; // Needed for death tests. void DetachFromThreadForTest();
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.cc b/components/invalidation/impl/invalidator_registrar_with_memory.cc deleted file mode 100644 index 3bd24df5..0000000 --- a/components/invalidation/impl/invalidator_registrar_with_memory.cc +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/invalidation/impl/invalidator_registrar_with_memory.h" - -#include <cstddef> -#include <iterator> -#include <utility> - -#include "base/logging.h" -#include "components/invalidation/public/object_id_invalidation_map.h" -#include "components/invalidation/public/topic_invalidation_map.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/scoped_user_pref_update.h" - -namespace syncer { - -namespace { - -const char kTopicsToHandler[] = "invalidation.topics_to_handler"; - -} // namespace - -// static -void InvalidatorRegistrarWithMemory::RegisterProfilePrefs( - PrefRegistrySimple* registry) { - registry->RegisterDictionaryPref(kTopicsToHandler); -} - -InvalidatorRegistrarWithMemory::InvalidatorRegistrarWithMemory( - PrefService* local_state) - : InvalidatorRegistrar(), local_state_(local_state) { - const base::Value* pref_data = local_state_->Get(kTopicsToHandler); - for (const auto& it : pref_data->DictItems()) { - Topic topic = it.first; - std::string handler_name; - it.second.GetAsString(&handler_name); - handler_name_to_topics_map_[handler_name].insert(topic); - } -} - -InvalidatorRegistrarWithMemory::~InvalidatorRegistrarWithMemory() {} - -bool InvalidatorRegistrarWithMemory::UpdateRegisteredTopics( - InvalidationHandler* handler, - const TopicSet& topics) { - TopicSet old_topics = GetRegisteredTopics(handler); - bool success = InvalidatorRegistrar::UpdateRegisteredTopics(handler, topics); - if (!InvalidatorRegistrar::IsHandlerRegistered(handler)) { - return success; - } - - TopicSet to_unregister; - DictionaryPrefUpdate update(local_state_, kTopicsToHandler); - std::set_difference(old_topics.begin(), old_topics.end(), topics.begin(), - topics.end(), - std::inserter(to_unregister, to_unregister.begin())); - if (!to_unregister.empty()) { - for (const auto& topic : to_unregister) { - update->RemoveKey(topic); - handler_name_to_topics_map_[handler->GetOwnerName()].erase(topic); - } - } - - for (const auto& topic : topics) { - handler_name_to_topics_map_[handler->GetOwnerName()].insert(topic); - update->SetKey(topic, base::Value(handler->GetOwnerName())); - } - return success; -} - -TopicSet InvalidatorRegistrarWithMemory::GetAllRegisteredIds() const { - TopicSet registered_topics; - for (const auto& handler_to_topic : handler_name_to_topics_map_) { - registered_topics.insert(handler_to_topic.second.begin(), - handler_to_topic.second.end()); - } - return registered_topics; -} - -} // namespace syncer
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.h b/components/invalidation/impl/invalidator_registrar_with_memory.h deleted file mode 100644 index a00e421f..0000000 --- a/components/invalidation/impl/invalidator_registrar_with_memory.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_REGISTRAR_WITH_MEMORY_H_ -#define COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_REGISTRAR_WITH_MEMORY_H_ - -#include <map> - -#include "base/macros.h" -#include "base/observer_list.h" -#include "base/threading/thread_checker.h" -#include "components/invalidation/impl/invalidator_registrar.h" -#include "components/invalidation/public/invalidation_export.h" -#include "components/invalidation/public/invalidation_handler.h" -#include "components/invalidation/public/invalidation_util.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" - -class PrefRegistrySimple; -class PrefService; - -namespace syncer { - -using HandlerNameTopicsMap = std::map<std::string, TopicSet>; - -// A helper class for implementations of the Invalidator interface. It helps -// keep track of registered handlers and which object ID registrations are -// associated with which handlers, so implementors can just reuse the logic -// here to dispatch invalidations and other interesting notifications. -class INVALIDATION_EXPORT InvalidatorRegistrarWithMemory - : public InvalidatorRegistrar { - public: - InvalidatorRegistrarWithMemory(PrefService* local_state); - - // It is an error to have registered handlers on destruction. - ~InvalidatorRegistrarWithMemory(); - - static void RegisterProfilePrefs(PrefRegistrySimple* registry); - - // Updates the set of topics associated with |handler|. |handler| must - // not be NULL, and must already be registered. A topic must be registered - // for at most one handler. If topic is already registered function returns - // false. - bool UpdateRegisteredTopics(InvalidationHandler* handler, - const TopicSet& topics) override - WARN_UNUSED_RESULT; - - // void UnregisterHandler(InvalidationHandler* handler) override; - // void RegisterHandler(InvalidationHandler* handler) override; - - // Returns the set of all IDs that are registered to some handler (even - // handlers that have been unregistered). - TopicSet GetAllRegisteredIds() const override; - - private: - std::unordered_map<std::string, InvalidationHandler*> - handler_name_to_handler_; - HandlerNameTopicsMap handler_name_to_topics_map_; - PrefService* local_state_; - - DISALLOW_COPY_AND_ASSIGN(InvalidatorRegistrarWithMemory); -}; - -} // namespace syncer - -#endif // COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_REGISTRAR_WITH_MEMORY_H_
diff --git a/components/metrics/data_use_tracker.cc b/components/metrics/data_use_tracker.cc index 61be02f..0cb37b0 100644 --- a/components/metrics/data_use_tracker.cc +++ b/components/metrics/data_use_tracker.cc
@@ -45,9 +45,9 @@ registry->RegisterDictionaryPref(metrics::prefs::kUmaCellDataUse); } -void DataUseTracker::UpdateMetricsUsagePrefs(const std::string& service_name, - int message_size, - bool is_cellular) { +void DataUseTracker::UpdateMetricsUsagePrefs(int message_size, + bool is_cellular, + bool is_metrics_service_usage) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!is_cellular) @@ -55,7 +55,7 @@ UpdateUsagePref(prefs::kUserCellDataUse, message_size); // TODO(holte): Consider adding seperate tracking for UKM. - if (service_name == "UMA" || service_name == "UKM") + if (is_metrics_service_usage) UpdateUsagePref(prefs::kUmaCellDataUse, message_size); }
diff --git a/components/metrics/data_use_tracker.h b/components/metrics/data_use_tracker.h index 104223e..457193e 100644 --- a/components/metrics/data_use_tracker.h +++ b/components/metrics/data_use_tracker.h
@@ -36,9 +36,9 @@ static void RegisterPrefs(PrefRegistrySimple* registry); // Updates data usage tracking prefs with the specified values. - void UpdateMetricsUsagePrefs(const std::string& service_name, - int message_size, - bool is_cellular); + void UpdateMetricsUsagePrefs(int message_size, + bool is_cellular, + bool is_metrics_service_usage); // Returns whether a log with provided |log_bytes| can be uploaded according // to data use ratio and UMA quota provided by variations.
diff --git a/components/metrics/data_use_tracker_unittest.cc b/components/metrics/data_use_tracker_unittest.cc index a271b5d..b571dc4f2 100644 --- a/components/metrics/data_use_tracker_unittest.cc +++ b/components/metrics/data_use_tracker_unittest.cc
@@ -106,7 +106,7 @@ int user_pref_value = 0; int uma_pref_value = 0; - data_use_tracker.UpdateMetricsUsagePrefs("", 2 * 100, true); + data_use_tracker.UpdateMetricsUsagePrefs(2 * 100, true, false); local_state.GetDictionary(prefs::kUserCellDataUse) ->GetInteger(kTodayStr, &user_pref_value); EXPECT_EQ(2 * 100, user_pref_value); @@ -114,7 +114,7 @@ ->GetInteger(kTodayStr, &uma_pref_value); EXPECT_EQ(0, uma_pref_value); - data_use_tracker.UpdateMetricsUsagePrefs("UMA", 100, true); + data_use_tracker.UpdateMetricsUsagePrefs(100, true, true); local_state.GetDictionary(prefs::kUserCellDataUse) ->GetInteger(kTodayStr, &user_pref_value); EXPECT_EQ(3 * 100, user_pref_value);
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index bfa17fe..01ed8be1e 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc
@@ -452,12 +452,12 @@ log_store()->StoreLog(log, MetricsLog::ONGOING_LOG); } -void MetricsService::UpdateMetricsUsagePrefs(const std::string& service_name, - int message_size, - bool is_cellular) { +void MetricsService::UpdateMetricsUsagePrefs(int message_size, + bool is_cellular, + bool is_metrics_service_usage) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - reporting_service_.UpdateMetricsUsagePrefs(service_name, message_size, - is_cellular); + reporting_service_.UpdateMetricsUsagePrefs(message_size, is_cellular, + is_metrics_service_usage); } //------------------------------------------------------------------------------
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h index 6471314..8a26561b 100644 --- a/components/metrics/metrics_service.h +++ b/components/metrics/metrics_service.h
@@ -171,9 +171,9 @@ void PushExternalLog(const std::string& log); // Updates data usage tracking prefs with the specified values. - void UpdateMetricsUsagePrefs(const std::string& service_name, - int message_size, - bool is_cellular); + void UpdateMetricsUsagePrefs(int message_size, + bool is_cellular, + bool is_metrics_service_usage); variations::SyntheticTrialRegistry* synthetic_trial_registry() { return &synthetic_trial_registry_;
diff --git a/components/metrics/reporting_service.cc b/components/metrics/reporting_service.cc index 6382804..9e18f4d 100644 --- a/components/metrics/reporting_service.cc +++ b/components/metrics/reporting_service.cc
@@ -81,13 +81,13 @@ return reporting_active_; } -void ReportingService::UpdateMetricsUsagePrefs(const std::string& service_name, - int message_size, - bool is_cellular) { +void ReportingService::UpdateMetricsUsagePrefs(int message_size, + bool is_cellular, + bool is_metrics_service_usage) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (data_use_tracker_) { - data_use_tracker_->UpdateMetricsUsagePrefs(service_name, message_size, - is_cellular); + data_use_tracker_->UpdateMetricsUsagePrefs(message_size, is_cellular, + is_metrics_service_usage); } }
diff --git a/components/metrics/reporting_service.h b/components/metrics/reporting_service.h index d724430..a913d4e5 100644 --- a/components/metrics/reporting_service.h +++ b/components/metrics/reporting_service.h
@@ -67,9 +67,9 @@ bool reporting_active() const; // Updates data usage tracking prefs with the specified values. - void UpdateMetricsUsagePrefs(const std::string& service_name, - int message_size, - bool is_cellular); + void UpdateMetricsUsagePrefs(int message_size, + bool is_cellular, + bool is_metrics_service_usage); // Registers local state prefs used by this class. This should only be called // once.
diff --git a/components/password_manager/ios/BUILD.gn b/components/password_manager/ios/BUILD.gn index c10662a..2254462 100644 --- a/components/password_manager/ios/BUILD.gn +++ b/components/password_manager/ios/BUILD.gn
@@ -23,8 +23,10 @@ "account_select_fill_data.h", "js_password_manager.h", "js_password_manager.mm", - "password_controller_helper.h", - "password_controller_helper.mm", + "password_form_helper.h", + "password_form_helper.mm", + "password_suggestion_helper.h", + "password_suggestion_helper.mm", ] } @@ -48,7 +50,7 @@ testonly = true sources = [ "account_select_fill_data_unittest.cc", - "password_controller_helper_unittest.mm", + "password_form_helper_unittest.mm", ] deps = [ ":ios",
diff --git a/components/password_manager/ios/password_controller_helper.h b/components/password_manager/ios/password_form_helper.h similarity index 78% rename from components/password_manager/ios/password_controller_helper.h rename to components/password_manager/ios/password_form_helper.h index 781feb7f..6e18d56 100644 --- a/components/password_manager/ios/password_controller_helper.h +++ b/components/password_manager/ios/password_form_helper.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_CONTROLLER_HELPER_H_ -#define COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_CONTROLLER_HELPER_H_ +#ifndef COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_FORM_HELPER_H_ +#define COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_FORM_HELPER_H_ #import <Foundation/Foundation.h> @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @class JsPasswordManager; -@class PasswordControllerHelper; +@class PasswordFormHelper; namespace autofill { struct PasswordForm; @@ -33,18 +33,17 @@ class WebState; } // namespace web -// A protocol implemented by a delegate of PasswordControllerHelper. -@protocol PasswordControllerHelperDelegate +// A protocol implemented by a delegate of PasswordFormHelper. +@protocol PasswordFormHelperDelegate // Called when the password form is submitted. -- (void)helper:(PasswordControllerHelper*)helper - didSubmitForm:(const autofill::PasswordForm&)form - inMainFrame:(BOOL)inMainFrame; +- (void)formHelper:(PasswordFormHelper*)formHelper + didSubmitForm:(const autofill::PasswordForm&)form + inMainFrame:(BOOL)inMainFrame; @end -// Handles common logic of password controller for both ios/chrome and -// ios/web_view. -// TODO(crbug.com/865114): Rename to PasswordFormHelper. -@interface PasswordControllerHelper +// Handles common form processing logic of password controller for both +// ios/chrome and ios/web_view. +@interface PasswordFormHelper : NSObject<FormActivityObserver, CRWWebStateObserver> // The JsPasswordManager processing password form via javascript. @@ -82,8 +81,9 @@ // Creates a instance with the given WebState, observer and delegate. - (instancetype)initWithWebState:(web::WebState*)webState - delegate:(nullable id<PasswordControllerHelperDelegate>) - delegate NS_DESIGNATED_INITIALIZER; + delegate: + (nullable id<PasswordFormHelperDelegate>)delegate + NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @@ -91,4 +91,4 @@ NS_ASSUME_NONNULL_END -#endif // COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_CONTROLLER_HELPER_H_ +#endif // COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_FORM_HELPER_H_
diff --git a/components/password_manager/ios/password_controller_helper.mm b/components/password_manager/ios/password_form_helper.mm similarity index 93% rename from components/password_manager/ios/password_controller_helper.mm rename to components/password_manager/ios/password_form_helper.mm index 691653e7d..1a0f1754 100644 --- a/components/password_manager/ios/password_controller_helper.mm +++ b/components/password_manager/ios/password_form_helper.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "components/password_manager/ios/password_controller_helper.h" +#import "components/password_manager/ios/password_form_helper.h" #include <stddef.h> @@ -48,9 +48,9 @@ constexpr char kCommandPrefix[] = "passwordForm"; } // namespace -@interface PasswordControllerHelper () +@interface PasswordFormHelper () -@property(nonatomic, weak) id<PasswordControllerHelperDelegate> delegate; +@property(nonatomic, weak) id<PasswordFormHelperDelegate> delegate; // Handler for injected JavaScript callbacks. - (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand; @@ -80,14 +80,14 @@ @end // Category for test only. -@interface PasswordControllerHelper (Testing) +@interface PasswordFormHelper (Testing) // Replaces JsPasswordManager for test. - (void)setJsPasswordManager:(JsPasswordManager*)jsPasswordManager; @end -@implementation PasswordControllerHelper { +@implementation PasswordFormHelper { // The WebState this instance is observing. Will be null after // -webStateDestroyed: has been called. web::WebState* _webState; @@ -112,8 +112,7 @@ #pragma mark - Initialization - (instancetype)initWithWebState:(web::WebState*)webState - delegate: - (id<PasswordControllerHelperDelegate>)delegate { + delegate:(id<PasswordFormHelperDelegate>)delegate { self = [super init]; if (self) { DCHECK(webState); @@ -127,7 +126,7 @@ _jsPasswordManager = [[JsPasswordManager alloc] initWithReceiver:_webState->GetJSInjectionReceiver()]; - __weak PasswordControllerHelper* weakSelf = self; + __weak PasswordFormHelper* weakSelf = self; auto callback = base::BindRepeating( ^bool(const base::DictionaryValue& JSON, const GURL& originURL, bool interacting, bool isMainFrame, web::WebFrame* senderFrame) { @@ -181,20 +180,20 @@ // origin. return; } - __weak PasswordControllerHelper* weakSelf = self; + __weak PasswordFormHelper* weakSelf = self; // This code is racing against the new page loading and will not get the // password form data if the page has changed. In most cases this code wins // the race. // TODO(crbug.com/418827): Fix this by passing in more data from the JS side. id completionHandler = ^(BOOL found, const autofill::PasswordForm& form) { - PasswordControllerHelper* strongSelf = weakSelf; - id<PasswordControllerHelperDelegate> strongDelegate = strongSelf.delegate; + PasswordFormHelper* strongSelf = weakSelf; + id<PasswordFormHelperDelegate> strongDelegate = strongSelf.delegate; if (!strongSelf || !strongSelf->_webState || !strongDelegate) { return; } - [strongDelegate helper:strongSelf - didSubmitForm:form - inMainFrame:formInMainFrame]; + [strongDelegate formHelper:strongSelf + didSubmitForm:form + inMainFrame:formInMainFrame]; }; // TODO(crbug.com/418827): Use |formData| instead of extracting form again. [self extractSubmittedPasswordForm:formName @@ -231,7 +230,7 @@ } if (_webState && self.delegate) { - [self.delegate helper:self didSubmitForm:*form inMainFrame:YES]; + [self.delegate formHelper:self didSubmitForm:*form inMainFrame:YES]; return YES; } @@ -343,7 +342,7 @@ return; } - __weak PasswordControllerHelper* weakSelf = self; + __weak PasswordFormHelper* weakSelf = self; [self.jsPasswordManager findPasswordFormsWithCompletionHandler:^( NSString* jsonString) { std::vector<autofill::PasswordForm> forms; @@ -386,10 +385,10 @@ password:(NSString*)password completionHandler: (nullable void (^)(BOOL))completionHandler { - __weak PasswordControllerHelper* weakSelf = self; + __weak PasswordFormHelper* weakSelf = self; [self findPasswordFormsWithCompletionHandler:^( const std::vector<autofill::PasswordForm>& forms) { - PasswordControllerHelper* strongSelf = weakSelf; + PasswordFormHelper* strongSelf = weakSelf; for (const auto& form : forms) { autofill::PasswordFormFillData formData; std::map<base::string16, const autofill::PasswordForm*> matches;
diff --git a/components/password_manager/ios/password_controller_helper_unittest.mm b/components/password_manager/ios/password_form_helper_unittest.mm similarity index 95% rename from components/password_manager/ios/password_controller_helper_unittest.mm rename to components/password_manager/ios/password_form_helper_unittest.mm index eaa6d895..cec663f 100644 --- a/components/password_manager/ios/password_controller_helper_unittest.mm +++ b/components/password_manager/ios/password_form_helper_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "components/password_manager/ios/password_controller_helper.h" +#import "components/password_manager/ios/password_form_helper.h" #include <stddef.h> @@ -16,7 +16,7 @@ #include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "components/password_manager/ios/account_select_fill_data.h" #import "components/password_manager/ios/js_password_manager.h" -#import "components/password_manager/ios/password_controller_helper.h" +#import "components/password_manager/ios/password_form_helper.h" #include "components/password_manager/ios/test_helpers.h" #include "ios/web/public/test/fakes/test_web_client.h" #import "ios/web/public/test/web_test_with_web_state.h" @@ -38,7 +38,7 @@ using test_helpers::SetPasswordFormFillData; using test_helpers::SetFillData; -@interface PasswordControllerHelper (Testing) +@interface PasswordFormHelper (Testing) // Provides access to the method below for testing with mocks. - (void)extractSubmittedPasswordForm:(const std::string&)formName @@ -126,17 +126,17 @@ } }; -class PasswordControllerHelperTest : public web::WebTestWithWebState { +class PasswordFormHelperTest : public web::WebTestWithWebState { public: - PasswordControllerHelperTest() + PasswordFormHelperTest() : web::WebTestWithWebState(std::make_unique<TestWebClientWithScript>()) {} - ~PasswordControllerHelperTest() override = default; + ~PasswordFormHelperTest() override = default; void SetUp() override { WebTestWithWebState::SetUp(); - helper_ = [[PasswordControllerHelper alloc] initWithWebState:web_state() - delegate:nil]; + helper_ = + [[PasswordFormHelper alloc] initWithWebState:web_state() delegate:nil]; } void TearDown() override { @@ -155,10 +155,10 @@ [NSString stringWithFormat:kGetFormIdScript, form_index])); } - // PasswordControllerHelper for testing. - PasswordControllerHelper* helper_; + // PasswordFormHelper for testing. + PasswordFormHelper* helper_; - DISALLOW_COPY_AND_ASSIGN(PasswordControllerHelperTest); + DISALLOW_COPY_AND_ASSIGN(PasswordFormHelperTest); }; struct GetSubmittedPasswordFormTestData { @@ -176,7 +176,7 @@ // Check that HTML forms are captured and converted correctly into // PasswordForms on submission. -TEST_F(PasswordControllerHelperTest, GetSubmittedPasswordForm) { +TEST_F(PasswordFormHelperTest, GetSubmittedPasswordForm) { // clang-format off const GetSubmittedPasswordFormTestData test_data[] = { // Two forms with no explicit names. @@ -267,7 +267,7 @@ }; // Check that HTML forms are converted correctly into PasswordForms. -TEST_F(PasswordControllerHelperTest, FindPasswordFormsInView) { +TEST_F(PasswordFormHelperTest, FindPasswordFormsInView) { // clang-format off const FindPasswordFormTestData test_data[] = { // Normal form: a username and a password element. @@ -500,7 +500,7 @@ }; // Tests that filling password forms works correctly. -TEST_F(PasswordControllerHelperTest, FillPasswordForm) { +TEST_F(PasswordFormHelperTest, FillPasswordForm) { LoadHtml(kHtmlWithMultiplePasswordForms); const std::string base_url = BaseUrl(); @@ -649,7 +649,7 @@ } // Tests that filling password forms with fill data works correctly. -TEST_F(PasswordControllerHelperTest, FillPasswordFormWithFillData) { +TEST_F(PasswordFormHelperTest, FillPasswordFormWithFillData) { LoadHtml( @"<form><input id='u1' type='text' name='un1'>" "<input id='p1' type='password' name='pw1'></form>"); @@ -673,7 +673,7 @@ // Tests that a form is found and the found form is filled in with the given // username and password. -TEST_F(PasswordControllerHelperTest, FindAndFillOnePasswordForm) { +TEST_F(PasswordFormHelperTest, FindAndFillOnePasswordForm) { LoadHtml( @"<form><input id='u1' type='text' name='un1'>" "<input id='p1' type='password' name='pw1'></form>"); @@ -698,7 +698,7 @@ // Tests that multiple forms on the same page are found and filled. // This test includes an mock injected failure on form filling to verify // that completion handler is called with the proper values. -TEST_F(PasswordControllerHelperTest, FindAndFillMultiplePasswordForms) { +TEST_F(PasswordFormHelperTest, FindAndFillMultiplePasswordForms) { // Fails the first call to fill password form. MockJsPasswordManager* mockJsPasswordManager = [[MockJsPasswordManager alloc] initWithReceiver:web_state()->GetJSInjectionReceiver()];
diff --git a/components/password_manager/ios/password_suggestion_helper.h b/components/password_manager/ios/password_suggestion_helper.h new file mode 100644 index 0000000..cbcca46 --- /dev/null +++ b/components/password_manager/ios/password_suggestion_helper.h
@@ -0,0 +1,109 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_SUGGESTION_HELPER_H_ +#define COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_SUGGESTION_HELPER_H_ + +#import <Foundation/Foundation.h> +#include <memory> + +#import "components/autofill/ios/browser/form_suggestion_provider.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FormSuggestion; +@class PasswordSuggestionHelper; + +namespace autofill { +struct PasswordFormFillData; +} // namespace autofill + +namespace password_manager { +struct FillData; +} // namespace password_manager + +namespace web { +class WebState; +} // namespace web + +// A protocol implemented by a delegate of PasswordSuggestionHelper. +@protocol PasswordSuggestionHelperDelegate<NSObject> + +// Called when form extraction is required for checking suggestion availability. +// The caller must trigger the form extraction in this method. +- (void)suggestionHelperShouldTriggerFormExtraction: + (PasswordSuggestionHelper*)suggestionHelper; + +@end + +// Provides common logic of password autofill suggestions for both ios/chrome +// and ios/web_view. +@interface PasswordSuggestionHelper : NSObject + +// Creates an instance with the given delegate. +- (instancetype)initWithDelegate:(id<PasswordSuggestionHelperDelegate>)delegate + NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +// Retrieves suggestions as username and realm pairs +// (defined in |password_manager::UsernameAndRealm|) and converts +// them into objective C representations. In the returned |FormSuggestion| +// items, |value| field will be the username and |displayDescription| will be +// the realm. +- (NSArray<FormSuggestion*>*) +retrieveSuggestionsWithFormName:(NSString*)formName + fieldIdentifier:(NSString*)fieldIdentifier + fieldType:(NSString*)fieldType; + +// Checks if suggestions are available for the field. +// |completion| will be called when the check is completed, with boolean +// parameter indicating whether suggestions are available or not. +// See //components/autofill/ios/form_util/form_activity_params.h for definition +// of other parameters. +- (void)checkIfSuggestionsAvailableForForm:(NSString*)formName + fieldIdentifier:(NSString*)fieldIdentifier + type:(NSString*)type + frameID:(NSString*)frameID + isMainFrame:(BOOL)isMainFrame + webState:(web::WebState*)webState + completionHandler: + (SuggestionsAvailableCompletion)completion; + +// Retrieves password form fill data for |username| for use in +// |PasswordFormHelper|'s +// -fillPasswordFormWithFillData:completionHandler:. +- (std::unique_ptr<password_manager::FillData>)getFillDataForUsername: + (NSString*)username; + +// The following methods should be called to maintain the correct state along +// with password forms. + +// Resets fill data, callbacks and state flags for new page. This method should +// be called in password controller's -webState:didLoadPageWithSuccess:. +- (void)resetForNewPage; + +// Prepares fill data with given password form data. Triggers callback for +// -checkIfSuggestionsAvailableForForm... if needed. +// This method should be called in password controller's +// -fillPasswordForm:completionHandler:. +- (void)processWithPasswordFormFillData: + (const autofill::PasswordFormFillData&)formData; + +// Processes field for which no saved credentials are available. +// Triggers callback for -checkIfSuggestionsAvailableForForm... if needed. +// This method should be called in password controller's +// -onNoSavedCredentials. +- (void)processWithNoSavedCredentials; + +// Updates the state for password form extraction state. +// This method should be called in password controller's +// -didFinishPasswordFormExtraction:, when the extracted forms are not empty. +- (void)updateStateOnPasswordFormExtracted; + +@end + +NS_ASSUME_NONNULL_END + +#endif // COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_SUGGESTION_HELPER_H_
diff --git a/components/password_manager/ios/password_suggestion_helper.mm b/components/password_manager/ios/password_suggestion_helper.mm new file mode 100644 index 0000000..f46f1853 --- /dev/null +++ b/components/password_manager/ios/password_suggestion_helper.mm
@@ -0,0 +1,175 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "components/password_manager/ios/password_suggestion_helper.h" + +#include "base/strings/sys_string_conversions.h" +#include "components/autofill/core/common/form_data.h" +#import "components/autofill/ios/browser/form_suggestion.h" +#include "components/password_manager/ios/account_select_fill_data.h" +#include "ios/web/public/web_state/web_frame.h" +#include "ios/web/public/web_state/web_frame_util.h" +#import "ios/web/public/web_state/web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using autofill::FormData; +using autofill::PasswordFormFillData; +using base::SysNSStringToUTF16; +using base::SysNSStringToUTF8; +using base::SysUTF16ToNSString; +using base::SysUTF8ToNSString; +using password_manager::AccountSelectFillData; +using password_manager::FillData; + +typedef void (^PasswordSuggestionsAvailableCompletion)( + const password_manager::AccountSelectFillData* __nullable); + +namespace { +NSString* const kPasswordFieldType = @"password"; +} // namespace + +@interface PasswordSuggestionHelper () +// Delegate to receive callbacks. +@property(nonatomic, weak, readonly) id<PasswordSuggestionHelperDelegate> + delegate; + +@end + +@implementation PasswordSuggestionHelper { + // The C++ interface to cache and retrieve password suggestions. + AccountSelectFillData _fillData; + + // YES indicates that extracted password form has been sent to the password + // manager. + BOOL _sentPasswordFormToPasswordManager; + + // The completion to inform the caller of -checkIfSuggestionsAvailableForForm: + // that suggestions are available for a given form and field. + PasswordSuggestionsAvailableCompletion _suggestionsAvailableCompletion; +} + +@synthesize delegate = _delegate; + +- (instancetype)initWithDelegate: + (id<PasswordSuggestionHelperDelegate>)delegate { + self = [super init]; + if (self) { + _sentPasswordFormToPasswordManager = NO; + _delegate = delegate; + } + return self; +} + +#pragma mark - Public methods + +- (NSArray<FormSuggestion*>*) +retrieveSuggestionsWithFormName:(NSString*)formName + fieldIdentifier:(NSString*)fieldIdentifier + fieldType:(NSString*)fieldType { + base::string16 utfFormName = SysNSStringToUTF16(formName); + base::string16 utfFieldIdentifier = SysNSStringToUTF16(fieldIdentifier); + BOOL isPasswordField = [fieldType isEqual:kPasswordFieldType]; + + NSMutableArray<FormSuggestion*>* results = [NSMutableArray array]; + + if (_fillData.IsSuggestionsAvailable(utfFormName, utfFieldIdentifier, + isPasswordField)) { + std::vector<password_manager::UsernameAndRealm> usernameAndRealms = + _fillData.RetrieveSuggestions(utfFormName, utfFieldIdentifier, + isPasswordField); + + for (const auto& usernameAndRealm : usernameAndRealms) { + NSString* username = SysUTF16ToNSString(usernameAndRealm.username); + NSString* realm = usernameAndRealm.realm.empty() + ? nil + : SysUTF8ToNSString(usernameAndRealm.realm); + [results addObject:[FormSuggestion suggestionWithValue:username + displayDescription:realm + icon:nil + identifier:0]]; + } + } + + return [results copy]; +} + +- (void)checkIfSuggestionsAvailableForForm:(NSString*)formName + fieldIdentifier:(NSString*)fieldIdentifier + type:(NSString*)type + frameID:(NSString*)frameID + isMainFrame:(BOOL)isMainFrame + webState:(web::WebState*)webState + completionHandler: + (SuggestionsAvailableCompletion)completion { + // When password controller's -processWithPasswordFormFillData: is already + // called, |completion| will be called immediately and |triggerFormExtraction| + // will be skipped. + // Otherwise, -suggestionHelperShouldTriggerFormExtraction: will be called + // and |completion| will not be called until + // -processWithPasswordFormFillData: is called. + // For unsupported form, |completion| will be called immediately and + // -suggestionHelperShouldTriggerFormExtraction: will be skipped. + if (!isMainFrame) { + web::WebFrame* frame = + web::GetWebFrameWithId(webState, SysNSStringToUTF8(frameID)); + if (!frame || webState->GetLastCommittedURL().GetOrigin() != + frame->GetSecurityOrigin()) { + // Passwords is only supported on main frame and iframes with the same + // origin. + completion(NO); + } + } + + if (!_sentPasswordFormToPasswordManager && [type isEqual:@"focus"]) { + // Save the callback until fill data is ready. + _suggestionsAvailableCompletion = ^(const AccountSelectFillData* fillData) { + completion(!fillData ? NO + : fillData->IsSuggestionsAvailable( + SysNSStringToUTF16(formName), + SysNSStringToUTF16(fieldIdentifier), false)); + }; + // Form extraction is required for this check. + [self.delegate suggestionHelperShouldTriggerFormExtraction:self]; + return; + } + + completion(_fillData.IsSuggestionsAvailable( + SysNSStringToUTF16(formName), SysNSStringToUTF16(fieldIdentifier), + false)); +} + +- (std::unique_ptr<password_manager::FillData>)getFillDataForUsername: + (NSString*)username { + return _fillData.GetFillData(SysNSStringToUTF16(username)); +} + +- (void)resetForNewPage { + _fillData.Reset(); + _sentPasswordFormToPasswordManager = NO; + _suggestionsAvailableCompletion = nil; +} + +- (void)processWithPasswordFormFillData:(const PasswordFormFillData&)formData { + _fillData.Add(formData); + + if (_suggestionsAvailableCompletion) { + _suggestionsAvailableCompletion(&_fillData); + _suggestionsAvailableCompletion = nil; + } +} +- (void)processWithNoSavedCredentials { + if (_suggestionsAvailableCompletion) { + _suggestionsAvailableCompletion(nullptr); + } + _suggestionsAvailableCompletion = nil; +} + +- (void)updateStateOnPasswordFormExtracted { + _sentPasswordFormToPasswordManager = YES; +} + +@end
diff --git a/components/sync/driver/glue/sync_backend_host_impl.cc b/components/sync/driver/glue/sync_backend_host_impl.cc index 8d85557..42af545 100644 --- a/components/sync/driver/glue/sync_backend_host_impl.cc +++ b/components/sync/driver/glue/sync_backend_host_impl.cc
@@ -149,11 +149,9 @@ DCHECK(!host_); if (invalidation_handler_registered_) { - if (reason != BROWSER_SHUTDOWN) { - bool success = - invalidator_->UpdateRegisteredInvalidationIds(this, ObjectIdSet()); - DCHECK(success); - } + bool success = + invalidator_->UpdateRegisteredInvalidationIds(this, ObjectIdSet()); + DCHECK(success); invalidator_->UnregisterInvalidationHandler(this); invalidator_ = nullptr; }
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc index 29c3977..5a0be40 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.cc +++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -185,6 +185,7 @@ if (!top_level_entity) { return false; } + top_level_permanent_item_ids_[model_type] = top_level_entity->GetId(); SaveEntity(std::move(top_level_entity)); if (model_type == syncer::BOOKMARKS) { @@ -200,6 +201,15 @@ return true; } +std::string LoopbackServer::GetTopLevelPermanentItemId( + syncer::ModelType model_type) { + auto it = top_level_permanent_item_ids_.find(model_type); + if (it == top_level_permanent_item_ids_.end()) { + return std::string(); + } + return it->second; +} + void LoopbackServer::UpdateEntityVersion(LoopbackServerEntity* entity) { entity->SetVersion(++version_); } @@ -506,6 +516,22 @@ return sync_entities; } +std::vector<sync_pb::SyncEntity> +LoopbackServer::GetPermanentSyncEntitiesByModelType(ModelType model_type) { + DCHECK(thread_checker_.CalledOnValidThread()); + std::vector<sync_pb::SyncEntity> sync_entities; + for (const auto& kv : entities_) { + const LoopbackServerEntity& entity = *kv.second; + if (!entity.IsDeleted() && entity.IsPermanent() && + entity.GetModelType() == model_type) { + sync_pb::SyncEntity sync_entity; + entity.SerializeAsProto(&sync_entity); + sync_entities.push_back(sync_entity); + } + } + return sync_entities; +} + std::unique_ptr<base::DictionaryValue> LoopbackServer::GetEntitiesAsDictionaryValue() { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.h b/components/sync/engine_impl/loopback_server/loopback_server.h index 407f2c6e..680e9a1 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.h +++ b/components/sync/engine_impl/loopback_server/loopback_server.h
@@ -88,6 +88,10 @@ // Inserts the default permanent items in |entities_|. bool CreateDefaultPermanentItems(); + // Returns an empty string if no top-level permanent item of the given type + // was created. + std::string GetTopLevelPermanentItemId(syncer::ModelType model_type); + std::string GenerateNewKeystoreKey() const; // Saves a |entity| to |entities_|. @@ -127,14 +131,20 @@ std::string GetStoreBirthday() const; // Returns all entities stored by the server of the given |model_type|. - // This method is only used in tests. + // Permanent entities are excluded. This method is only used in tests. std::vector<sync_pb::SyncEntity> GetSyncEntitiesByModelType( syncer::ModelType model_type); + // Returns a list of permanent entities of the given |model_type|. This method + // is only used in tests. + std::vector<sync_pb::SyncEntity> GetPermanentSyncEntitiesByModelType( + syncer::ModelType model_type); + // Creates a DicionaryValue representation of all entities present in the // server. The dictionary keys are the strings generated by ModelTypeToString // and the values are ListValues containing StringValue versions of entity - // names. Used by test to verify the contents of the server state. + // names. Permanent entities are excluded. Used by test to verify the contents + // of the server state. std::unique_ptr<base::DictionaryValue> GetEntitiesAsDictionaryValue(); // Modifies the entity on the server with the given |id|. The entity's @@ -189,6 +199,7 @@ int64_t store_birthday_; EntityMap entities_; + std::map<ModelType, std::string> top_level_permanent_item_ids_; std::vector<std::string> keystore_keys_; // The file used to store the local sync data.
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc index c2b55fc..e2f9c67c 100644 --- a/components/sync/test/fake_server/fake_server.cc +++ b/components/sync/test/fake_server/fake_server.cc
@@ -306,6 +306,18 @@ return loopback_server_->GetSyncEntitiesByModelType(model_type); } +std::vector<sync_pb::SyncEntity> +FakeServer::GetPermanentSyncEntitiesByModelType(ModelType model_type) { + DCHECK(thread_checker_.CalledOnValidThread()); + return loopback_server_->GetPermanentSyncEntitiesByModelType(model_type); +} + +std::string FakeServer::GetTopLevelPermanentItemId( + syncer::ModelType model_type) { + DCHECK(thread_checker_.CalledOnValidThread()); + return loopback_server_->GetTopLevelPermanentItemId(model_type); +} + void FakeServer::InjectEntity(std::unique_ptr<LoopbackServerEntity> entity) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(entity->GetModelType() != syncer::AUTOFILL_WALLET_DATA)
diff --git a/components/sync/test/fake_server/fake_server.h b/components/sync/test/fake_server/fake_server.h index fdede785..6a8c2928 100644 --- a/components/sync/test/fake_server/fake_server.h +++ b/components/sync/test/fake_server/fake_server.h
@@ -81,10 +81,21 @@ // Returns all entities stored by the server of the given |model_type|. // This method returns SyncEntity protocol buffer objects (instead of // LoopbackServerEntity) so that callers can inspect datatype-specific data - // (e.g., the URL of a session tab). + // (e.g., the URL of a session tab). Permanent entities are excluded. std::vector<sync_pb::SyncEntity> GetSyncEntitiesByModelType( syncer::ModelType model_type); + // Returns all permanent entities stored by the server of the given + // |model_type|. This method returns SyncEntity protocol buffer objects + // (instead of LoopbackServerEntity) so that callers can inspect + // datatype-specific data (e.g., the URL of a session tab). + std::vector<sync_pb::SyncEntity> GetPermanentSyncEntitiesByModelType( + syncer::ModelType model_type); + + // Returns an empty string if no top-level permanent item of the given type + // was created. + std::string GetTopLevelPermanentItemId(syncer::ModelType model_type); + // Adds |entity| to the server's collection of entities. This method makes no // guarantees that the added entity will result in successful server // operations.
diff --git a/components/sync_bookmarks/BUILD.gn b/components/sync_bookmarks/BUILD.gn index e264a6f..3b36cc4 100644 --- a/components/sync_bookmarks/BUILD.gn +++ b/components/sync_bookmarks/BUILD.gn
@@ -38,6 +38,7 @@ "//components/keyed_service/core:core", "//components/sync", "//components/undo", + "//ui/base", "//ui/gfx", ] }
diff --git a/components/sync_bookmarks/DEPS b/components/sync_bookmarks/DEPS index eb67095..bc162d7 100644 --- a/components/sync_bookmarks/DEPS +++ b/components/sync_bookmarks/DEPS
@@ -7,5 +7,6 @@ "+components/prefs", "+components/sync", "+components/undo", + "+ui/base", "+ui/gfx", ]
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc index 9a69445..cc7ae9c 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor.cc +++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -216,10 +216,9 @@ sync_pb::BookmarkModelMetadata model_metadata; model_metadata.ParseFromString(metadata_str); - auto model_type_state = std::make_unique<sync_pb::ModelTypeState>(); - model_type_state->Swap(model_metadata.mutable_model_type_state()); - - if (model_type_state->initial_sync_done()) { + if (model_metadata.model_type_state().initial_sync_done() && + SyncedBookmarkTracker::BookmarkModelMatchesMetadata(model, + model_metadata)) { std::vector<NodeMetadataPair> nodes_metadata; for (sync_pb::BookmarkMetadata& bookmark_metadata : *model_metadata.mutable_bookmarks_metadata()) { @@ -227,35 +226,20 @@ // all nodes and store in a map keyed by id instead of doing a lookup for // every id. const bookmarks::BookmarkNode* node = nullptr; - if (bookmark_metadata.metadata().is_deleted()) { - if (bookmark_metadata.has_id()) { - DLOG(ERROR) << "Error when decoding sync metadata: Tombstones " - "shouldn't have a bookmark id."; - continue; - } - } else { - if (!bookmark_metadata.has_id()) { - DLOG(ERROR) - << "Error when decoding sync metadata: Bookmark id is missing."; - continue; - } + if (!bookmark_metadata.metadata().is_deleted()) { node = GetBookmarkNodeByID(bookmark_model_, bookmark_metadata.id()); - if (node == nullptr) { - DLOG(ERROR) << "Error when decoding sync metadata: Cannot find the " - "bookmark node."; - continue; - } + DCHECK(node); } auto metadata = std::make_unique<sync_pb::EntityMetadata>(); metadata->Swap(bookmark_metadata.mutable_metadata()); nodes_metadata.emplace_back(node, std::move(metadata)); } - // TODO(crbug.com/516866): Handle local nodes that don't have a - // corresponding - // metadata. + auto model_type_state = std::make_unique<sync_pb::ModelTypeState>(); + model_type_state->Swap(model_metadata.mutable_model_type_state()); StartTrackingMetadata(std::move(nodes_metadata), std::move(model_type_state)); - } else if (!model_metadata.bookmarks_metadata().empty()) { + } else if (!model_metadata.model_type_state().initial_sync_done() && + !model_metadata.bookmarks_metadata().empty()) { DLOG(ERROR) << "Persisted Metadata not empty while initial sync is not done."; }
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.h b/components/sync_bookmarks/bookmark_model_type_processor.h index 66adbba..2a221df 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor.h +++ b/components/sync_bookmarks/bookmark_model_type_processor.h
@@ -63,7 +63,7 @@ // restored via ModelReadyToSync() below. std::string EncodeSyncMetadata() const; - // It mainly decodes a BookmarkModelMetadata proto seralized in + // It mainly decodes a BookmarkModelMetadata proto serialized in // |metadata_str|, and uses it to fill in the tracker and the model type state // objects. |model| must not be null and must outlive this object. It is used // to the retrieve the local node ids, and is stored in the processor to be
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc index 49a0312..33f299fe 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc +++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -30,7 +30,11 @@ namespace { const char kBookmarkBarTag[] = "bookmark_bar"; +const char kOtherBookmarksTag[] = "other_bookmarks"; +const char kMobileBookmarksTag[] = "synced_bookmarks"; const char kBookmarkBarId[] = "bookmark_bar_id"; +const char kOtherBookmarksId[] = "other_bookmarks_id"; +const char kMobileBookmarksId[] = "mobile_bookmarks_id"; const char kBookmarksRootId[] = "root_id"; const char kCacheGuid[] = "generated_id"; @@ -79,8 +83,8 @@ const SyncedBookmarkTracker* tracker = processor->GetTrackerForTest(); // Make sure the tracker contains all bookmarks in |bookmarks| + the - // bookmark bar node. - ASSERT_THAT(tracker->TrackedEntitiesCountForTest(), Eq(bookmarks.size() + 1)); + // 3 permanent nodes. + ASSERT_THAT(tracker->TrackedEntitiesCountForTest(), Eq(bookmarks.size() + 3)); for (BookmarkInfo bookmark : bookmarks) { const SyncedBookmarkTracker::Entity* entity = @@ -103,22 +107,26 @@ syncer::UpdateResponseDataList updates; syncer::UniquePosition pos = syncer::UniquePosition::InitialPosition( syncer::UniquePosition::RandomSuffix()); - // Add update for the permanent folder "Bookmarks bar". + // Add update for the permanent folders "Bookmarks bar", "Other Bookmarks" and + // "Mobile Bookmarks". updates.push_back( CreateUpdateResponseData({kBookmarkBarId, std::string(), std::string(), kBookmarksRootId, kBookmarkBarTag}, pos, /*response_version=*/0)); + updates.push_back( + CreateUpdateResponseData({kOtherBookmarksId, std::string(), std::string(), + kBookmarksRootId, kOtherBookmarksTag}, + pos, /*response_version=*/0)); + updates.push_back(CreateUpdateResponseData( + {kMobileBookmarksId, std::string(), std::string(), kBookmarksRootId, + kMobileBookmarksTag}, + pos, /*response_version=*/0)); for (BookmarkInfo bookmark : bookmarks) { pos = syncer::UniquePosition::After(pos, syncer::UniquePosition::RandomSuffix()); updates.push_back( CreateUpdateResponseData(bookmark, pos, /*response_version=*/0)); } - // TODO(crbug.com/516866): Remove after a proper positioning for remote - // updates is implemented. Reversing the updates because the sorting algorithm - // isn't stable. This is OK for now because once proper positioning is - // implemented, the siblings update requests order would be irrelvant. - std::reverse(updates.begin(), updates.end()); processor->OnUpdateReceived(CreateDummyModelTypeState(), updates); AssertState(processor, bookmarks); } @@ -278,11 +286,20 @@ // within the processor. sync_pb::BookmarkModelMetadata model_metadata; model_metadata.mutable_model_type_state()->set_initial_sync_done(true); - // Add an entry for bookmark bar. + // Add entries for the permanent nodes. TestBookmarkClient adds all of them. sync_pb::BookmarkMetadata* bookmark_metadata = model_metadata.add_bookmarks_metadata(); bookmark_metadata->set_id(bookmark_bar_node->id()); bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId); + + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(bookmark_model()->other_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id(kOtherBookmarksId); + + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(bookmark_model()->mobile_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id(kMobileBookmarksId); + // Add an entry for the bookmark node. bookmark_metadata = model_metadata.add_bookmarks_metadata(); bookmark_metadata->set_id(bookmarknode->id()); @@ -331,6 +348,50 @@ AssertState(&new_processor, bookmarks); } +TEST_F(BookmarkModelTypeProcessorTest, + ShouldIgnoreNonEmptyMetadataWhileSyncNotDone) { + sync_pb::BookmarkModelMetadata model_metadata; + model_metadata.mutable_model_type_state()->set_initial_sync_done(false); + // Add entries to the metadata. + sync_pb::BookmarkMetadata* bookmark_metadata = + model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(bookmark_model()->bookmark_bar_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId); + + // Create a new processor and init it with the metadata str. + BookmarkModelTypeProcessor new_processor(bookmark_undo_service()); + + std::string metadata_str; + model_metadata.SerializeToString(&metadata_str); + new_processor.ModelReadyToSync(metadata_str, base::DoNothing(), + bookmark_model()); + // Metadata are corrupted, so no tracker should have been created. + EXPECT_THAT(new_processor.GetTrackerForTest(), IsNull()); +} + +TEST_F(BookmarkModelTypeProcessorTest, + ShouldIgnoreMetadataNotMatchingTheModel) { + sync_pb::BookmarkModelMetadata model_metadata; + model_metadata.mutable_model_type_state()->set_initial_sync_done(true); + // Add entries for only the bookmark bar. However, the TestBookmarkClient will + // create all the 3 permanent nodes. + sync_pb::BookmarkMetadata* bookmark_metadata = + model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(bookmark_model()->bookmark_bar_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId); + + // Create a new processor and init it with the metadata str. + BookmarkModelTypeProcessor new_processor(bookmark_undo_service()); + + std::string metadata_str; + model_metadata.SerializeToString(&metadata_str); + new_processor.ModelReadyToSync(metadata_str, base::DoNothing(), + bookmark_model()); + + // Metadata are corrupted, so no tracker should have been created. + EXPECT_THAT(new_processor.GetTrackerForTest(), IsNull()); +} + // Verifies that the model type state stored in the tracker gets // updated upon handling remote updates by assigning a new encryption // key name.
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc index 14c3c35..c49854f 100644 --- a/components/sync_bookmarks/synced_bookmark_tracker.cc +++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -4,6 +4,7 @@ #include "components/sync_bookmarks/synced_bookmark_tracker.h" +#include <algorithm> #include <set> #include <utility> @@ -11,11 +12,13 @@ #include "base/sha1.h" #include "base/stl_util.h" #include "base/trace_event/memory_usage_estimator.h" +#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_node.h" #include "components/sync/base/time.h" #include "components/sync/base/unique_position.h" #include "components/sync/model/entity_data.h" #include "components/sync/protocol/proto_memory_estimations.h" +#include "ui/base/models/tree_node_iterator.h" namespace sync_bookmarks { @@ -107,6 +110,58 @@ SyncedBookmarkTracker::~SyncedBookmarkTracker() = default; +// static +bool SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + const bookmarks::BookmarkModel* model, + const sync_pb::BookmarkModelMetadata& model_metadata) { + DCHECK(model_metadata.model_type_state().initial_sync_done()); + + // Collect ids of non-deletion entries in the metadata. + std::vector<int> metadata_node_ids; + for (const sync_pb::BookmarkMetadata& bookmark_metadata : + model_metadata.bookmarks_metadata()) { + if (!bookmark_metadata.metadata().has_server_id()) { + DLOG(ERROR) << "Error when decoding sync metadata: Entities must contain " + "server id."; + return false; + } + if (bookmark_metadata.metadata().is_deleted() && + bookmark_metadata.has_id()) { + DLOG(ERROR) << "Error when decoding sync metadata: Tombstones " + "shouldn't have a bookmark id."; + return false; + } + if (!bookmark_metadata.metadata().is_deleted() && + !bookmark_metadata.has_id()) { + DLOG(ERROR) + << "Error when decoding sync metadata: Bookmark id is missing."; + return false; + } + // The entry is valid. If it's not a tombstone, collect its node id to + // compare it later with the ids in the model. + if (!bookmark_metadata.metadata().is_deleted()) { + metadata_node_ids.push_back(bookmark_metadata.id()); + } + } + + // Collect ids of nodes in the model. + std::vector<int> model_node_ids; + ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator( + model->root_node()); + while (iterator.has_next()) { + const bookmarks::BookmarkNode* node = iterator.Next(); + model_node_ids.push_back(node->id()); + } + + if (model_node_ids.size() != metadata_node_ids.size()) { + return false; + } + std::sort(model_node_ids.begin(), model_node_ids.end()); + std::sort(metadata_node_ids.begin(), metadata_node_ids.end()); + return std::equal(model_node_ids.begin(), model_node_ids.end(), + metadata_node_ids.begin()); +} + const SyncedBookmarkTracker::Entity* SyncedBookmarkTracker::GetEntityForSyncId( const std::string& sync_id) const { auto it = sync_id_to_entities_map_.find(sync_id);
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.h b/components/sync_bookmarks/synced_bookmark_tracker.h index 5857786..8384924e 100644 --- a/components/sync_bookmarks/synced_bookmark_tracker.h +++ b/components/sync_bookmarks/synced_bookmark_tracker.h
@@ -18,6 +18,7 @@ #include "components/sync/protocol/unique_position.pb.h" namespace bookmarks { +class BookmarkModel; class BookmarkNode; } @@ -95,6 +96,13 @@ std::unique_ptr<sync_pb::ModelTypeState> model_type_state); ~SyncedBookmarkTracker(); + // Checks the integrity of the |model_metadata|. It also verifies that the + // contents of the |model_metadata| match the contents of |model|. It should + // only be called if the initial sync has completed. + static bool BookmarkModelMatchesMetadata( + const bookmarks::BookmarkModel* model, + const sync_pb::BookmarkModelMetadata& model_metadata); + // Returns null if no entity is found. const Entity* GetEntityForSyncId(const std::string& sync_id) const;
diff --git a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc index f368bc25..10955cf1 100644 --- a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc +++ b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
@@ -376,6 +376,94 @@ EXPECT_THAT(entities_with_local_change[3]->metadata()->server_id(), Eq(kId3)); } +TEST(SyncedBookmarkTrackerTest, ShouldMatchModelAndMetadata) { + std::unique_ptr<bookmarks::BookmarkModel> model = + bookmarks::TestBookmarkClient::CreateModel(); + + const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node(); + const bookmarks::BookmarkNode* node = model->AddFolder( + /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0")); + + sync_pb::BookmarkModelMetadata model_metadata; + model_metadata.mutable_model_type_state()->set_initial_sync_done(true); + // Add entries for all the permanent nodes. TestBookmarkClient creates all the + // 3 permanent nodes. + sync_pb::BookmarkMetadata* bookmark_metadata = + model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(model->bookmark_bar_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id("BookmarkBarId"); + + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(model->other_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId"); + + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(model->mobile_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id("MobileBookmarksId"); + + // Add entry for the extra node. + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(node->id()); + bookmark_metadata->mutable_metadata()->set_server_id("NodeId"); + + // Add a tombstone entry. + sync_pb::BookmarkMetadata* tombstone = + model_metadata.add_bookmarks_metadata(); + tombstone->mutable_metadata()->set_server_id("tombstoneId"); + tombstone->mutable_metadata()->set_is_deleted(true); + + EXPECT_TRUE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + model.get(), model_metadata)); +} + +TEST(SyncedBookmarkTrackerTest, ShouldNotMatchModelAndCorruptedMetadata) { + std::unique_ptr<bookmarks::BookmarkModel> model = + bookmarks::TestBookmarkClient::CreateModel(); + + sync_pb::BookmarkModelMetadata model_metadata; + model_metadata.mutable_model_type_state()->set_initial_sync_done(true); + // Add entries for 2 permanent nodes only. TestBookmarkClient creates all the + // 3 permanent nodes. + sync_pb::BookmarkMetadata* bookmark_metadata = + model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(model->bookmark_bar_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id("BookmarkBarId"); + + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(model->other_node()->id()); + bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId"); + + // The entry for the Mobile bookmarks is missing. + EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + model.get(), model_metadata)); + + // The entry for the Mobile bookmarks is missing a server id. + bookmark_metadata = model_metadata.add_bookmarks_metadata(); + bookmark_metadata->set_id(model->mobile_node()->id()); + EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + model.get(), model_metadata)); + + // The entry for the Mobile bookmarks is missing a node id. + bookmark_metadata->clear_id(); + bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId"); + EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + model.get(), model_metadata)); + + // The entry for the Mobile bookmarks is having a wrong node id. + bookmark_metadata->set_id(model->mobile_node()->id() + 1); + EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + model.get(), model_metadata)); + + // A tombstone shouldn't have a node id. + sync_pb::BookmarkMetadata* tombstone = + model_metadata.add_bookmarks_metadata(); + tombstone->mutable_metadata()->set_server_id("tombstoneId"); + tombstone->mutable_metadata()->set_is_deleted(true); + tombstone->set_id(10); + EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata( + model.get(), model_metadata)); +} + } // namespace } // namespace sync_bookmarks
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index 5cf6462..b1d54ae 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -279,8 +279,7 @@ DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin || event.GetType() == blink::WebInputEvent::kGestureScrollUpdate || event.GetType() == blink::WebInputEvent::kGestureScrollEnd || - event.GetType() == blink::WebInputEvent::kGestureFlingStart || - event.GetType() == blink::WebInputEvent::kGestureFlingCancel); + event.GetType() == blink::WebInputEvent::kGestureFlingStart); auto* parent_view = GetParentRenderWidgetHostView(); if (!parent_view) @@ -303,9 +302,7 @@ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) { event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_); is_scroll_bubbling_ = true; - } else if (is_scroll_bubbling_ || - event.GetType() == blink::WebInputEvent::kGestureFlingCancel) { - // For GFC events the router decides whether to bubble them or not. + } else if (is_scroll_bubbling_) { event_router->BubbleScrollEvent(parent_view, resent_gesture_event, view_); } if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index bd5221c..1be647e 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -62,6 +62,7 @@ #include "content/browser/frame_host/navigator.h" #include "content/browser/renderer_host/render_view_host_impl.h" // Temporary #include "content/browser/site_instance_impl.h" +#include "content/common/content_constants_internal.h" #include "content/common/frame_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" @@ -133,6 +134,24 @@ return last_entry && last_entry->GetIsOverridingUserAgent(); } +// Determines whether to override user agent for a navigation. +bool ShouldOverrideUserAgent( + NavigationController::UserAgentOverrideOption override_user_agent, + const NavigationEntry* last_committed_entry) { + switch (override_user_agent) { + case NavigationController::UA_OVERRIDE_INHERIT: + return ShouldKeepOverride(last_committed_entry); + case NavigationController::UA_OVERRIDE_TRUE: + return true; + case NavigationController::UA_OVERRIDE_FALSE: + return false; + default: + break; + } + NOTREACHED(); + return false; +} + // Returns true this navigation should be treated as a reload. For e.g. // navigating to the last committed url via the address bar or clicking on a // link which results in a navigation to the last committed or pending @@ -215,6 +234,34 @@ return true; } +bool IsValidURLForNavigation(bool is_main_frame, + const GURL& virtual_url, + const GURL& dest_url) { + // Don't attempt to navigate if the virtual URL is non-empty and invalid. + if (is_main_frame && !virtual_url.is_valid() && !virtual_url.is_empty()) { + LOG(WARNING) << "Refusing to load for invalid virtual URL: " + << virtual_url.possibly_invalid_spec(); + return false; + } + + // Don't attempt to navigate to non-empty invalid URLs. + if (!dest_url.is_valid() && !dest_url.is_empty()) { + LOG(WARNING) << "Refusing to load invalid URL: " + << dest_url.possibly_invalid_spec(); + return false; + } + + // The renderer will reject IPC messages with URLs longer than + // this limit, so don't attempt to navigate with a longer URL. + if (dest_url.spec().size() > url::kMaxURLChars) { + LOG(WARNING) << "Refusing to load URL as it exceeds " << url::kMaxURLChars + << " characters."; + return false; + } + + return true; +} + // See replaced_navigation_entry_data.h for details: this information is meant // to ensure |*output_entry| keeps track of its original URL (landing page in // case of server redirects) as it gets replaced (e.g. history.replaceState()), @@ -286,6 +333,72 @@ } } +// Adjusts the original input URL if needed, to get the URL to actually load and +// the virtual URL, which may differ. +void RewriteUrlForNavigation(const GURL& original_url, + BrowserContext* browser_context, + GURL* url_to_load, + GURL* virtual_url, + bool* reverse_on_redirect) { + // Fix up the given URL before letting it be rewritten, so that any minor + // cleanup (e.g., removing leading dots) will not lead to a virtual URL. + *virtual_url = original_url; + BrowserURLHandlerImpl::GetInstance()->FixupURLBeforeRewrite(virtual_url, + browser_context); + + // Allow the browser URL handler to rewrite the URL. This will, for example, + // remove "view-source:" from the beginning of the URL to get the URL that + // will actually be loaded. This real URL won't be shown to the user, just + // used internally. + *url_to_load = *virtual_url; + BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( + url_to_load, browser_context, reverse_on_redirect); +} + +#if DCHECK_IS_ON() +// Helper sanity check function used in debug mode. +void ValidateRequestMatchesEntry(NavigationRequest* request, + NavigationEntryImpl* entry) { + if (request->frame_tree_node()->IsMainFrame()) { + DCHECK_EQ(request->browser_initiated(), !entry->is_renderer_initiated()); + DCHECK(ui::PageTransitionTypeIncludingQualifiersIs( + request->common_params().transition, entry->GetTransitionType())); + } + DCHECK_EQ(request->common_params().should_replace_current_entry, + entry->should_replace_entry()); + DCHECK_EQ(request->request_params().should_clear_history_list, + entry->should_clear_history_list()); + DCHECK_EQ(request->common_params().has_user_gesture, + entry->has_user_gesture()); + DCHECK_EQ(request->common_params().base_url_for_data_url, + entry->GetBaseURLForDataURL()); + DCHECK_EQ(request->request_params().can_load_local_resources, + entry->GetCanLoadLocalResources()); + DCHECK_EQ(request->common_params().started_from_context_menu, + entry->has_started_from_context_menu()); + + FrameNavigationEntry* frame_entry = + entry->GetFrameEntry(request->frame_tree_node()); + if (!frame_entry) { + NOTREACHED(); + return; + } + + DCHECK_EQ(request->common_params().url, frame_entry->url()); + DCHECK_EQ(request->common_params().method, frame_entry->method()); + + size_t redirect_size = request->request_params().redirects.size(); + if (redirect_size == frame_entry->redirect_chain().size()) { + for (size_t i = 0; i < redirect_size; ++i) { + DCHECK_EQ(request->request_params().redirects[i], + frame_entry->redirect_chain()[i]); + } + } else { + NOTREACHED(); + } +} +#endif // DCHECK_IS_ON() + } // namespace // NavigationControllerImpl ---------------------------------------------------- @@ -309,28 +422,19 @@ const std::string& extra_headers, BrowserContext* browser_context, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) { - // Fix up the given URL before letting it be rewritten, so that any minor - // cleanup (e.g., removing leading dots) will not lead to a virtual URL. - GURL dest_url(url); - BrowserURLHandlerImpl::GetInstance()->FixupURLBeforeRewrite(&dest_url, - browser_context); - - // Allow the browser URL handler to rewrite the URL. This will, for example, - // remove "view-source:" from the beginning of the URL to get the URL that - // will actually be loaded. This real URL won't be shown to the user, just - // used internally. - GURL loaded_url(dest_url); + GURL url_to_load; + GURL virtual_url; bool reverse_on_redirect = false; - BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary( - &loaded_url, browser_context, &reverse_on_redirect); + RewriteUrlForNavigation(url, browser_context, &url_to_load, &virtual_url, + &reverse_on_redirect); NavigationEntryImpl* entry = new NavigationEntryImpl( nullptr, // The site instance for tabs is sent on navigation // (WebContents::GetSiteInstance). - loaded_url, referrer, base::string16(), transition, is_renderer_initiated, - blob_url_loader_factory); - entry->SetVirtualURL(dest_url); - entry->set_user_typed_url(dest_url); + url_to_load, referrer, base::string16(), transition, + is_renderer_initiated, blob_url_loader_factory); + entry->SetVirtualURL(virtual_url); + entry->set_user_typed_url(virtual_url); entry->set_update_virtual_url_with_url(reverse_on_redirect); entry->set_extra_headers(extra_headers); return base::WrapUnique(entry); @@ -1810,6 +1914,31 @@ pending_entry_->set_ssl_error(error); } +#if defined(OS_ANDROID) +// static +bool NavigationControllerImpl::ValidateDataURLAsString( + const scoped_refptr<const base::RefCountedString>& data_url_as_string) { + if (!data_url_as_string) + return false; + + if (data_url_as_string->size() > kMaxLengthOfDataURLString) + return false; + + // The number of characters that is enough for validating a data: URI. + // From the GURL's POV, the only important part here is scheme, it doesn't + // check the actual content. Thus we can take only the prefix of the url, to + // avoid unneeded copying of a potentially long string. + const size_t kDataUriPrefixMaxLen = 64; + GURL data_url( + std::string(data_url_as_string->front_as<char>(), + std::min(data_url_as_string->size(), kDataUriPrefixMaxLen))); + if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) + return false; + + return true; +} +#endif + bool NavigationControllerImpl::StartHistoryNavigationInNewSubframe( RenderFrameHostImpl* render_frame_host, const GURL& default_url) { @@ -1843,11 +1972,10 @@ } } - std::unique_ptr<NavigationRequest> request = CreateNavigationRequest( + std::unique_ptr<NavigationRequest> request = CreateNavigationRequestFromEntry( render_frame_host->frame_tree_node(), *entry, frame_entry, ReloadType::NONE, false /* is_same_document_history_load */, - true /* is_history_navigation_in_new_child */, nullptr, nullptr, - base::TimeTicks() /* input_start */, WasActivatedOption::kUnknown); + true /* is_history_navigation_in_new_child */); if (!request) return false; @@ -1915,9 +2043,12 @@ // http://crbug.com/457149 if (should_replace_current_entry && GetEntryCount() > 0) entry->set_should_replace_entry(true); + + bool override_user_agent = false; if (GetLastCommittedEntry() && GetLastCommittedEntry()->GetIsOverridingUserAgent()) { entry->SetIsOverridingUserAgent(true); + override_user_agent = true; } // TODO(creis): Set user gesture and intent received timestamp on Android. @@ -1934,11 +2065,37 @@ std::vector<GURL>(), PageState(), method, -1, blob_url_loader_factory); } - std::unique_ptr<NavigationRequest> request = CreateNavigationRequest( - render_frame_host->frame_tree_node(), *entry, frame_entry.get(), - ReloadType::NONE, false /* is_same_document_history_load */, - false /* is_history_navigation_in_new_child */, post_body, nullptr, - base::TimeTicks() /* input_start */, WasActivatedOption::kUnknown); + LoadURLParams params(url); + params.source_site_instance = source_site_instance; + params.load_type = method == "POST" ? LOAD_TYPE_HTTP_POST : LOAD_TYPE_DEFAULT; + params.transition_type = page_transition; + params.frame_tree_node_id = + render_frame_host->frame_tree_node()->frame_tree_node_id(); + params.referrer = referrer; + /* params.redirect_chain: skip */ + params.extra_headers = extra_headers; + params.is_renderer_initiated = is_renderer_initiated; + params.override_user_agent = UA_OVERRIDE_INHERIT; + /* params.base_url_for_data_url: skip */ + /* params.virtual_url_for_data_url: skip */ + /* params.data_url_as_string: skip */ + params.post_data = post_body; + params.can_load_local_resources = false; + params.should_replace_current_entry = false; + /* params.frame_name: skip */ + // TODO(clamy): See if user gesture should be propagated to this function. + params.has_user_gesture = false; + params.should_clear_history_list = false; + params.started_from_context_menu = false; + /* params.navigation_ui_data: skip */ + /* params.input_start: skip */ + params.was_activated = WasActivatedOption::kUnknown; + + std::unique_ptr<NavigationRequest> request = + CreateNavigationRequestFromLoadParams( + render_frame_host->frame_tree_node(), params, override_user_agent, + should_replace_current_entry, false /* has_user_gesture */, + ReloadType::NONE, *entry, frame_entry.get()); if (!request) return; @@ -2192,11 +2349,10 @@ // frame to navigate based on names if this were a same document // navigation, so we can safely assume this is the different document case. std::unique_ptr<NavigationRequest> navigation_request = - CreateNavigationRequest( + CreateNavigationRequestFromEntry( root, *pending_entry_, pending_entry_->GetFrameEntry(root), reload_type, false /* is_same_document_history_load */, - false /* is_history_navigation_in_new_child */, nullptr, nullptr, - base::TimeTicks() /* input_start */, WasActivatedOption::kUnknown); + false /* is_history_navigation_in_new_child */); if (!navigation_request) { // This navigation cannot start (e.g. the URL is invalid), delete the // pending NavigationEntry. @@ -2269,12 +2425,10 @@ old_item->document_sequence_number() && !frame->current_frame_host()->GetLastCommittedURL().is_empty()) { std::unique_ptr<NavigationRequest> navigation_request = - CreateNavigationRequest( + CreateNavigationRequestFromEntry( frame, *pending_entry_, new_item, reload_type, true /* is_same_document_history_load */, - false /* is_history_navigation_in_new_child */, nullptr, nullptr, - base::TimeTicks() /* input_start */, - WasActivatedOption::kUnknown); + false /* is_history_navigation_in_new_child */); if (navigation_request) { // Only add the request if was properly created. It's possible for the // creation to fail in certain cases, e.g. when the URL is invalid. @@ -2297,12 +2451,10 @@ return; } else { std::unique_ptr<NavigationRequest> navigation_request = - CreateNavigationRequest( + CreateNavigationRequestFromEntry( frame, *pending_entry_, new_item, reload_type, false /* is_same_document_history_load */, - false /* is_history_navigation_in_new_child */, nullptr, nullptr, - base::TimeTicks() /* input_start */, - WasActivatedOption::kUnknown); + false /* is_history_navigation_in_new_child */); if (navigation_request) { // Only add the request if was properly created. It's possible for the // creation to fail in certain cases, e.g. when the URL is invalid. @@ -2335,11 +2487,40 @@ if (!node) node = delegate_->GetFrameTree()->root(); + // Compute overrides to the LoadURLParams for |override_user_agent|, + // |should_replace_current_entry| and |has_user_gesture| that will be used + // both in the creation of the NavigationEntry and the NavigationRequest. + // Ideally, the LoadURLParams themselves would be updated, but since they are + // passed as a const reference, this is not possible. + // TODO(clamy): When we only create a NavigationRequest, move this to + // CreateNavigationRequestFromLoadURLParams. + bool override_user_agent = ShouldOverrideUserAgent(params.override_user_agent, + GetLastCommittedEntry()); + + // Don't allow an entry replacement if there is no entry to replace. + // http://crbug.com/457149 + bool should_replace_current_entry = + params.should_replace_current_entry && entries_.size(); + + // Always propagate `has_user_gesture` on Android but only when the request + // was originated by the renderer on other platforms. This is merely for + // backward compatibility as browser process user gestures create confusion in + // many tests. + bool has_user_gesture = false; +#if defined(OS_ANDROID) + has_user_gesture = params.has_user_gesture; +#else + if (params.is_renderer_initiated) + has_user_gesture = params.has_user_gesture; +#endif + // Javascript URLs should not create NavigationEntries. All other navigations // do, including navigations to chrome renderer debug URLs. std::unique_ptr<NavigationEntryImpl> entry; if (!params.url.SchemeIs(url::kJavaScriptScheme)) { - entry = CreateNavigationEntryFromLoadParams(node, params); + entry = CreateNavigationEntryFromLoadParams( + node, params, override_user_agent, should_replace_current_entry, + has_user_gesture); DiscardPendingEntry(false); SetPendingEntry(std::move(entry)); } @@ -2379,15 +2560,12 @@ // navigation_ui_data should only be present for main frame navigations. DCHECK(node->IsMainFrame() || !params.navigation_ui_data); - // TODO(clamy): Create the NavigationRequest directly from the LoadURLParams - // instead of relying on the NavigationEntry. DCHECK(pending_entry_); - std::unique_ptr<NavigationRequest> request = CreateNavigationRequest( - node, *pending_entry_, pending_entry_->GetFrameEntry(node), reload_type, - false /* is_same_document_history_load */, - false /* is_history_navigation_in_new_child */, nullptr, - params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr, - params.input_start, params.was_activated); + std::unique_ptr<NavigationRequest> request = + CreateNavigationRequestFromLoadParams( + node, params, override_user_agent, should_replace_current_entry, + has_user_gesture, reload_type, *pending_entry_, + pending_entry_->GetFrameEntry(node)); // If the navigation couldn't start, return immediately and discard the // pending NavigationEntry. @@ -2396,6 +2574,11 @@ return; } +#if DCHECK_IS_ON() + // Safety check that NavigationRequest and NavigationEntry match. + ValidateRequestMatchesEntry(request.get(), pending_entry_); +#endif + // If an interstitial page is showing, the previous renderer is blocked and // cannot make new requests. Unblock (and disable) it to allow this // navigation to succeed. The interstitial will stay visible until the @@ -2435,7 +2618,10 @@ std::unique_ptr<NavigationEntryImpl> NavigationControllerImpl::CreateNavigationEntryFromLoadParams( FrameTreeNode* node, - const LoadURLParams& params) { + const LoadURLParams& params, + bool override_user_agent, + bool should_replace_current_entry, + bool has_user_gesture) { // Browser initiated navigations might not have a blob_url_loader_factory set // in params even if the navigation is to a blob URL. If that happens, lookup // the correct url loader factory to use here. @@ -2477,39 +2663,10 @@ // Set the FTN ID (only used in non-site-per-process, for tests). entry->set_frame_tree_node_id(node->frame_tree_node_id()); - // Don't allow an entry replacement if there is no entry to replace. - // http://crbug.com/457149 - if (params.should_replace_current_entry && entries_.size() > 0) - entry->set_should_replace_entry(true); + entry->set_should_replace_entry(should_replace_current_entry); entry->set_should_clear_history_list(params.should_clear_history_list); - - bool override = false; - switch (params.override_user_agent) { - case UA_OVERRIDE_INHERIT: - override = ShouldKeepOverride(GetLastCommittedEntry()); - break; - case UA_OVERRIDE_TRUE: - override = true; - break; - case UA_OVERRIDE_FALSE: - override = false; - break; - default: - NOTREACHED(); - break; - } - entry->SetIsOverridingUserAgent(override); - -// Always propagate `has_user_gesture` on Android but only when the request -// was originated by the renderer on other platforms. This is merely for -// backward compatibility as browser process user gestures create confusion in -// many tests. -#if defined(OS_ANDROID) - entry->set_has_user_gesture(params.has_user_gesture); -#else - if (params.is_renderer_initiated) - entry->set_has_user_gesture(params.has_user_gesture); -#endif + entry->SetIsOverridingUserAgent(override_user_agent); + entry->set_has_user_gesture(has_user_gesture); switch (params.load_type) { case LOAD_TYPE_DEFAULT: @@ -2541,17 +2698,121 @@ } std::unique_ptr<NavigationRequest> -NavigationControllerImpl::CreateNavigationRequest( +NavigationControllerImpl::CreateNavigationRequestFromLoadParams( + FrameTreeNode* node, + const LoadURLParams& params, + bool override_user_agent, + bool should_replace_current_entry, + bool has_user_gesture, + ReloadType reload_type, + const NavigationEntryImpl& entry, + FrameNavigationEntry* frame_entry) { + DCHECK_EQ(-1, GetIndexOfEntry(&entry)); + GURL url_to_load; + GURL virtual_url; + bool reverse_on_redirect = false; + RewriteUrlForNavigation(params.url, browser_context_, &url_to_load, + &virtual_url, &reverse_on_redirect); + + // For DATA loads, override the virtual URL. + if (params.load_type == LOAD_TYPE_DATA) + virtual_url = params.virtual_url_for_data_url; + + if (virtual_url.is_empty()) + virtual_url = url_to_load; + + CHECK(!node->IsMainFrame() || virtual_url == entry.GetVirtualURL()); + CHECK_EQ(url_to_load, frame_entry->url()); + + // TODO(clamy): In order to remove the pending NavigationEntry, |virtual_url| + // and |reverse_on_redirect| should be stored in the NavigationRequest. + + if (!IsValidURLForNavigation(node->IsMainFrame(), virtual_url, url_to_load)) + return nullptr; + + // Determine if Previews should be used for the navigation. + PreviewsState previews_state = PREVIEWS_UNSPECIFIED; + if (!node->IsMainFrame()) { + // For subframes, use the state of the top-level frame. + previews_state = node->frame_tree() + ->root() + ->current_frame_host() + ->last_navigation_previews_state(); + } + + // Give the delegate an opportunity to adjust the previews state. + if (delegate_) + delegate_->AdjustPreviewsStateForNavigation(&previews_state); + + // This will be used to set the Navigation Timing API navigationStart + // parameter for browser navigations in new tabs (intents, tabs opened through + // "Open link in new tab"). If the navigation must wait on the current + // RenderFrameHost to execute its BeforeUnload event, the navigation start + // will be updated when the BeforeUnload ack is received. + base::TimeTicks navigation_start = base::TimeTicks::Now(); + + FrameMsg_Navigate_Type::Value navigation_type = + GetNavigationType(node->current_url(), // old_url + url_to_load, // new_url + reload_type, // reload_type + entry, // entry + *frame_entry, // frame_entry + false); // is_same_document_history_load + + // Create the NavigationParams based on |params|. + + bool is_view_source_mode = virtual_url.SchemeIs(kViewSourceScheme); + const GURL& history_url_for_data_url = + params.base_url_for_data_url.is_empty() ? GURL() : virtual_url; + CommonNavigationParams common_params( + url_to_load, params.referrer, params.transition_type, navigation_type, + !is_view_source_mode, should_replace_current_entry, + params.base_url_for_data_url, history_url_for_data_url, previews_state, + navigation_start, + params.load_type == LOAD_TYPE_HTTP_POST ? "POST" : "GET", + params.post_data, base::Optional<SourceLocation>(), + params.started_from_context_menu, has_user_gesture, InitiatorCSPInfo(), + params.input_start); + + RequestNavigationParams request_params( + override_user_agent, params.redirect_chain, common_params.url, + common_params.method, params.can_load_local_resources, + frame_entry->page_state(), entry.GetUniqueID(), + false /* is_history_navigation_in_new_child */, + entry.GetSubframeUniqueNames(node), true /* intended_as_new_entry */, + -1 /* pending_history_list_offset */, + params.should_clear_history_list ? -1 : GetLastCommittedEntryIndex(), + params.should_clear_history_list ? 0 : GetEntryCount(), + is_view_source_mode, params.should_clear_history_list); +#if defined(OS_ANDROID) + if (ValidateDataURLAsString(params.data_url_as_string)) { + request_params.data_url_as_string = params.data_url_as_string->data(); + } +#endif + + request_params.was_activated = params.was_activated; + + // A form submission may happen here if the navigation is a renderer-initiated + // form submission that took the OpenURL path. + scoped_refptr<network::ResourceRequestBody> request_body = params.post_data; + + // extra_headers in params are \n separated; NavigationRequests want \r\n. + std::string extra_headers_crlf; + base::ReplaceChars(params.extra_headers, "\n", "\r\n", &extra_headers_crlf); + return NavigationRequest::CreateBrowserInitiated( + node, common_params, request_params, !params.is_renderer_initiated, + extra_headers_crlf, *frame_entry, entry, request_body, + params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr); +} + +std::unique_ptr<NavigationRequest> +NavigationControllerImpl::CreateNavigationRequestFromEntry( FrameTreeNode* frame_tree_node, const NavigationEntryImpl& entry, FrameNavigationEntry* frame_entry, ReloadType reload_type, bool is_same_document_history_load, - bool is_history_navigation_in_new_child, - const scoped_refptr<network::ResourceRequestBody>& post_body, - std::unique_ptr<NavigationUIData> navigation_ui_data, - base::TimeTicks input_start, - WasActivatedOption was_activated) { + bool is_history_navigation_in_new_child) { GURL dest_url = frame_entry->url(); Referrer dest_referrer = frame_entry->referrer(); if (reload_type == ReloadType::ORIGINAL_REQUEST_URL && @@ -2564,28 +2825,8 @@ dest_referrer = Referrer(); } - // Don't attempt to navigate if the virtual URL is non-empty and invalid. - if (frame_tree_node->IsMainFrame()) { - const GURL& virtual_url = entry.GetVirtualURL(); - if (!virtual_url.is_valid() && !virtual_url.is_empty()) { - LOG(WARNING) << "Refusing to load for invalid virtual URL: " - << virtual_url.possibly_invalid_spec(); - return nullptr; - } - } - - // Don't attempt to navigate to non-empty invalid URLs. - if (!dest_url.is_valid() && !dest_url.is_empty()) { - LOG(WARNING) << "Refusing to load invalid URL: " - << dest_url.possibly_invalid_spec(); - return nullptr; - } - - // The renderer will reject IPC messages with URLs longer than - // this limit, so don't attempt to navigate with a longer URL. - if (dest_url.spec().size() > url::kMaxURLChars) { - LOG(WARNING) << "Refusing to load URL as it exceeds " << url::kMaxURLChars - << " characters."; + if (!IsValidURLForNavigation(frame_tree_node->IsMainFrame(), + entry.GetVirtualURL(), dest_url)) { return nullptr; } @@ -2609,9 +2850,6 @@ // RenderFrameHost to execute its BeforeUnload event, the navigation start // will be updated when the BeforeUnload ack is received. base::TimeTicks navigation_start = base::TimeTicks::Now(); - TRACE_EVENT_INSTANT_WITH_TIMESTAMP0( - "navigation,rail", "NavigationTiming navigationStart", - TRACE_EVENT_SCOPE_GLOBAL, navigation_start); FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType( frame_tree_node->current_url(), // old_url @@ -2620,11 +2858,41 @@ entry, // entry *frame_entry, // frame_entry is_same_document_history_load); // is_same_document_history_load + + // A form submission may happen here if the navigation is a + // back/forward/reload navigation that does a form resubmission. + scoped_refptr<network::ResourceRequestBody> request_body; + std::string post_content_type; + if (frame_entry->method() == "POST") { + request_body = frame_entry->GetPostData(&post_content_type); + // Might have a LF at end. + post_content_type = + base::TrimWhitespaceASCII(post_content_type, base::TRIM_ALL) + .as_string(); + } + + // Create the NavigationParams based on |entry| and |frame_entry|. + CommonNavigationParams common_params = entry.ConstructCommonNavigationParams( + *frame_entry, request_body, dest_url, dest_referrer, navigation_type, + previews_state, navigation_start, base::TimeTicks() /* input_start */); + + // TODO(clamy): |intended_as_new_entry| below should always be false once + // Reload no longer leads to this being called for a pending NavigationEntry + // of index -1. + RequestNavigationParams request_params = + entry.ConstructRequestNavigationParams( + *frame_entry, common_params.url, common_params.method, + is_history_navigation_in_new_child, + entry.GetSubframeUniqueNames(frame_tree_node), + GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + GetIndexOfEntry(&entry), GetLastCommittedEntryIndex(), + GetEntryCount()); + request_params.post_content_type = post_content_type; + return NavigationRequest::CreateBrowserInitiated( - frame_tree_node, dest_url, dest_referrer, *frame_entry, entry, - navigation_type, previews_state, is_same_document_history_load, - is_history_navigation_in_new_child, post_body, navigation_start, this, - std::move(navigation_ui_data), input_start, was_activated); + frame_tree_node, common_params, request_params, + !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, + entry, request_body, nullptr /* navigation_ui_data */); } void NavigationControllerImpl::NotifyNavigationEntryCommitted(
diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index b4ef12e..afaa65e 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h
@@ -232,6 +232,13 @@ // navigation failed due to an SSL error. void SetPendingNavigationSSLError(bool error); +// Returns true if the string corresponds to a valid data URL, false +// otherwise. +#if defined(OS_ANDROID) + static bool ValidateDataURLAsString( + const scoped_refptr<const base::RefCountedString>& data_url_as_string); +#endif + private: friend class RestoreHelper; @@ -279,24 +286,47 @@ // Creates and returns a NavigationEntry based on |load_params| for a // navigation in |node|. + // |override_user_agent|, |should_replace_current_entry| and + // |has_user_gesture| will override the values from |load_params|. The same + // values should be passed to CreateNavigationRequestFromLoadParams. std::unique_ptr<NavigationEntryImpl> CreateNavigationEntryFromLoadParams( FrameTreeNode* node, - const LoadURLParams& load_params); + const LoadURLParams& load_params, + bool override_user_agent, + bool should_replace_current_entry, + bool has_user_gesture); - // Creates and returns a NavigationRequest based on the provided parameters. + // Creates and returns a NavigationRequest based on |load_params| for a + // new navigation in |node|. // Will return nullptr if the parameters are invalid and the navigation cannot // start. - std::unique_ptr<NavigationRequest> CreateNavigationRequest( + // |override_user_agent|, |should_replace_current_entry| and + // |has_user_gesture| will override the values from |load_params|. The same + // values should be passed to CreateNavigationEntryFromLoadParams. + // TODO(clamy): Remove the dependency on NavigationEntry and + // FrameNavigationEntry. + std::unique_ptr<NavigationRequest> CreateNavigationRequestFromLoadParams( + FrameTreeNode* node, + const LoadURLParams& load_params, + bool override_user_agent, + bool should_replace_current_entry, + bool has_user_gesture, + ReloadType reload_type, + const NavigationEntryImpl& entry, + FrameNavigationEntry* frame_entry); + + // Creates and returns a NavigationRequest for a navigation to |entry|. Will + // return nullptr if the parameters are invalid and the navigation cannot + // start. + // TODO(clamy): Ensure this is only called for navigations to existing + // NavigationEntries. + std::unique_ptr<NavigationRequest> CreateNavigationRequestFromEntry( FrameTreeNode* frame_tree_node, const NavigationEntryImpl& entry, FrameNavigationEntry* frame_entry, ReloadType reload_type, bool is_same_document_history_load, - bool is_history_navigation_in_new_child, - const scoped_refptr<network::ResourceRequestBody>& post_body, - std::unique_ptr<NavigationUIData> navigation_ui_data, - base::TimeTicks input_start, - WasActivatedOption was_activated); + bool is_history_navigation_in_new_child); // Returns whether there is a pending NavigationEntry whose unique ID matches // the given NavigationHandle's pending_nav_entry_id.
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index bece944..47db0eb 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -20,6 +20,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "components/url_formatter/url_formatter.h" +#include "content/browser/frame_host/navigation_controller_impl.h" #include "content/common/content_constants_internal.h" #include "content/common/navigation_params.h" #include "content/common/page_state_serialization.h" @@ -732,18 +733,8 @@ intended_as_new_entry, pending_offset_to_send, current_offset_to_send, current_length_to_send, IsViewSourceMode(), should_clear_history_list()); #if defined(OS_ANDROID) - if (GetDataURLAsString() && - GetDataURLAsString()->size() <= kMaxLengthOfDataURLString) { - // The number of characters that is enough for validating a data: URI. From - // the GURL's POV, the only important part here is scheme, it doesn't check - // the actual content. Thus we can take only the prefix of the url, to avoid - // unneeded copying of a potentially long string. - const size_t kDataUriPrefixMaxLen = 64; - GURL data_url(std::string( - GetDataURLAsString()->front_as<char>(), - std::min(GetDataURLAsString()->size(), kDataUriPrefixMaxLen))); - if (data_url.is_valid() && data_url.SchemeIs(url::kDataScheme)) - request_params.data_url_as_string = GetDataURLAsString()->data(); + if (NavigationControllerImpl::ValidateDataURLAsString(GetDataURLAsString())) { + request_params.data_url_as_string = GetDataURLAsString()->data(); } #endif return request_params;
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index b86fa9fc..d920ead 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -281,39 +281,17 @@ // static std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated( FrameTreeNode* frame_tree_node, - const GURL& dest_url, - const Referrer& dest_referrer, + const CommonNavigationParams& common_params, + const RequestNavigationParams& request_params, + bool browser_initiated, + const std::string& extra_headers, const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, - FrameMsg_Navigate_Type::Value navigation_type, - PreviewsState previews_state, - bool is_same_document_history_load, - bool is_history_navigation_in_new_child, const scoped_refptr<network::ResourceRequestBody>& post_body, - base::TimeTicks navigation_start, - NavigationControllerImpl* controller, - std::unique_ptr<NavigationUIData> navigation_ui_data, - base::TimeTicks input_start, - WasActivatedOption was_activated) { - // A form submission happens either because the navigation is a - // renderer-initiated form submission that took the OpenURL path or a - // back/forward/reload navigation the does a form resubmission. - scoped_refptr<network::ResourceRequestBody> request_body; - std::string post_content_type; - if (post_body) { - // Standard form submission from the renderer. - request_body = post_body; - } else if (frame_entry.method() == "POST") { - // Form resubmission during a back/forward/reload navigation. - request_body = frame_entry.GetPostData(&post_content_type); - // Might have a LF at end. - post_content_type = - base::TrimWhitespaceASCII(post_content_type, base::TRIM_ALL) - .as_string(); - } + std::unique_ptr<NavigationUIData> navigation_ui_data) { // TODO(arthursonzogni): Form submission with the "GET" method is possible. // This is not currently handled here. - bool is_form_submission = !!request_body; + bool is_form_submission = !!post_body; base::Optional<url::Origin> initiator = frame_tree_node->IsMainFrame() @@ -321,31 +299,10 @@ : base::Optional<url::Origin>( frame_tree_node->frame_tree()->root()->current_origin()); - // While the navigation was started via the LoadURL path it may have come from - // the renderer in the first place as part of OpenURL. - bool browser_initiated = !entry.is_renderer_initiated(); - - CommonNavigationParams common_params = entry.ConstructCommonNavigationParams( - frame_entry, request_body, dest_url, dest_referrer, navigation_type, - previews_state, navigation_start, input_start); - - RequestNavigationParams request_params = - entry.ConstructRequestNavigationParams( - frame_entry, common_params.url, common_params.method, - is_history_navigation_in_new_child, - entry.GetSubframeUniqueNames(frame_tree_node), - controller->GetPendingEntryIndex() == -1, - controller->GetIndexOfEntry(&entry), - controller->GetLastCommittedEntryIndex(), - controller->GetEntryCount()); - request_params.post_content_type = post_content_type; - request_params.was_activated = was_activated; - std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest( frame_tree_node, common_params, mojom::BeginNavigationParams::New( - entry.extra_headers(), net::LOAD_NORMAL, - false /* skip_service_worker */, + extra_headers, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::LOCATION, blink::WebMixedContentContextType::kBlockable, is_form_submission, GURL() /* searchable_form_url */,
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 7d37652..233111e 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -32,7 +32,6 @@ class FrameNavigationEntry; class FrameTreeNode; -class NavigationControllerImpl; class NavigationHandleImpl; class NavigationURLLoader; class NavigationData; @@ -80,22 +79,20 @@ }; // Creates a request for a browser-intiated navigation. + // Note: this is sometimes called for renderer-initiated navigations going + // through the OpenURL path. |browser_initiated| should be false in that case. + // TODO(clamy): Rename this function and consider merging it with + // CreateRendererInitiated. static std::unique_ptr<NavigationRequest> CreateBrowserInitiated( FrameTreeNode* frame_tree_node, - const GURL& dest_url, - const Referrer& dest_referrer, + const CommonNavigationParams& common_params, + const RequestNavigationParams& request_params, + bool browser_initiated, + const std::string& extra_headers, const FrameNavigationEntry& frame_entry, const NavigationEntryImpl& entry, - FrameMsg_Navigate_Type::Value navigation_type, - PreviewsState previews_state, - bool is_same_document_history_load, - bool is_history_navigation_in_new_child, const scoped_refptr<network::ResourceRequestBody>& post_body, - base::TimeTicks navigation_start, - NavigationControllerImpl* controller, - std::unique_ptr<NavigationUIData> navigation_ui_data, - base::TimeTicks input_start, - WasActivatedOption was_activated); + std::unique_ptr<NavigationUIData> navigation_ui_data); // Creates a request for a renderer-intiated navigation. // Note: |body| is sent to the IO thread when calling BeginNavigation, and
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 7d7544d..52771f1 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -324,6 +324,9 @@ ReloadType reload_type, RestoreType restore_type) { TRACE_EVENT0("browser,navigation", "NavigatorImpl::Navigate"); + TRACE_EVENT_INSTANT_WITH_TIMESTAMP0( + "navigation,rail", "NavigationTiming navigationStart", + TRACE_EVENT_SCOPE_GLOBAL, request->common_params().navigation_start); const GURL& dest_url = request->common_params().url; FrameTreeNode* frame_tree_node = request->frame_tree_node();
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index a5e33ca..9dbcbb9 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -436,6 +436,8 @@ const NavigationEntryImpl& entry) { // Tests currently only navigate using main frame FrameNavigationEntries. FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); + FrameTreeNode* frame_tree_node = + manager->current_frame_host()->frame_tree_node(); NavigationControllerImpl* controller = static_cast<NavigationControllerImpl*>(manager->current_frame_host() ->frame_tree_node() @@ -445,13 +447,37 @@ entry.restore_type() == RestoreType::NONE ? FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT : FrameMsg_Navigate_Type::RESTORE; + scoped_refptr<network::ResourceRequestBody> request_body; + std::string post_content_type; + if (frame_entry->method() == "POST") { + request_body = frame_entry->GetPostData(&post_content_type); + // Might have a LF at end. + post_content_type = + base::TrimWhitespaceASCII(post_content_type, base::TRIM_ALL) + .as_string(); + } + + CommonNavigationParams common_params = + entry.ConstructCommonNavigationParams( + *frame_entry, request_body, frame_entry->url(), + frame_entry->referrer(), navigate_type, PREVIEWS_UNSPECIFIED, + base::TimeTicks::Now(), base::TimeTicks::Now()); + RequestNavigationParams request_params = + entry.ConstructRequestNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller->GetPendingEntryIndex() == + -1 /* intended_as_new_entry */, + controller->GetIndexOfEntry(&entry), + controller->GetLastCommittedEntryIndex(), + controller->GetEntryCount()); + request_params.post_content_type = post_content_type; + std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - manager->frame_tree_node_, frame_entry->url(), - frame_entry->referrer(), *frame_entry, entry, navigate_type, - PREVIEWS_UNSPECIFIED, false, false, nullptr, base::TimeTicks::Now(), - controller, nullptr, base::TimeTicks(), - WasActivatedOption::kUnknown); + frame_tree_node, common_params, request_params, + !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, + entry, request_body, nullptr /* navigation_ui_data */); // Simulates request creation that triggers the 1st internal call to // GetFrameHostForNavigation. @@ -2818,14 +2844,27 @@ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */, nullptr /* blob_url_loader_factory */); FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); + FrameTreeNode* frame_tree_node = + manager->current_frame_host()->frame_tree_node(); + CommonNavigationParams common_params = entry.ConstructCommonNavigationParams( + *frame_entry, nullptr, frame_entry->url(), frame_entry->referrer(), + FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, + base::TimeTicks::Now(), base::TimeTicks::Now()); + RequestNavigationParams request_params = + entry.ConstructRequestNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + static_cast<NavigationControllerImpl&>(controller()) + .GetIndexOfEntry(&entry), + controller().GetLastCommittedEntryIndex(), + controller().GetEntryCount()); + std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - contents()->GetFrameTree()->root(), frame_entry->url(), - frame_entry->referrer(), *frame_entry, entry, - FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, - false, false, nullptr, base::TimeTicks::Now(), - static_cast<NavigationControllerImpl*>(&controller()), nullptr, - base::TimeTicks(), WasActivatedOption::kUnknown); + frame_tree_node, common_params, request_params, + !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, + entry, nullptr /* request_body */, nullptr /* navigation_ui_data */); manager->DidCreateNavigationRequest(navigation_request.get()); // As the initial RenderFrame was not live, the new RenderFrameHost should be @@ -2881,14 +2920,27 @@ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */, nullptr /* blob_url_loader_factory */); FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); + FrameTreeNode* frame_tree_node = + manager->current_frame_host()->frame_tree_node(); + CommonNavigationParams common_params = entry.ConstructCommonNavigationParams( + *frame_entry, nullptr, frame_entry->url(), frame_entry->referrer(), + FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, + base::TimeTicks::Now(), base::TimeTicks::Now()); + RequestNavigationParams request_params = + entry.ConstructRequestNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + static_cast<NavigationControllerImpl&>(controller()) + .GetIndexOfEntry(&entry), + controller().GetLastCommittedEntryIndex(), + controller().GetEntryCount()); + std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - contents()->GetFrameTree()->root(), frame_entry->url(), - frame_entry->referrer(), *frame_entry, entry, - FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, - false, false, nullptr, base::TimeTicks::Now(), - static_cast<NavigationControllerImpl*>(&controller()), nullptr, - base::TimeTicks(), WasActivatedOption::kUnknown); + frame_tree_node, common_params, request_params, + !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, + entry, nullptr /* request_body */, nullptr /* navigation_ui_data */); manager->DidCreateNavigationRequest(navigation_request.get()); // The current WebUI should still be in place and the pending WebUI should be @@ -2941,14 +2993,27 @@ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */, nullptr /* blob_url_loader_factory */); FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get(); + FrameTreeNode* frame_tree_node = + manager->current_frame_host()->frame_tree_node(); + CommonNavigationParams common_params = entry.ConstructCommonNavigationParams( + *frame_entry, nullptr, frame_entry->url(), frame_entry->referrer(), + FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, + base::TimeTicks::Now(), base::TimeTicks::Now()); + RequestNavigationParams request_params = + entry.ConstructRequestNavigationParams( + *frame_entry, common_params.url, common_params.method, false, + entry.GetSubframeUniqueNames(frame_tree_node), + controller().GetPendingEntryIndex() == -1 /* intended_as_new_entry */, + static_cast<NavigationControllerImpl&>(controller()) + .GetIndexOfEntry(&entry), + controller().GetLastCommittedEntryIndex(), + controller().GetEntryCount()); + std::unique_ptr<NavigationRequest> navigation_request = NavigationRequest::CreateBrowserInitiated( - contents()->GetFrameTree()->root(), frame_entry->url(), - frame_entry->referrer(), *frame_entry, entry, - FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED, - false, false, nullptr, base::TimeTicks::Now(), - static_cast<NavigationControllerImpl*>(&controller()), nullptr, - base::TimeTicks(), WasActivatedOption::kUnknown); + frame_tree_node, common_params, request_params, + !entry.is_renderer_initiated(), entry.extra_headers(), *frame_entry, + entry, nullptr /* request_body */, nullptr /* navigation_ui_data */); manager->DidCreateNavigationRequest(navigation_request.get()); // The current WebUI should still be in place and there should be a new
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc index 497ee22..2a29c367 100644 --- a/content/browser/loader/prefetch_url_loader_service.cc +++ b/content/browser/loader/prefetch_url_loader_service.cc
@@ -5,6 +5,7 @@ #include "content/browser/loader/prefetch_url_loader_service.h" #include "base/feature_list.h" +#include "base/time/default_tick_clock.h" #include "content/browser/loader/prefetch_url_loader.h" #include "content/browser/url_loader_factory_getter.h" #include "content/public/browser/content_browser_client.h" @@ -38,7 +39,8 @@ PrefetchURLLoaderService::PrefetchURLLoaderService() : signed_exchange_prefetch_metric_recorder_( - base::MakeRefCounted<SignedExchangePrefetchMetricRecorder>()) {} + base::MakeRefCounted<SignedExchangePrefetchMetricRecorder>( + base::DefaultTickClock::GetInstance())) {} void PrefetchURLLoaderService::InitializeResourceContext( ResourceContext* resource_context,
diff --git a/content/browser/renderer_host/input/fling_browsertest.cc b/content/browser/renderer_host/input/fling_browsertest.cc index 343ae569..14afc422 100644 --- a/content/browser/renderer_host/input/fling_browsertest.cc +++ b/content/browser/renderer_host/input/fling_browsertest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/test/browser_test_utils.h" @@ -93,7 +92,7 @@ void LoadPageWithOOPIF() { // navigate main frame to URL. GURL main_url(embedded_test_server()->GetURL( - "a.com", "/frame_tree/scrollable_page_with_positioned_frame.html")); + "a.com", "/frame_tree/page_with_positioned_frame.html")); EXPECT_TRUE(NavigateToURL(shell(), main_url)); // Navigate oopif to URL. @@ -120,21 +119,17 @@ iframe_node->current_frame_host()->GetRenderWidgetHost()->GetView()); } - void SimulateTouchscreenFling( - RenderWidgetHostImpl* render_widget_host, - const gfx::Vector2dF& fling_velocity = gfx::Vector2dF(0.f, -2000.f)) { + void SimulateTouchscreenFling(RenderWidgetHostImpl* render_widget_host) { DCHECK(render_widget_host); // Send a GSB to start scrolling sequence. - auto input_msg_watcher = std::make_unique<InputMsgWatcher>( - render_widget_host, blink::WebInputEvent::kGestureScrollBegin); blink::WebGestureEvent gesture_scroll_begin( blink::WebGestureEvent::kGestureScrollBegin, blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow()); gesture_scroll_begin.SetSourceDevice(blink::kWebGestureDeviceTouchscreen); gesture_scroll_begin.data.scroll_begin.delta_hint_units = blink::WebGestureEvent::ScrollUnits::kPrecisePixels; - gesture_scroll_begin.data.scroll_begin.delta_x_hint = fling_velocity.x(); - gesture_scroll_begin.data.scroll_begin.delta_y_hint = fling_velocity.y(); + gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f; + gesture_scroll_begin.data.scroll_begin.delta_y_hint = -5.f; const gfx::PointF scroll_location_in_widget(1, 1); const gfx::PointF scroll_location_in_root = child_view_ ? child_view_->TransformPointToRootCoordSpaceF( @@ -147,31 +142,26 @@ gesture_scroll_begin.SetPositionInWidget(scroll_location_in_widget); gesture_scroll_begin.SetPositionInScreen(scroll_location_in_screen); render_widget_host->ForwardGestureEvent(gesture_scroll_begin); - input_msg_watcher->GetAckStateWaitIfNecessary(); // Send a GFS. blink::WebGestureEvent gesture_fling_start( blink::WebGestureEvent::kGestureFlingStart, blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow()); gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchscreen); - gesture_fling_start.data.fling_start.velocity_x = fling_velocity.x(); - gesture_fling_start.data.fling_start.velocity_y = fling_velocity.y(); + gesture_fling_start.data.fling_start.velocity_x = 0.f; + gesture_fling_start.data.fling_start.velocity_y = -2000.f; gesture_fling_start.SetPositionInWidget(scroll_location_in_widget); gesture_fling_start.SetPositionInScreen(scroll_location_in_screen); render_widget_host->ForwardGestureEvent(gesture_fling_start); } - void SimulateTouchpadFling( - RenderWidgetHostImpl* render_widget_host, - const gfx::Vector2dF& fling_velocity = gfx::Vector2dF(0.f, -2000.f)) { + void SimulateTouchpadFling(RenderWidgetHostImpl* render_widget_host) { DCHECK(render_widget_host); // Send a wheel event to start scrolling sequence. auto input_msg_watcher = std::make_unique<InputMsgWatcher>( - render_widget_host, blink::WebInputEvent::kGestureScrollBegin); + GetWidgetHost(), blink::WebInputEvent::kMouseWheel); blink::WebMouseWheelEvent wheel_event = - SyntheticWebMouseWheelEventBuilder::Build( - 10, 10, fling_velocity.x() / 1000, fling_velocity.y() / 1000, 0, - true); + SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true); wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan; const gfx::PointF position_in_widget(1, 1); const gfx::PointF position_in_root = @@ -185,15 +175,15 @@ wheel_event.SetPositionInWidget(position_in_widget); wheel_event.SetPositionInScreen(position_in_screen); render_widget_host->ForwardWheelEvent(wheel_event); - input_msg_watcher->GetAckStateWaitIfNecessary(); + input_msg_watcher->WaitForAck(); // Send a GFS. blink::WebGestureEvent gesture_fling_start( blink::WebGestureEvent::kGestureFlingStart, blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow()); gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchpad); - gesture_fling_start.data.fling_start.velocity_x = fling_velocity.x(); - gesture_fling_start.data.fling_start.velocity_y = fling_velocity.y(); + gesture_fling_start.data.fling_start.velocity_x = 0.f; + gesture_fling_start.data.fling_start.velocity_y = -2000.f; gesture_fling_start.SetPositionInWidget(position_in_widget); gesture_fling_start.SetPositionInScreen(position_in_screen); render_widget_host->ForwardGestureEvent(gesture_fling_start); @@ -222,36 +212,25 @@ run_loop.Run(); } - void WaitForOOPIFScroll(FrameTreeNode* iframe_node, - int target_scroll_offset = 100, - bool upward = false) { - DCHECK(iframe_node); - double scroll_top = - EvalJs(iframe_node->current_frame_host(), "window.scrollY") - .ExtractDouble(); + void WaitForChildScroll() { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + ASSERT_EQ(1U, root->child_count()); + FrameTreeNode* iframe_node = root->child_at(0); + int scroll_top = EvalJs(iframe_node->current_frame_host(), "window.scrollY") + .ExtractDouble(); // scrollTop > 0 is not enough since the first progressFling is called from - // FlingController::ProcessGestureFlingStart. Wait for scrollTop to reach - // target_scroll_offset to make sure that ProgressFling has been called - // through FlingScheduler at least once. - while ((upward && scroll_top > target_scroll_offset) || - (!upward && scroll_top < target_scroll_offset)) { + // FlingController::ProcessGestureFlingStart. Wait for scrollTop to exceed + // 100 pixels to make sure that ProgressFling has been called through + // FlingScheduler at least once. + while (scroll_top < 100) { GiveItSomeTime(); scroll_top = EvalJs(iframe_node->current_frame_host(), "window.scrollY") .ExtractDouble(); } } - FrameTreeNode* GetRootNode() { - return static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root(); - } - - FrameTreeNode* GetChildNode() { - FrameTreeNode* root = GetRootNode(); - return root->child_at(0); - } - std::unique_ptr<base::RunLoop> run_loop_; RenderWidgetHostViewBase* child_view_ = nullptr; RenderWidgetHostViewBase* root_view_ = nullptr; @@ -260,10 +239,6 @@ DISALLOW_COPY_AND_ASSIGN(BrowserSideFlingBrowserTest); }; -// On Mac we don't have any touchscreen/touchpad fling events (GFS/GFC). -// Instead, the OS keeps sending wheel events when the user lifts their fingers -// from touchpad. -#if !defined(OS_MACOSX) IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchscreenFling) { LoadURL(kBrowserFlingDataURL); SimulateTouchscreenFling(GetWidgetHost()); @@ -306,86 +281,23 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchscreenFlingInOOPIF) { LoadPageWithOOPIF(); SimulateTouchscreenFling(child_view_->host()); - WaitForOOPIFScroll(GetChildNode()); + WaitForChildScroll(); } IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFlingInOOPIF) { LoadPageWithOOPIF(); - SimulateTouchpadFling(child_view_->host()); - WaitForOOPIFScroll(GetChildNode()); -} -IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, - TouchscreenFlingBubblesFromOOPIF) { - LoadPageWithOOPIF(); - // Scroll the parent down so that it is scrollable upward. - EXPECT_TRUE( - ExecJs(GetRootNode()->current_frame_host(), "window.scrollTo(0, 20)")); - // We expect to have window.scrollY == 20 after scrolling but with zoom for - // dsf enabled on android we get window.scrollY == 19 (see - // https://crbug.com/891860). - WaitForOOPIFScroll(GetRootNode(), 19); - - // Fling and wait for the parent to scroll upward. - gfx::Vector2d fling_velocity(0, 2000); - SimulateTouchscreenFling(child_view_->host(), fling_velocity); - WaitForOOPIFScroll(GetRootNode(), 15, true /* upward */); + SimulateTouchscreenFling(child_view_->host()); + WaitForChildScroll(); } -// Flaky, probably because of https://crbug.com/892656 -#define MAYBE_TouchpadFlingBubblesFromOOPIF \ - DISABLED_TouchpadFlingBubblesFromOOPIF -IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, - MAYBE_TouchpadFlingBubblesFromOOPIF) { - LoadPageWithOOPIF(); - // Scroll the parent down so that it is scrollable upward. - EXPECT_TRUE( - ExecJs(GetRootNode()->current_frame_host(), "window.scrollTo(0, 20)")); - // We expect to have window.scrollY == 20 after scrolling but with zoom for - // dsf enabled on android we get window.scrollY == 19 (see - // https://crbug.com/891860). - WaitForOOPIFScroll(GetRootNode(), 19); - - // Fling and wait for the parent to scroll upward. - gfx::Vector2d fling_velocity(0, 2000); - SimulateTouchpadFling(child_view_->host(), fling_velocity); - WaitForOOPIFScroll(GetRootNode(), 15, true /* upward */); -} -IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, GFCGetsBubbledFromOOPIF) { - LoadPageWithOOPIF(); - // Scroll the parent down so that it is scrollable upward. - EXPECT_TRUE( - ExecJs(GetRootNode()->current_frame_host(), "window.scrollTo(0, 20)")); - // We expect to have window.scrollY == 20 after scrolling but with zoom for - // dsf enabled on android we get window.scrollY == 19 (see - // https://crbug.com/891860). - WaitForOOPIFScroll(GetRootNode(), 19); - - // Fling and wait for the parent to scroll upward. - gfx::Vector2d fling_velocity(0, 2000); - SimulateTouchscreenFling(child_view_->host(), fling_velocity); - WaitForOOPIFScroll(GetRootNode(), 15, true /* upward */); - - // Send a GFC to the child and wait for it to get bubbled. - auto input_msg_watcher = std::make_unique<InputMsgWatcher>( - GetWidgetHost(), blink::WebInputEvent::kGestureFlingCancel); - blink::WebGestureEvent gesture_fling_cancel( - blink::WebGestureEvent::kGestureFlingCancel, - blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow()); - gesture_fling_cancel.SetSourceDevice(blink::kWebGestureDeviceTouchscreen); - - const gfx::PointF location_in_widget(1, 1); - const gfx::PointF location_in_root = - child_view_->TransformPointToRootCoordSpaceF(location_in_widget); - const gfx::PointF location_in_screen = - location_in_root + root_view_->GetViewBounds().OffsetFromOrigin(); - gesture_fling_cancel.SetPositionInWidget(location_in_widget); - gesture_fling_cancel.SetPositionInScreen(location_in_screen); - child_view_->host()->ForwardGestureEvent(gesture_fling_cancel); - input_msg_watcher->GetAckStateWaitIfNecessary(); -} - +// Disabled on MacOS because it doesn't support touchscreen scroll. +#if defined(OS_MACOSX) +#define MAYBE_ScrollEndGeneratedForFilteredFling \ + DISABLED_ScrollEndGeneratedForFilteredFling +#else // Flaky, see https://crbug.com/850455 #define MAYBE_ScrollEndGeneratedForFilteredFling \ DISABLED_ScrollEndGeneratedForFilteredFling +#endif IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, MAYBE_ScrollEndGeneratedForFilteredFling) { LoadURL(kTouchActionFilterDataURL); @@ -436,6 +348,5 @@ EXPECT_EQ(InputEventAckSource::BROWSER, scroll_end_watcher->last_event_ack_source()); } -#endif // !defined(OS_MACOSX) } // namespace content
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index f72a8f5..899b712 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -590,9 +590,8 @@ touch_action_filter_.OnSetTouchAction(cc::kTouchActionAuto); } -void InputRouterImpl::OnHasTouchEventHandlersForTest(bool has_handlers) { - touch_action_filter_.OnHasTouchEventHandlers(has_handlers); - // TODO(ajwong): Why doesn't this change |touch_event_queue_|? +void InputRouterImpl::ForceResetTouchActionForTest() { + touch_action_filter_.ForceResetTouchActionForTest(); } void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h index 3edcf79..0582b35 100644 --- a/content/browser/renderer_host/input/input_router_impl.h +++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -107,7 +107,7 @@ return frame_host_binding_; } - void OnHasTouchEventHandlersForTest(bool has_handlers); + void ForceResetTouchActionForTest(); private: friend class InputRouterImplTest;
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc index 249640d..da66a5d 100644 --- a/content/browser/renderer_host/input/touch_action_filter.cc +++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -231,6 +231,11 @@ return false; } +void TouchActionFilter::ForceResetTouchActionForTest() { + allowed_touch_action_.reset(); + scrolling_touch_action_.reset(); +} + void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) { // TODO(https://crbug.com/849819): add a DCHECK for // |has_touch_event_handler_|.
diff --git a/content/browser/renderer_host/input/touch_action_filter.h b/content/browser/renderer_host/input/touch_action_filter.h index 0def2d9..231a026 100644 --- a/content/browser/renderer_host/input/touch_action_filter.h +++ b/content/browser/renderer_host/input/touch_action_filter.h
@@ -69,6 +69,8 @@ void IncreaseActiveTouches(); void DecreaseActiveTouches(); + void ForceResetTouchActionForTest(); + // Debugging only. void AppendToGestureSequenceForDebugging(const char* str);
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index 4b730f7..39b30d84 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -293,9 +293,6 @@ if (view == last_fling_start_target_) last_fling_start_target_ = nullptr; - if (view == last_fling_start_bubbled_target_) - last_fling_start_bubbled_target_ = nullptr; - event_targeter_->ViewWillBeDestroyed(view); } @@ -1004,8 +1001,7 @@ DCHECK(event.GetType() == blink::WebInputEvent::kGestureScrollBegin || event.GetType() == blink::WebInputEvent::kGestureScrollUpdate || event.GetType() == blink::WebInputEvent::kGestureScrollEnd || - event.GetType() == blink::WebInputEvent::kGestureFlingStart || - event.GetType() == blink::WebInputEvent::kGestureFlingCancel); + event.GetType() == blink::WebInputEvent::kGestureFlingStart); ui::LatencyInfo latency_info = ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(event); @@ -1034,20 +1030,7 @@ } bubbling_gesture_scroll_target_.target = target_view; - } else if (event.GetType() == blink::WebInputEvent::kGestureFlingCancel) { - // GFC event must get bubbled to the same target view that the last GFS has - // been bubbled. - if (last_fling_start_bubbled_target_) { - last_fling_start_bubbled_target_->ProcessGestureEvent( - GestureEventInTarget(event, last_fling_start_bubbled_target_), - latency_info); - last_fling_start_bubbled_target_ = nullptr; - } - return; } else { // !(event.GetType() == blink::WebInputEvent::kGestureScrollBegin) - // && !(event.GetType() == - // blink::WebInputEvent::kGestureFlingCancel) - if (!bubbling_gesture_scroll_target_.target) { // The GestureScrollBegin event is not bubbled, don't bubble the rest of // the scroll events. @@ -1079,12 +1062,6 @@ bubbling_gesture_scroll_target_.target->ProcessGestureEvent( GestureEventInTarget(event, bubbling_gesture_scroll_target_.target), latency_info); - - // The GFC should be sent to the view that handles the GFS. - if (event.GetType() == blink::WebInputEvent::kGestureFlingStart) { - last_fling_start_bubbled_target_ = bubbling_gesture_scroll_target_.target; - } - if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd || event.GetType() == blink::WebInputEvent::kGestureFlingStart) { first_bubbling_scroll_target_.target = nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h index 7bcc75b..e1bf8094 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.h +++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -308,12 +308,6 @@ // Tracked for the purpose of targeting subsequent fling cancel events. RenderWidgetHostViewBase* last_fling_start_target_ = nullptr; - // During scroll bubbling we bubble the GFS to the target view so that its - // fling controller takes care of flinging. In this case we should also send - // the GFC to the bubbling target so that the fling controller currently in - // charge of the fling progress could handle the fling cancellelation as well. - RenderWidgetHostViewBase* last_fling_start_bubbled_target_ = nullptr; - // Tracked for the purpose of providing a root_view when dispatching emulated // touch/gesture events. RenderWidgetHostViewBase* last_emulated_event_root_view_;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 0ba4a66..10b41c9 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -527,24 +527,6 @@ ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS || ack_result == INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE; -// The inertial events on Mac should still get bubbled since there is no GFS to -// bubble and the inertial events are received from the OS. -#if !defined(OS_MACOSX) - // When a GFS is bubbled, we still send it to the fling controller of the - // child view to finish the scroll sequence. However the GSU and GSE events - // that are generated by the child view's fling controller do not need to get - // bubbled since the GFS event itself is bubbled and the target's fling - // controller will take care of flinging. - if ((event.GetType() == blink::WebInputEvent::kGestureScrollEnd && - event.data.scroll_end.inertial_phase == - blink::WebGestureEvent::kMomentumPhase) || - (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate && - event.data.scroll_update.inertial_phase == - blink::WebGestureEvent::kMomentumPhase)) { - return; - } -#endif // defined(OS_MACOSX) - if ((event.GetType() == blink::WebInputEvent::kGestureScrollBegin) && should_bubble) { DCHECK(!is_scroll_sequence_bubbling_); @@ -563,8 +545,7 @@ should_bubble) || event.GetType() == blink::WebInputEvent::kGestureScrollUpdate || event.GetType() == blink::WebInputEvent::kGestureScrollEnd || - event.GetType() == blink::WebInputEvent::kGestureFlingStart || - event.GetType() == blink::WebInputEvent::kGestureFlingCancel) { + event.GetType() == blink::WebInputEvent::kGestureFlingStart) { frame_connector_->BubbleScrollEvent(event); } }
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 71f632e6..8ff295b6 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -4788,7 +4788,7 @@ static_cast<InputRouterImpl*>( static_cast<RenderWidgetHostImpl*>(rwhva_root_->GetRenderWidgetHost()) ->input_router()) - ->OnHasTouchEventHandlersForTest(true); + ->ForceResetTouchActionForTest(); } SendPinchBeginEndSequence(rwhva_root_, bounds.CenterPoint(), rwhi_child_);
diff --git a/content/browser/web_contents/web_contents_ns_view_bridge.mm b/content/browser/web_contents/web_contents_ns_view_bridge.mm index 90181ae..68516c32 100644 --- a/content/browser/web_contents/web_contents_ns_view_bridge.mm +++ b/content/browser/web_contents/web_contents_ns_view_bridge.mm
@@ -50,6 +50,10 @@ NSRect ns_bounds_in_superview = [[cocoa_view_ superview] convertRect:ns_bounds_in_window fromView:nil]; [cocoa_view_ setFrame:ns_bounds_in_superview]; + // Ensure that the child RenderWidgetHostViews have the same frame as the + // WebContentsView. + for (NSView* child in [cocoa_view_ subviews]) + [child setFrame:[cocoa_view_ bounds]]; [cocoa_view_ setHidden:NO]; }
diff --git a/content/browser/web_package/signed_exchange_loader.cc b/content/browser/web_package/signed_exchange_loader.cc index 85a3ced..f4324a6d 100644 --- a/content/browser/web_package/signed_exchange_loader.cc +++ b/content/browser/web_package/signed_exchange_loader.cc
@@ -33,6 +33,8 @@ namespace { constexpr char kLoadResultHistogram[] = "SignedExchange.LoadResult"; +constexpr char kPrefetchLoadResultHistogram[] = + "SignedExchange.Prefetch.LoadResult"; net::RedirectInfo CreateRedirectInfo(const GURL& new_url, const GURL& outer_request_url) { @@ -129,6 +131,11 @@ DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled()); DCHECK(outer_request_url_.is_valid()); + if (!(load_flags_ & net::LOAD_PREFETCH)) { + metric_recorder_->OnSignedExchangeNonPrefetch( + outer_request_url_, outer_response_.response_time); + } + // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#privacy-considerations // This can be difficult to determine when the exchange is being loaded from // local disk, but when the client itself requested the exchange over a @@ -136,8 +143,15 @@ // transport layer, and MUST NOT accept exchanges transferred over plain HTTP // without TLS. [spec text] if (!IsOriginSecure(outer_request_url)) { - UMA_HISTOGRAM_ENUMERATION(kLoadResultHistogram, - SignedExchangeLoadResult::kSXGServedFromNonHTTPS); + const SignedExchangeLoadResult result = + SignedExchangeLoadResult::kSXGServedFromNonHTTPS; + UMA_HISTOGRAM_ENUMERATION(kLoadResultHistogram, result); + if (load_flags_ & net::LOAD_PREFETCH) { + UMA_HISTOGRAM_ENUMERATION(kPrefetchLoadResultHistogram, result); + metric_recorder_->OnSignedExchangePrefetchFinished( + outer_request_url_, outer_response_.response_time); + } + devtools_proxy_->ReportError( "Signed exchange response from non secure origin is not supported.", base::nullopt /* error_field */); @@ -282,9 +296,10 @@ const network::ResourceResponseHead& resource_response, std::unique_ptr<net::SourceStream> payload_stream) { UMA_HISTOGRAM_ENUMERATION(kLoadResultHistogram, result); - if (load_flags_ & net::LOAD_PREFETCH) { - metric_recorder_->OnSignedExchangePrefetchFinished(request_url, error); + UMA_HISTOGRAM_ENUMERATION(kPrefetchLoadResultHistogram, result); + metric_recorder_->OnSignedExchangePrefetchFinished( + outer_request_url_, outer_response_.response_time); } if (error) { @@ -358,6 +373,7 @@ // TODO(https://crbug.com/803774): Fill the data length information too. network::URLLoaderCompletionStatus status; status.error_code = result; + status.completion_time = base::TimeTicks::Now(); if (ssl_info_) { DCHECK((url_loader_options_ &
diff --git a/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc b/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc index e83902c..605c3f2 100644 --- a/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc +++ b/content/browser/web_package/signed_exchange_prefetch_metric_recorder.cc
@@ -4,20 +4,113 @@ #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h" -#include "content/public/browser/browser_thread.h" +#include "base/metrics/histogram_macros.h" +#include "base/time/tick_clock.h" namespace content { -SignedExchangePrefetchMetricRecorder::SignedExchangePrefetchMetricRecorder() = - default; +constexpr size_t kMaxEntries = 256u; + +// SignedExchangePrefetchMetricRecorder will not associate prefetch +// to a navigation if they are older than |kPrefetchExpireTimeDelta|. +constexpr base::TimeDelta kPrefetchExpireTimeDelta = + base::TimeDelta::FromMilliseconds(30000); +// SignedExchangePrefetchMetricRecorder flushes expired prefetch entries once +// per |kFlushTimeoutTimeDelta|. +constexpr base::TimeDelta kFlushTimeoutTimeDelta = + base::TimeDelta::FromMilliseconds(30100); + +constexpr char kPrecisionHistogram[] = + "SignedExchange.Prefetch.Precision.30Seconds"; +constexpr char kRecallHistogram[] = "SignedExchange.Prefetch.Recall.30Seconds"; + +SignedExchangePrefetchMetricRecorder::SignedExchangePrefetchMetricRecorder( + const base::TickClock* tick_clock) + : tick_clock_(tick_clock), + flush_timer_(std::make_unique<base::OneShotTimer>(tick_clock)) { + DETACH_FROM_SEQUENCE(sequence_checker_); +} + SignedExchangePrefetchMetricRecorder::~SignedExchangePrefetchMetricRecorder() = default; void SignedExchangePrefetchMetricRecorder::OnSignedExchangePrefetchFinished( const GURL& outer_url, - net::Error error) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - // TODO(crbug.com/890180): Actually Report UMA. + base::Time response_time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (disabled_) + return; + + if (recent_prefetch_entries_.size() > kMaxEntries) { + // Avoid DoS. Turn off further metric logging to avoid skew too. + recent_prefetch_entries_.clear(); + disabled_ = true; + return; + } + + // Update |prefetch_time| for an existing entry. + recent_prefetch_entries_.insert_or_assign( + std::make_pair(outer_url, response_time), tick_clock_->NowTicks()); + + if (!flush_timer_->IsRunning()) + ScheduleFlushTimer(); +} + +void SignedExchangePrefetchMetricRecorder::OnSignedExchangeNonPrefetch( + const GURL& outer_url, + base::Time response_time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (disabled_) + return; + + auto it = + recent_prefetch_entries_.find(std::make_pair(outer_url, response_time)); + bool prefetch_found = false; + if (it != recent_prefetch_entries_.end()) { + prefetch_found = true; + recent_prefetch_entries_.erase(it); + } + + UMA_HISTOGRAM_BOOLEAN(kRecallHistogram, prefetch_found); + if (prefetch_found) + UMA_HISTOGRAM_BOOLEAN(kPrecisionHistogram, true); +} + +void SignedExchangePrefetchMetricRecorder::ScheduleFlushTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + flush_timer_->Start( + FROM_HERE, kFlushTimeoutTimeDelta, + base::BindOnce(&SignedExchangePrefetchMetricRecorder::OnFlushTimer, + base::Unretained(this))); +} + +void SignedExchangePrefetchMetricRecorder::OnFlushTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (disabled_) + return; + + const base::TimeTicks expire_before = + tick_clock_->NowTicks() - kPrefetchExpireTimeDelta; + + PrefetchEntries entries; + std::swap(entries, recent_prefetch_entries_); + for (const auto& it : entries) { + const base::TimeTicks prefetch_time = it.second; + + if (prefetch_time < expire_before) { + UMA_HISTOGRAM_BOOLEAN(kPrecisionHistogram, false); + continue; + } + + recent_prefetch_entries_.insert(it); + } + + if (!recent_prefetch_entries_.empty()) + ScheduleFlushTimer(); } } // namespace content
diff --git a/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h b/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h index 00566617..fa300da5 100644 --- a/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h +++ b/content/browser/web_package/signed_exchange_prefetch_metric_recorder.h
@@ -5,9 +5,16 @@ #ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_METRIC_RECORDER_H_ #define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_PREFETCH_METRIC_RECORDER_H_ +#include <utility> +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "net/base/net_errors.h" +#include "base/sequence_checker.h" +#include "base/time/tick_clock.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "content/browser/web_package/signed_exchange_loader.h" +#include "content/common/content_export.h" class GURL; @@ -15,18 +22,35 @@ // SignedExchangePrefetchMetricRecorder records signed exchange prefetch and // its usage metrics. -class SignedExchangePrefetchMetricRecorder final +class CONTENT_EXPORT SignedExchangePrefetchMetricRecorder final : public base::RefCountedThreadSafe<SignedExchangePrefetchMetricRecorder> { public: - SignedExchangePrefetchMetricRecorder(); + explicit SignedExchangePrefetchMetricRecorder( + const base::TickClock* tick_clock); + void OnSignedExchangeNonPrefetch(const GURL& outer_url, + base::Time response_time); void OnSignedExchangePrefetchFinished(const GURL& outer_url, - net::Error error); + base::Time response_time); private: friend class base::RefCountedThreadSafe<SignedExchangePrefetchMetricRecorder>; ~SignedExchangePrefetchMetricRecorder(); + void ScheduleFlushTimer(); + void OnFlushTimer(); + + bool disabled_ = false; + const base::TickClock* tick_clock_; + + using PrefetchEntries = + base::flat_map<std::pair<GURL, base::Time /* response_time */>, + base::TimeTicks /* prefetch_time */>; + PrefetchEntries recent_prefetch_entries_; + + std::unique_ptr<base::OneShotTimer> flush_timer_; + + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(SignedExchangePrefetchMetricRecorder); };
diff --git a/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc b/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc new file mode 100644 index 0000000..5cae66b --- /dev/null +++ b/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc
@@ -0,0 +1,106 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h" + +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" +#include "base/test/simple_test_clock.h" +#include "base/test/simple_test_tick_clock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +class SignedExchangePrefetchMetricRecorderTest : public ::testing::Test { + public: + SignedExchangePrefetchMetricRecorderTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {} + + void SetUp() override { + metric_recorder_ = + base::MakeRefCounted<SignedExchangePrefetchMetricRecorder>( + &test_tick_clock_); + } + + void FastForwardBy(const base::TimeDelta fast_forward_delta) { + test_clock_.Advance(fast_forward_delta); + test_tick_clock_.Advance(fast_forward_delta); + scoped_task_environment_.FastForwardBy(fast_forward_delta); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + const base::HistogramTester histogram_tester_; + base::SimpleTestClock test_clock_; + base::SimpleTestTickClock test_tick_clock_; + scoped_refptr<SignedExchangePrefetchMetricRecorder> metric_recorder_; +}; + +TEST_F(SignedExchangePrefetchMetricRecorderTest, PrecisionRecall) { + const base::Time response_time = test_clock_.Now(); + metric_recorder_->OnSignedExchangePrefetchFinished( + GURL("https://example.org/success.sxg"), response_time); + + FastForwardBy(base::TimeDelta::FromMilliseconds(100)); + + const base::Time response_time2 = test_clock_.Now(); + metric_recorder_->OnSignedExchangePrefetchFinished( + GURL("https://example.org/prefetch_unused.sxg"), response_time2); + + FastForwardBy(base::TimeDelta::FromMilliseconds(100)); + + histogram_tester_.ExpectTotalCount( + "SignedExchange.Prefetch.Precision.30Seconds", 0); + histogram_tester_.ExpectTotalCount("SignedExchange.Prefetch.Recall.30Seconds", + 0); + + metric_recorder_->OnSignedExchangeNonPrefetch( + GURL("https://example.org/success.sxg"), response_time); + + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Precision.30Seconds", true, 1); + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Recall.30Seconds", true, 1); + + const base::Time response_time3 = test_clock_.Now(); + metric_recorder_->OnSignedExchangeNonPrefetch( + GURL("https://example.org/not_prefetched.sxg"), response_time3); + + histogram_tester_.ExpectBucketCount( + "SignedExchange.Prefetch.Recall.30Seconds", true, 1); + histogram_tester_.ExpectBucketCount( + "SignedExchange.Prefetch.Recall.30Seconds", false, 1); + + FastForwardBy(base::TimeDelta::FromMilliseconds(35000)); + + histogram_tester_.ExpectBucketCount( + "SignedExchange.Prefetch.Precision.30Seconds", true, 1); + histogram_tester_.ExpectBucketCount( + "SignedExchange.Prefetch.Precision.30Seconds", false, 1); +} + +TEST_F(SignedExchangePrefetchMetricRecorderTest, DuplicatePrefetch) { + GURL url("https://example.org/foo.sxg"); + const base::Time response_time = test_clock_.Now(); + + metric_recorder_->OnSignedExchangePrefetchFinished(url, response_time); + + FastForwardBy(base::TimeDelta::FromMilliseconds(100)); + + metric_recorder_->OnSignedExchangePrefetchFinished(url, response_time); + + FastForwardBy(base::TimeDelta::FromMilliseconds(100)); + + metric_recorder_->OnSignedExchangeNonPrefetch(url, response_time); + + FastForwardBy(base::TimeDelta::FromMilliseconds(35000)); + + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Precision.30Seconds", true, 1); + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Recall.30Seconds", true, 1); +} + +} // namespace content
diff --git a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc index 491651da..f1d6a76 100644 --- a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc +++ b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -254,6 +254,17 @@ histogram_tester_.ExpectTotalCount( "SignedExchange.Time.CertificateFetch.Success", PrefetchIsEnabled() ? 2 : 1); + if (PrefetchIsEnabled()) { + histogram_tester_.ExpectUniqueSample("SignedExchange.Prefetch.LoadResult", + SignedExchangeLoadResult::kSuccess, 1); + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Recall.30Seconds", true, 1); + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Precision.30Seconds", true, 1); + } else { + histogram_tester_.ExpectUniqueSample( + "SignedExchange.Prefetch.Recall.30Seconds", false, 1); + } } IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 86fb816..0420191 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -330,6 +330,7 @@ "//content/browser/android/select_popup.cc", "//content/public/browser/android/child_process_importance.h", "//content/public/browser/android/motion_event_action.h", + "//content/public/browser/browsing_data_remover.h", "//content/public/browser/invalidate_type.h", "//content/public/browser/navigation_controller.h", "//content/public/common/browser_controls_state.h",
diff --git a/content/public/browser/browsing_data_remover.h b/content/public/browser/browsing_data_remover.h index 67596f7..60055a79 100644 --- a/content/public/browser/browsing_data_remover.h +++ b/content/public/browser/browsing_data_remover.h
@@ -121,6 +121,9 @@ // A helper enum to report the deletion of cookies and/or cache. Do not // reorder the entries, as this enum is passed to UMA. + // A Java counterpart will be generated for this enum so that it can be + // logged on Android. + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.browsing_data enum CookieOrCacheDeletionChoice { NEITHER_COOKIES_NOR_CACHE, ONLY_COOKIES,
diff --git a/content/public/renderer/media_stream_utils.cc b/content/public/renderer/media_stream_utils.cc index 15d6f12c..f6ad39d 100644 --- a/content/public/renderer/media_stream_utils.cc +++ b/content/public/renderer/media_stream_utils.cc
@@ -20,7 +20,6 @@ #include "media/capture/video_capturer_source.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_source.h" -#include "third_party/blink/public/web/web_media_stream_registry.h" namespace content {
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 932bb243..6860439 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -653,7 +653,7 @@ void ResetTouchAction(RenderWidgetHost* host) { static_cast<InputRouterImpl*>( static_cast<RenderWidgetHostImpl*>(host)->input_router()) - ->OnHasTouchEventHandlersForTest(true); + ->ForceResetTouchActionForTest(); } void ResendGestureScrollUpdateToEmbedder(WebContents* guest_web_contents,
diff --git a/content/renderer/media/web_media_element_source_utils.cc b/content/renderer/media/web_media_element_source_utils.cc index 94502c5..9fc4893 100644 --- a/content/renderer/media/web_media_element_source_utils.cc +++ b/content/renderer/media/web_media_element_source_utils.cc
@@ -6,7 +6,6 @@ #include "third_party/blink/public/platform/web_media_player_source.h" #include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/blink/public/web/web_media_stream_registry.h" namespace content { @@ -15,11 +14,6 @@ if (source.IsMediaStream()) return source.GetAsMediaStream(); - if (source.IsURL()) { - return blink::WebMediaStreamRegistry::LookupMediaStreamDescriptor( - source.GetAsURL()); - } - return blink::WebMediaStream(); }
diff --git a/content/renderer/push_messaging/push_messaging_client.cc b/content/renderer/push_messaging/push_messaging_client.cc index 512d3e2..06ae6c7 100644 --- a/content/renderer/push_messaging/push_messaging_client.cc +++ b/content/renderer/push_messaging/push_messaging_client.cc
@@ -15,13 +15,11 @@ #include "content/public/common/service_names.mojom.h" #include "content/renderer/push_messaging/push_provider.h" #include "content/renderer/render_frame_impl.h" -#include "content/renderer/service_worker/web_service_worker_registration_impl.h" #include "services/service_manager/public/cpp/connector.h" #include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h" -#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/web/web_console_message.h" #include "third_party/blink/public/web/web_local_frame.h" @@ -45,11 +43,10 @@ } void PushMessagingClient::Subscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const blink::WebPushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { - DCHECK(service_worker_registration); DCHECK(callbacks); // If a developer provided an application server key in |options|, skip @@ -59,7 +56,7 @@ ->GetManifestManager() .RequestManifest(base::BindOnce(&PushMessagingClient::DidGetManifest, base::Unretained(this), - service_worker_registration, options, + service_worker_registration_id, options, user_gesture, std::move(callbacks))); } else { PushSubscriptionOptions content_options; @@ -67,13 +64,13 @@ // Just treat the server key as a string of bytes and pass it to the push // service. content_options.sender_info = options.application_server_key.Latin1(); - DoSubscribe(service_worker_registration, content_options, user_gesture, + DoSubscribe(service_worker_registration_id, content_options, user_gesture, std::move(callbacks)); } } void PushMessagingClient::DidGetManifest( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const blink::WebPushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks, @@ -95,20 +92,15 @@ base::UTF16ToUTF8(manifest.gcm_sender_id.string()); } - DoSubscribe(service_worker_registration, content_options, user_gesture, + DoSubscribe(service_worker_registration_id, content_options, user_gesture, std::move(callbacks)); } void PushMessagingClient::DoSubscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const PushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { - int64_t service_worker_registration_id = - static_cast<WebServiceWorkerRegistrationImpl*>( - service_worker_registration) - ->RegistrationId(); - if (options.sender_info.empty()) { DidSubscribe(std::move(callbacks), mojom::PushRegistrationStatus::NO_SENDER_ID, base::nullopt,
diff --git a/content/renderer/push_messaging/push_messaging_client.h b/content/renderer/push_messaging/push_messaging_client.h index c8d6e8e3..b8ef9bc 100644 --- a/content/renderer/push_messaging/push_messaging_client.h +++ b/content/renderer/push_messaging/push_messaging_client.h
@@ -44,13 +44,13 @@ // WebPushClient implementation. void Subscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const blink::WebPushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) override; void DidGetManifest( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const blink::WebPushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks, @@ -58,7 +58,7 @@ const blink::Manifest& manifest); void DoSubscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const PushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks);
diff --git a/content/renderer/push_messaging/push_provider.cc b/content/renderer/push_messaging/push_provider.cc index 3f3e6e6..605a4b0 100644 --- a/content/renderer/push_messaging/push_provider.cc +++ b/content/renderer/push_messaging/push_provider.cc
@@ -15,7 +15,6 @@ #include "content/public/common/push_messaging_status.mojom.h" #include "content/public/common/push_subscription_options.h" #include "content/public/common/service_names.mojom.h" -#include "content/renderer/service_worker/web_service_worker_registration_impl.h" #include "services/service_manager/public/cpp/connector.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h" @@ -87,15 +86,6 @@ return ""; } -// Returns the id of the given |service_worker_registration|, which -// is only available on the implementation of the interface. -int64_t GetServiceWorkerRegistrationId( - blink::WebServiceWorkerRegistration* service_worker_registration) { - return static_cast<WebServiceWorkerRegistrationImpl*>( - service_worker_registration) - ->RegistrationId(); -} - } // namespace blink::WebPushError PushRegistrationStatusToWebPushError( @@ -180,15 +170,12 @@ } void PushProvider::Subscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const blink::WebPushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { - DCHECK(service_worker_registration); DCHECK(callbacks); - int64_t service_worker_registration_id = - GetServiceWorkerRegistrationId(service_worker_registration); PushSubscriptionOptions content_options; content_options.user_visible_only = options.user_visible_only; @@ -233,14 +220,10 @@ } void PushProvider::Unsubscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) { - DCHECK(service_worker_registration); DCHECK(callbacks); - int64_t service_worker_registration_id = - GetServiceWorkerRegistrationId(service_worker_registration); - push_messaging_manager_->Unsubscribe( service_worker_registration_id, // Safe to use base::Unretained because |push_messaging_manager_ |is owned @@ -266,14 +249,10 @@ } void PushProvider::GetSubscription( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) { - DCHECK(service_worker_registration); DCHECK(callbacks); - int64_t service_worker_registration_id = - GetServiceWorkerRegistrationId(service_worker_registration); - push_messaging_manager_->GetSubscription( service_worker_registration_id, // Safe to use base::Unretained because |push_messaging_manager_ |is owned
diff --git a/content/renderer/push_messaging/push_provider.h b/content/renderer/push_messaging/push_provider.h index 223d4cbc..ad6b1fc4 100644 --- a/content/renderer/push_messaging/push_provider.h +++ b/content/renderer/push_messaging/push_provider.h
@@ -50,15 +50,15 @@ // blink::WebPushProvider implementation. void Subscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const blink::WebPushSubscriptionOptions& options, bool user_gesture, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) override; void Unsubscribe( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, std::unique_ptr<blink::WebPushUnsubscribeCallbacks> callbacks) override; void GetSubscription( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks) override; private:
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index cf3e520..08cf1c5a 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -204,7 +204,6 @@ #include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_input_method_controller.h" #include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_media_stream_registry.h" #include "third_party/blink/public/web/web_navigation_policy.h" #include "third_party/blink/public/web/web_navigation_timings.h" #include "third_party/blink/public/web/web_plugin.h"
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index b82d9757..0362df8 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1160,7 +1160,7 @@ } void RenderThreadImpl::InitializeCompositorThread() { - blink_platform_impl_->InitializeCompositorThread(); + blink_platform_impl_->CreateAndSetCompositorThread(); compositor_task_runner_ = blink_platform_impl_->CompositorThreadTaskRunner(); compositor_task_runner_->PostTask( FROM_HERE,
diff --git a/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc b/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc index ffef851..f17dc37 100644 --- a/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc +++ b/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc
@@ -8,7 +8,6 @@ #include "media/media_buildflags.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_track.h" -#include "third_party/blink/public/web/web_media_stream_registry.h" namespace {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 1725379..f5529db 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1622,6 +1622,7 @@ "../browser/web_package/signed_exchange_certificate_chain_unittest.cc", "../browser/web_package/signed_exchange_envelope_unittest.cc", "../browser/web_package/signed_exchange_handler_unittest.cc", + "../browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc", "../browser/web_package/signed_exchange_prologue_unittest.cc", "../browser/web_package/signed_exchange_signature_header_field_unittest.cc", "../browser/web_package/signed_exchange_signature_verifier_unittest.cc",
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index d7af48c..abc9869 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -138,6 +138,3 @@ ['android', ('qualcomm', 'Adreno (TM) 420')], bug=883500) self.Fail('Pixel_BackgroundImage', ['android', ('qualcomm', 'Adreno (TM) 430')], bug=883500) - - # TODO(yiyix): remove expectation after rebaseline. - self.Fail("Pixel_CSS3DBlueBox", bug=879379)
diff --git a/docs/adding_to_third_party.md b/docs/adding_to_third_party.md index 0d2e025..eda7e18 100644 --- a/docs/adding_to_third_party.md +++ b/docs/adding_to_third_party.md
@@ -127,12 +127,11 @@ When adding a new package that could potentially carry security risk, make sure to highlight risk to security@chromium.org. You may be asked to add a README.security or, in dangerous cases, README.SECURITY.URGENTLY file. -* Add chromium-third-party@google.com as a reviewer on your change. This - will trigger an automatic round-robin assignment of the review to an - appropriate reviewer. This list does not receive or deliver email, so only - use it as a reviewer, not for other communication. +* Get licensing approval. Email opensource-licensing@google.com with relevant + details and a link to the CL. -Please send separate emails to the eng review and security lists. +Please send separate emails to the eng review, opensource licensing, and +security lists. Subsequent changes don't require third-party-owners approval; you can modify the code as much as you want. When you update code, be mindful of security-related
diff --git a/google_apis/gaia/gaia_auth_util.cc b/google_apis/gaia/gaia_auth_util.cc index e2bb6147..75d69c8 100644 --- a/google_apis/gaia/gaia_auth_util.cc +++ b/google_apis/gaia/gaia_auth_util.cc
@@ -182,14 +182,4 @@ return true; } -bool RequestOriginatedFromGaia(const net::URLRequest& request) { - return request.GetUserData(kURLRequestUserDataKey) != nullptr; -} - -void MarkURLFetcherAsGaia(net::URLFetcher* fetcher) { - DCHECK(fetcher); - fetcher->SetURLRequestUserData(kURLRequestUserDataKey, - base::Bind(&GaiaURLRequestUserData::Create)); -} - } // namespace gaia
diff --git a/google_apis/gaia/gaia_auth_util.h b/google_apis/gaia/gaia_auth_util.h index 175a41d..c6af6322 100644 --- a/google_apis/gaia/gaia_auth_util.h +++ b/google_apis/gaia/gaia_auth_util.h
@@ -11,11 +11,6 @@ class GURL; -namespace net { -class URLFetcher; -class URLRequest; -} // namespace net - namespace gaia { struct ListedAccount { @@ -66,12 +61,6 @@ std::vector<ListedAccount>* accounts, std::vector<ListedAccount>* signed_out_accounts); -// Returns true if the URL request originated from GAIA. -bool RequestOriginatedFromGaia(const net::URLRequest& request); - -// Marks the URL request as a Gaia request. -void MarkURLFetcherAsGaia(net::URLFetcher* request); - } // namespace gaia #endif // GOOGLE_APIS_GAIA_GAIA_AUTH_UTIL_H_
diff --git a/google_apis/gaia/gaia_oauth_client.cc b/google_apis/gaia/gaia_oauth_client.cc index c6c0221..3e14812 100644 --- a/google_apis/gaia/gaia_oauth_client.cc +++ b/google_apis/gaia/gaia_oauth_client.cc
@@ -403,10 +403,6 @@ // Retry is implemented internally. request_->SetRetryOptions(0, network::SimpleURLLoader::RETRY_NEVER); - // TODO(https://crbug.com/808498) re-add data use measurement once - // SimpleURLLoader supports it. Previous way of setting it was: - // MarkURLFetcherAsGaia(request_.get()); - request_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( url_loader_factory_.get(), // Unretained(this) is safe since |this| owns |request_|, and its deletion
diff --git a/google_apis/gaia/oauth2_api_call_flow.cc b/google_apis/gaia/oauth2_api_call_flow.cc index 86b8b75..2a4c73f4 100644 --- a/google_apis/gaia/oauth2_api_call_flow.cc +++ b/google_apis/gaia/oauth2_api_call_flow.cc
@@ -95,10 +95,6 @@ std::unique_ptr<network::SimpleURLLoader> result = network::SimpleURLLoader::Create(std::move(request), traffic_annotation); - // TODO(https://crbug.com/808498) re-add data use measurement once - // SimpleURLLoader supports it. Previously: - // gaia::MarkURLFetcherAsGaia(result.get()); - // Fetchers are sometimes cancelled because a network change was detected, // especially at startup and after sign-in on ChromeOS. Retrying once should // be enough in those cases; let the fetcher retry up to 3 times just in case.
diff --git a/headless/lib/browser/headless_request_context_manager.cc b/headless/lib/browser/headless_request_context_manager.cc index 318f26c..f8dcb0ae 100644 --- a/headless/lib/browser/headless_request_context_manager.cc +++ b/headless/lib/browser/headless_request_context_manager.cc
@@ -128,14 +128,14 @@ void SetURLRequestContext(net::URLRequestContext* context) { DCHECK(!context_ && !context_owner_); - DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService)); + DCHECK(!base::FeatureList::IsEnabled(::network::features::kNetworkService)); context_ = context; } void SetURLRequestContext(std::unique_ptr<net::URLRequestContext> context) { DCHECK(!context_ && !context_owner_); - DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); + DCHECK(base::FeatureList::IsEnabled(::network::features::kNetworkService)); context_owner_ = std::move(context); context_ = context_owner_.get(); @@ -160,7 +160,7 @@ // ProxyConfigClient. class HeadlessProxyConfigMonitor : public net::ProxyConfigService::Observer, - public network::mojom::ProxyConfigPollerClient { + public ::network::mojom::ProxyConfigPollerClient { public: static void DeleteSoon(std::unique_ptr<HeadlessProxyConfigMonitor> instance) { instance->task_runner_->DeleteSoon(FROM_HERE, instance.release()); @@ -191,7 +191,7 @@ // whenever the configuration changes. Can be called more than once to inform // multiple NetworkContexts of proxy changes. void AddToNetworkContextParams( - network::mojom::NetworkContextParams* network_context_params) { + ::network::mojom::NetworkContextParams* network_context_params) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(!proxy_config_client_); network_context_params->proxy_config_client_request = @@ -231,8 +231,8 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner_; std::unique_ptr<net::ProxyConfigService> proxy_config_service_; - mojo::Binding<network::mojom::ProxyConfigPollerClient> poller_binding_; - network::mojom::ProxyConfigClientPtr proxy_config_client_; + mojo::Binding<::network::mojom::ProxyConfigPollerClient> poller_binding_; + ::network::mojom::ProxyConfigClientPtr proxy_config_client_; DISALLOW_COPY_AND_ASSIGN(HeadlessProxyConfigMonitor); }; @@ -254,7 +254,8 @@ #if defined(OS_LINUX) && !defined(OS_CHROMEOS) if (manager->user_data_path_.empty()) { - network::mojom::CryptConfigPtr config = network::mojom::CryptConfig::New(); + ::network::mojom::CryptConfigPtr config = + ::network::mojom::CryptConfig::New(); config->store = command_line->GetSwitchValueASCII(switches::kPasswordStore); config->product_name = kProductName; config->should_use_preference = false; @@ -277,7 +278,7 @@ const HeadlessBrowserContextOptions* options, base::FilePath user_data_path) : network_service_enabled_( - base::FeatureList::IsEnabled(network::features::kNetworkService)), + base::FeatureList::IsEnabled(::network::features::kNetworkService)), io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits( {content::BrowserThread::IO})), user_data_path_(std::move(user_data_path)), @@ -359,7 +360,7 @@ if (!network_service_enabled_) { DCHECK(network_context_request_); - auto builder = std::make_unique<network::URLRequestContextBuilderMojo>(); + auto builder = std::make_unique<::network::URLRequestContextBuilderMojo>(); builder->set_network_delegate(std::make_unique<DelegateImpl>()); builder->SetCreateHttpTransactionFactoryCallback( base::BindOnce(&content::CreateDevToolsNetworkTransactionFactory)); @@ -381,9 +382,9 @@ url_request_context_getter_->SetURLRequestContext(builder.Build()); } -network::mojom::NetworkContextParamsPtr +::network::mojom::NetworkContextParamsPtr HeadlessRequestContextManager::CreateNetworkContextParams() { - auto context_params = network::mojom::NetworkContextParams::New(); + auto context_params = ::network::mojom::NetworkContextParams::New(); context_params->user_agent = user_agent_; context_params->accept_language = accept_language_;
diff --git a/headless/public/headless_browser.cc b/headless/public/headless_browser.cc index 9ad4199..2f66f1f 100644 --- a/headless/public/headless_browser.cc +++ b/headless/public/headless_browser.cc
@@ -20,14 +20,14 @@ namespace { // Product name for building the default user agent string. -const char kProductName[] = "HeadlessChrome"; +const char kHeadlessProductName[] = "HeadlessChrome"; constexpr gfx::Size kDefaultWindowSize(800, 600); constexpr gfx::FontRenderParams::Hinting kDefaultFontRenderHinting = gfx::FontRenderParams::Hinting::HINTING_FULL; std::string GetProductNameAndVersion() { - return std::string(kProductName) + "/" + PRODUCT_VERSION; + return std::string(kHeadlessProductName) + "/" + PRODUCT_VERSION; } } // namespace
diff --git a/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json b/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json index 61acdf96..2f8510bf0 100644 --- a/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json +++ b/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json
@@ -4,7 +4,7 @@ "the final GM, but disabled for the other betas to reduce swirl for the", "goma team. Build is performed with gn+ninja." ], - "xcode build version": "10o23u", + "xcode build version": "10a254a", "use xcode build version": true, "gn_args": [ "additional_target_cpus=[\"x86\"]",
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index ea225ce..0a1d18e 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -956,6 +956,10 @@ ios::GetChromeBrowserProvider() ->GetMailtoHandlerProvider() ->RemoveMailtoHandling(); + // _localStatePrefChangeRegistrar is observing the PrefService, which is owned + // indirectly by _chromeMain (through the ChromeBrowserState). + // Unregister the observer before the service is destroyed. + _localStatePrefChangeRegistrar.RemoveAll(); _chromeMain.reset(); }
diff --git a/ios/chrome/browser/passwords/password_controller.h b/ios/chrome/browser/passwords/password_controller.h index 0d368507..389c6f0 100644 --- a/ios/chrome/browser/passwords/password_controller.h +++ b/ios/chrome/browser/passwords/password_controller.h
@@ -9,7 +9,7 @@ #include <memory> #import "components/autofill/ios/browser/form_suggestion_provider.h" -#import "components/password_manager/ios/password_controller_helper.h" +#import "components/password_manager/ios/password_form_helper.h" #import "ios/chrome/browser/passwords/ios_chrome_password_manager_client.h" #import "ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" @@ -42,7 +42,7 @@ @interface PasswordController : NSObject<CRWWebStateObserver, PasswordManagerClientDelegate, PasswordManagerDriverDelegate, - PasswordControllerHelperDelegate> + PasswordFormHelperDelegate> // An object that can provide suggestions from this PasswordController. @property(nonatomic, readonly) id<FormSuggestionProvider> suggestionProvider;
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index 7ee3ff97..eee8586e 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -36,6 +36,7 @@ #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/ios/account_select_fill_data.h" #import "components/password_manager/ios/js_password_manager.h" +#import "components/password_manager/ios/password_suggestion_helper.h" #include "components/sync/driver/sync_service.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h" @@ -77,9 +78,6 @@ using password_manager::SerializeFillData; using password_manager::SerializePasswordFormFillData; -typedef void (^PasswordSuggestionsAvailableCompletion)( - const AccountSelectFillData*); - namespace { // Types of password infobars to display. enum class PasswordInfoBarType { SAVE, UPDATE }; @@ -111,15 +109,18 @@ } } // namespace -@interface PasswordController () +@interface PasswordController ()<PasswordSuggestionHelperDelegate> // View controller for auto sign-in notification, owned by this // PasswordController. @property(nonatomic, strong) NotifyUserAutoSigninViewController* notifyAutoSigninViewController; -// Helper contains common password controller logic. -@property(nonatomic, readonly) PasswordControllerHelper* helper; +// Helper contains common password form processing logic. +@property(nonatomic, readonly) PasswordFormHelper* formHelper; + +// Helper contains common password suggestion logic. +@property(nonatomic, readonly) PasswordSuggestionHelper* suggestionHelper; @end @@ -147,69 +148,12 @@ @end -namespace { - -// Constructs an array of FormSuggestions, each corresponding to a username/ -// password pair in |AccountSelectFillData|. "Show all" item is appended. -NSArray* BuildSuggestions(const AccountSelectFillData& fillData, - NSString* formName, - NSString* fieldIdentifier, - NSString* fieldType) { - base::string16 form_name = base::SysNSStringToUTF16(formName); - base::string16 field_identifier = base::SysNSStringToUTF16(fieldIdentifier); - bool is_password_field = [fieldType isEqualToString:@"password"]; - - NSMutableArray* suggestions = [NSMutableArray array]; - PasswordSuggestionType suggestion_type = PasswordSuggestionType::SHOW_ALL; - if (fillData.IsSuggestionsAvailable(form_name, field_identifier, - is_password_field)) { - std::vector<password_manager::UsernameAndRealm> username_and_realms_ = - fillData.RetrieveSuggestions(form_name, field_identifier, - is_password_field); - - // Add credentials. - for (const auto& username_and_realm : username_and_realms_) { - NSString* value = [base::SysUTF16ToNSString(username_and_realm.username) - stringByAppendingString:kSuggestionSuffix]; - NSString* origin = - username_and_realm.realm.empty() - ? nil - : base::SysUTF8ToNSString(username_and_realm.realm); - - [suggestions addObject:[FormSuggestion suggestionWithValue:value - displayDescription:origin - icon:nil - identifier:0]]; - suggestion_type = PasswordSuggestionType::CREDENTIALS; - } - } - - // Once Manual Fallback is enabled the access to settings will exist as an - // option in the new passwords UI. - if (!autofill::features::IsPasswordManualFallbackEnabled()) { - // Add "Show all". - NSString* showAll = l10n_util::GetNSString(IDS_IOS_SHOW_ALL_PASSWORDS); - [suggestions addObject:[FormSuggestion suggestionWithValue:showAll - displayDescription:nil - icon:nil - identifier:1]]; - } - if (suggestions.count) { - LogSuggestionShown(suggestion_type); - } - return [suggestions copy]; -} - -} // namespace - @implementation PasswordController { std::unique_ptr<PasswordManager> _passwordManager; std::unique_ptr<PasswordManagerClient> _passwordManagerClient; std::unique_ptr<PasswordManagerDriver> _passwordManagerDriver; std::unique_ptr<CredentialManager> _credentialManager; - AccountSelectFillData _fillData; - // The WebState this instance is observing. Will be null after // -webStateDestroyed: has been called. web::WebState* _webState; @@ -220,14 +164,6 @@ // Timer for hiding "Signing in as ..." notification. base::OneShotTimer _notifyAutoSigninTimer; - // True indicates that a request for credentials has been sent to the password - // store. - BOOL _sentRequestToStore; - - // The completion to inform FormSuggestionController that suggestions are - // available for a given form and field. - PasswordSuggestionsAvailableCompletion _suggestionsAvailableCompletion; - // User credential waiting to be displayed in autosign-in snackbar, once tab // becomes active. std::unique_ptr<autofill::PasswordForm> _pendingAutoSigninPasswordForm; @@ -241,7 +177,9 @@ @synthesize notifyAutoSigninViewController = _notifyAutoSigninViewController; -@synthesize helper = _helper; +@synthesize formHelper = _formHelper; + +@synthesize suggestionHelper = _suggestionHelper; - (instancetype)initWithWebState:(web::WebState*)webState { self = [self initWithWebState:webState @@ -259,8 +197,10 @@ _webStateObserverBridge = std::make_unique<web::WebStateObserverBridge>(self); _webState->AddObserver(_webStateObserverBridge.get()); - _helper = [[PasswordControllerHelper alloc] initWithWebState:webState - delegate:self]; + _formHelper = + [[PasswordFormHelper alloc] initWithWebState:webState delegate:self]; + _suggestionHelper = + [[PasswordSuggestionHelper alloc] initWithDelegate:self]; if (passwordManagerClient) _passwordManagerClient = std::move(passwordManagerClient); else @@ -268,8 +208,6 @@ _passwordManager.reset(new PasswordManager(_passwordManagerClient.get())); _passwordManagerDriver.reset(new IOSChromePasswordManagerDriver(self)); - _sentRequestToStore = NO; - if (base::FeatureList::IsEnabled(features::kCredentialManager)) { _credentialManager = std::make_unique<CredentialManager>( _passwordManagerClient.get(), _webState); @@ -308,9 +246,9 @@ - (void)findAndFillPasswordForms:(NSString*)username password:(NSString*)password completionHandler:(void (^)(BOOL))completionHandler { - [self.helper findAndFillPasswordFormsWithUserName:username - password:password - completionHandler:completionHandler]; + [self.formHelper findAndFillPasswordFormsWithUserName:username + password:password + completionHandler:completionHandler]; } #pragma mark - CRWWebStateObserver @@ -334,9 +272,7 @@ - (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success { DCHECK_EQ(_webState, webState); // Clear per-page state. - _fillData.Reset(); - _sentRequestToStore = NO; - _suggestionsAvailableCompletion = nil; + [self.suggestionHelper resetForNewPage]; // Retrieve the identity of the page. In case the page might be malicous, // returns early. @@ -391,45 +327,18 @@ webState:(web::WebState*)webState completionHandler: (SuggestionsAvailableCompletion)completion { - if (!isMainFrame) { - web::WebFrame* frame = - web::GetWebFrameWithId(webState, base::SysNSStringToUTF8(frameID)); - if (!frame || webState->GetLastCommittedURL().GetOrigin() != - frame->GetSecurityOrigin()) { - // Passwords is only supported on main frame and iframes with the same - // origin. - completion(NO); - return; - } - } - - bool should_send_request_to_store = - !_sentRequestToStore && [type isEqual:@"focus"]; - bool is_password_field = [fieldType isEqual:@"password"]; - - if (should_send_request_to_store) { - // Save the completion and go look for suggestions. - _suggestionsAvailableCompletion = - [^(const AccountSelectFillData* fill_data) { - if (is_password_field) { - // Always display "Show all" on the password field. - completion(YES); - } else if (!fill_data) { - completion(NO); - } else { - completion(fill_data->IsSuggestionsAvailable( - base::SysNSStringToUTF16(formName), - base::SysNSStringToUTF16(fieldIdentifier), false)); - } - } copy]; - [self findPasswordFormsAndSendThemToPasswordStore]; - return; - } - - completion(is_password_field || - _fillData.IsSuggestionsAvailable( - base::SysNSStringToUTF16(formName), - base::SysNSStringToUTF16(fieldIdentifier), false)); + [self.suggestionHelper + checkIfSuggestionsAvailableForForm:formName + fieldIdentifier:fieldIdentifier + type:type + frameID:frameID + isMainFrame:isMainFrame + webState:webState + completionHandler:^(BOOL suggestionsAvailable) { + // Always display "Show All..." for password fields. + completion([fieldType isEqualToString:@"password"] || + suggestionsAvailable); + }]; } - (void)retrieveSuggestionsForForm:(NSString*)formName @@ -442,8 +351,41 @@ webState:(web::WebState*)webState completionHandler:(SuggestionsReadyCompletion)completion { DCHECK(GetPageURLAndCheckTrustLevel(webState, nullptr)); - completion(BuildSuggestions(_fillData, formName, fieldIdentifier, fieldType), - self); + NSArray<FormSuggestion*>* rawSuggestions = + [self.suggestionHelper retrieveSuggestionsWithFormName:formName + fieldIdentifier:fieldIdentifier + fieldType:fieldType]; + PasswordSuggestionType suggestion_type = + rawSuggestions.count > 0 ? PasswordSuggestionType::CREDENTIALS + : PasswordSuggestionType::SHOW_ALL; + + NSMutableArray<FormSuggestion*>* suggestions = [NSMutableArray array]; + for (FormSuggestion* rawSuggestion in rawSuggestions) { + [suggestions + addObject:[FormSuggestion + suggestionWithValue: + [rawSuggestion.value + stringByAppendingString:kSuggestionSuffix] + displayDescription:rawSuggestion.displayDescription + icon:nil + identifier:0]]; + } + + // Once Manual Fallback is enabled the access to settings will exist as an + // option in the new passwords UI. + if (!autofill::features::IsPasswordManualFallbackEnabled()) { + // Add "Show all". + NSString* showAll = l10n_util::GetNSString(IDS_IOS_SHOW_ALL_PASSWORDS); + [suggestions addObject:[FormSuggestion suggestionWithValue:showAll + displayDescription:nil + icon:nil + identifier:1]]; + } + if (suggestions.count) { + LogSuggestionShown(suggestion_type); + } + + completion([suggestions copy], self); } - (void)didSelectSuggestion:(FormSuggestion*)suggestion @@ -460,18 +402,19 @@ return; } LogSuggestionClicked(PasswordSuggestionType::CREDENTIALS); - base::string16 value = base::SysNSStringToUTF16(suggestion.value); DCHECK([suggestion.value hasSuffix:kSuggestionSuffix]); - value.erase(value.length() - kSuggestionSuffix.length); - std::unique_ptr<FillData> fillData = _fillData.GetFillData(value); + NSString* username = [suggestion.value + substringToIndex:suggestion.value.length - kSuggestionSuffix.length]; + std::unique_ptr<password_manager::FillData> fillData = + [self.suggestionHelper getFillDataForUsername:username]; if (!fillData) completion(); - [self.helper fillPasswordFormWithFillData:*fillData - completionHandler:^(BOOL success) { - completion(); - }]; + [self.formHelper fillPasswordFormWithFillData:*fillData + completionHandler:^(BOOL success) { + completion(); + }]; } #pragma mark - PasswordManagerClientDelegate @@ -487,7 +430,7 @@ } - (const GURL&)lastCommittedURL { - return self.helper.lastCommittedURL; + return self.formHelper.lastCommittedURL; } - (void)showSavePasswordInfoBar: @@ -546,27 +489,20 @@ - (void)fillPasswordForm:(const autofill::PasswordFormFillData&)formData completionHandler:(void (^)(BOOL))completionHandler { - _fillData.Add(formData); - - if (_suggestionsAvailableCompletion) { - _suggestionsAvailableCompletion(&_fillData); - _suggestionsAvailableCompletion = nil; - } - - [self.helper fillPasswordForm:formData completionHandler:completionHandler]; + [self.suggestionHelper processWithPasswordFormFillData:formData]; + [self.formHelper fillPasswordForm:formData + completionHandler:completionHandler]; } - (void)onNoSavedCredentials { - if (_suggestionsAvailableCompletion) - _suggestionsAvailableCompletion(nullptr); - _suggestionsAvailableCompletion = nil; + [self.suggestionHelper processWithNoSavedCredentials]; } -#pragma mark - PasswordControllerHelperDelegate +#pragma mark - PasswordFormHelperDelegate -- (void)helper:(PasswordControllerHelper*)helper - didSubmitForm:(const PasswordForm&)form - inMainFrame:(BOOL)inMainFrame { +- (void)formHelper:(PasswordFormHelper*)formHelper + didSubmitForm:(const PasswordForm&)form + inMainFrame:(BOOL)inMainFrame { if (inMainFrame) { self.passwordManager->OnPasswordFormSubmitted(self.passwordManagerDriver, form); @@ -578,6 +514,13 @@ } } +#pragma mark - PasswordSuggestionHelperDelegate + +- (void)suggestionHelperShouldTriggerFormExtraction: + (PasswordSuggestionHelper*)suggestionHelper { + [self findPasswordFormsAndSendThemToPasswordStore]; +} + #pragma mark - Private methods - (void)didFinishPasswordFormExtraction: @@ -594,7 +537,8 @@ ->DidShowPasswordFieldInInsecureContext(); } - _sentRequestToStore = YES; + [self.suggestionHelper updateStateOnPasswordFormExtracted]; + // Invoke the password manager callback to autofill password forms // on the loaded page. self.passwordManager->OnPasswordFormsParsed(self.passwordManagerDriver, @@ -616,8 +560,8 @@ // Read all password forms from the page and send them to the password // manager. __weak PasswordController* weakSelf = self; - [self.helper findPasswordFormsWithCompletionHandler:^( - const std::vector<autofill::PasswordForm>& forms) { + [self.formHelper findPasswordFormsWithCompletionHandler:^( + const std::vector<autofill::PasswordForm>& forms) { [weakSelf didFinishPasswordFormExtraction:forms]; }]; }
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index 7de9876..97872e3 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -23,7 +23,7 @@ #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #import "components/password_manager/ios/js_password_manager.h" -#import "components/password_manager/ios/password_controller_helper.h" +#import "components/password_manager/ios/password_form_helper.h" #include "components/password_manager/ios/test_helpers.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" @@ -150,8 +150,8 @@ @interface PasswordController ( Testing)<CRWWebStateObserver, FormSuggestionProvider> -// Provides access to common helper logic for testing with mocks. -@property(readonly) PasswordControllerHelper* helper; +// Provides access to common form helper logic for testing with mocks. +@property(readonly) PasswordFormHelper* formHelper; - (void)fillPasswordForm:(const PasswordFormFillData&)formData completionHandler:(void (^)(BOOL))completionHandler; @@ -160,7 +160,7 @@ @end -@interface PasswordControllerHelper (Testing) +@interface PasswordFormHelper (Testing) // Provides access to JavaScript Manager for testing with mocks. @property(readonly) JsPasswordManager* jsPasswordManager; @@ -254,7 +254,7 @@ // |failure_count| reaches |target_failure_count|, stop the partial mock // and let the original JavaScript manager execute. void SetFillPasswordFormFailureCount(int target_failure_count) { - id original_manager = passwordController_.helper.jsPasswordManager; + id original_manager = passwordController_.formHelper.jsPasswordManager; OCPartialMockObject* failing_manager = [OCMockObject partialMockForObject:original_manager]; __block int failure_count = 0; @@ -388,11 +388,12 @@ LoadHtml(data.html_string); __block std::vector<PasswordForm> forms; __block BOOL block_was_called = NO; - [passwordController_.helper findPasswordFormsWithCompletionHandler:^( - const std::vector<PasswordForm>& result) { - block_was_called = YES; - forms = result; - }]; + [passwordController_.formHelper + findPasswordFormsWithCompletionHandler:^( + const std::vector<PasswordForm>& result) { + block_was_called = YES; + forms = result; + }]; EXPECT_TRUE( WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool() { return block_was_called; @@ -489,7 +490,7 @@ form.username_element); } }; - [passwordController_.helper + [passwordController_.formHelper extractSubmittedPasswordForm:FormName(data.number_of_forms_to_submit) completionHandler:completion_handler]; EXPECT_TRUE(
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 6ae837c..0384f0f 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -3057,8 +3057,10 @@ - (BOOL)isTabScrolledToTopForBubblePresenter:(BubblePresenter*)bubblePresenter { DCHECK(bubblePresenter == self.bubblePresenter); - CGPoint scrollOffset = - self.currentWebState->GetWebViewProxy().scrollViewProxy.contentOffset; + CRWWebViewScrollViewProxy* scrollProxy = + self.currentWebState->GetWebViewProxy().scrollViewProxy; + CGPoint scrollOffset = scrollProxy.contentOffset; + UIEdgeInsets contentInset = scrollProxy.contentInset; // If there is a native controller, use the native controller's scroll offset. id nativeController = @@ -3068,7 +3070,7 @@ scrollOffset = [nativeController scrollOffset]; } - return CGPointEqualToPoint(scrollOffset, CGPointZero); + return AreCGFloatsEqual(scrollOffset.y, -contentInset.top); } #pragma mark - SnapshotGeneratorDelegate methods @@ -4740,6 +4742,29 @@ [nativeController focusFakebox]; } +- (void)unfocusOmniboxAndSwitchToTabWithURL:(const GURL&)URL { + // TODO(crbug.com/893121): Add animations. + + // Cancelling the omnibox edit makes |URL| unsafe as it is not longer + // retained. + GURL retainedURL = URL; + [self.dispatcher cancelOmniboxEdit]; + + // TODO(crbug.com/893121): This should probably live in the WebState. + WebStateList* webStateList = self.tabModel.webStateList; + web::WebState* currentWebState = webStateList->GetActiveWebState(); + + for (NSInteger index = 0; index < webStateList->count(); index++) { + web::WebState* webState = webStateList->GetWebStateAt(index); + + if (webState != currentWebState && + retainedURL == webState->GetVisibleURL()) { + self.tabModel.webStateList->ActivateWebStateAt(index); + return; + } + } +} + #pragma mark - TabModelObserver methods // Observer method, tab inserted.
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm index 3b080bf..dc30152 100644 --- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -25,6 +25,7 @@ #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" #import "ios/chrome/browser/tabs/tab.h" +#import "ios/chrome/browser/tabs/tab_helper_util.h" #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/tabs/tab_model_observer.h" #import "ios/chrome/browser/tabs/tab_private.h" @@ -42,6 +43,7 @@ #import "ios/chrome/browser/web/error_page_content.h" #include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" #include "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/chrome/browser/web_state_list/web_usage_enabler/web_state_list_web_usage_enabler.h" #import "ios/chrome/browser/web_state_list/web_usage_enabler/web_state_list_web_usage_enabler_factory.h" #include "ios/chrome/grit/ios_strings.h" @@ -51,7 +53,11 @@ #import "ios/net/protocol_handler_util.h" #import "ios/testing/ocmock_complex_type_helper.h" #include "ios/web/public/referrer.h" +#import "ios/web/public/test/fakes/fake_navigation_context.h" +#import "ios/web/public/test/fakes/test_navigation_manager.h" +#import "ios/web/public/test/fakes/test_web_state.h" #include "ios/web/public/test/test_web_thread_bundle.h" +#import "ios/web/public/web_state/js/crw_js_injection_receiver.h" #import "ios/web/public/web_state/ui/crw_native_content_provider.h" #import "ios/web/web_state/ui/crw_web_controller.h" #import "ios/web/web_state/web_state_impl.h" @@ -241,6 +247,18 @@ BlockCleanupTest::TearDown(); } + // Returns a new unique_ptr containing a test webstate. + std::unique_ptr<web::TestWebState> CreateTestWebState() { + auto web_state = std::make_unique<web::TestWebState>(); + web_state->SetBrowserState(chrome_browser_state_.get()); + web_state->SetNavigationManager( + std::make_unique<web::TestNavigationManager>()); + id mockJsInjectionReceiver = OCMClassMock([CRWJSInjectionReceiver class]); + web_state->SetJSInjectionReceiver(mockJsInjectionReceiver); + AttachTabHelpers(web_state.get(), true); + return web_state; + } + MOCK_METHOD0(OnCompletionCalled, void()); web::TestWebThreadBundle thread_bundle_; @@ -256,6 +274,33 @@ UIWindow* window_; }; +TEST_F(BrowserViewControllerTest, TestSwitchToTab) { + WebStateList* web_state_list = tabModel_.webStateList; + ASSERT_EQ(0, web_state_list->count()); + + std::unique_ptr<web::TestWebState> web_state = CreateTestWebState(); + web::WebState* web_state_ptr = web_state.get(); + web_state->SetCurrentURL(GURL("http://test/1")); + web_state_list->InsertWebState(0, std::move(web_state), + WebStateList::INSERT_FORCE_INDEX, + WebStateOpener()); + + std::unique_ptr<web::TestWebState> web_state_2 = CreateTestWebState(); + web::WebState* web_state_ptr_2 = web_state_2.get(); + GURL url("http://test/2"); + web_state_2->SetCurrentURL(url); + web_state_list->InsertWebState(1, std::move(web_state_2), + WebStateList::INSERT_FORCE_INDEX, + WebStateOpener()); + + web_state_list->ActivateWebStateAt(0); + + ASSERT_EQ(web_state_ptr, web_state_list->GetActiveWebState()); + + [bvc_.dispatcher unfocusOmniboxAndSwitchToTabWithURL:url]; + EXPECT_EQ(web_state_ptr_2, web_state_list->GetActiveWebState()); +} + TEST_F(BrowserViewControllerTest, TestTabSelected) { [bvc_ tabSelected:tab_ notifyToolbar:YES]; EXPECT_EQ([[tab_ view] superview], [bvc_ contentArea]);
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index 8e91139..8acc5372 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -14,6 +14,7 @@ #import "ios/chrome/browser/ui/commands/qr_scanner_commands.h" #import "ios/chrome/browser/ui/commands/snackbar_commands.h" +class GURL; @class OpenNewTabCommand; @class ReadingListAddCommand; @@ -116,6 +117,9 @@ // omnibox. - (void)focusFakebox; +// Unfocus omnibox then switch to the first tab displaying |URL|. +- (void)unfocusOmniboxAndSwitchToTabWithURL:(const GURL&)URL; + @end #endif // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_articles_header_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_articles_header_item.mm index f7e932f2..582681b 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_articles_header_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_articles_header_item.mm
@@ -70,6 +70,14 @@ #pragma mark - ContentSuggestionsArticlesHeaderCell +@interface ContentSuggestionsArticlesHeaderCell () + +@property(nonatomic, strong) NSArray<NSLayoutConstraint*>* standardConstraints; +@property(nonatomic, strong) + NSArray<NSLayoutConstraint*>* accessibilityConstraints; + +@end + @implementation ContentSuggestionsArticlesHeaderCell @synthesize button = _button; @@ -83,34 +91,62 @@ _label.translatesAutoresizingMaskIntoConstraints = NO; _label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; _label.textColor = UIColorFromRGB(kLabelColorRGB, 1.0); + _label.adjustsFontForContentSizeCategory = YES; _label.adjustsFontSizeToFitWidth = YES; _button = [UIButton buttonWithType:UIButtonTypeSystem]; _button.translatesAutoresizingMaskIntoConstraints = NO; _button.titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + _button.titleLabel.adjustsFontForContentSizeCategory = YES; [_button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:_button]; [self.contentView addSubview:_label]; + + _standardConstraints = @[ + [_label.bottomAnchor + constraintEqualToAnchor:self.contentView.bottomAnchor], + [_button.topAnchor constraintEqualToAnchor:self.contentView.topAnchor], + [_label.trailingAnchor + constraintLessThanOrEqualToAnchor:_button.leadingAnchor], + [_button.trailingAnchor + constraintEqualToAnchor:self.contentView.trailingAnchor + constant:-kTextMargin], + ]; + _accessibilityConstraints = @[ + [_label.bottomAnchor + constraintEqualToAnchor:self.contentView.centerYAnchor], + [_button.topAnchor + constraintEqualToAnchor:self.contentView.centerYAnchor], + [_label.trailingAnchor + constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor + constant:-kTextMargin], + [_button.leadingAnchor + constraintEqualToAnchor:self.contentView.leadingAnchor + constant:kTextMargin], + [_button.trailingAnchor + constraintLessThanOrEqualToAnchor:self.contentView.trailingAnchor + constant:-kTextMargin], + ]; + [NSLayoutConstraint activateConstraints:@[ [_label.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:kTextMargin], [_label.topAnchor constraintEqualToAnchor:self.contentView.topAnchor], - [_label.bottomAnchor - constraintEqualToAnchor:self.contentView.bottomAnchor], - [_button.trailingAnchor - constraintEqualToAnchor:self.contentView.trailingAnchor - constant:-kTextMargin], - [_button.topAnchor constraintEqualToAnchor:self.contentView.topAnchor], [_button.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor], - [_label.trailingAnchor - constraintLessThanOrEqualToAnchor:_button.leadingAnchor] ]]; + + if (ContentSizeCategoryIsAccessibilityCategory( + self.traitCollection.preferredContentSizeCategory)) { + [NSLayoutConstraint activateConstraints:_accessibilityConstraints]; + } else { + [NSLayoutConstraint activateConstraints:_standardConstraints]; + } } return self; } @@ -120,6 +156,27 @@ self.delegate = nil; } +#pragma mark - UIView + +- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + BOOL isCurrentCategoryAccessibility = + ContentSizeCategoryIsAccessibilityCategory( + self.traitCollection.preferredContentSizeCategory); + BOOL isPreviousCategoryAccessibility = + ContentSizeCategoryIsAccessibilityCategory( + previousTraitCollection.preferredContentSizeCategory); + if (isCurrentCategoryAccessibility != isPreviousCategoryAccessibility) { + if (isCurrentCategoryAccessibility) { + [NSLayoutConstraint deactivateConstraints:self.standardConstraints]; + [NSLayoutConstraint activateConstraints:self.accessibilityConstraints]; + } else { + [NSLayoutConstraint deactivateConstraints:self.accessibilityConstraints]; + [NSLayoutConstraint activateConstraints:self.standardConstraints]; + } + } +} + #pragma mark Private // Callback for the button action.
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h index 3fc5d52..04c269f1 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h
@@ -7,14 +7,14 @@ #import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" -@class FaviconViewNew; +@class FaviconView; // Corresponding cell for an article in the suggestions. @interface ContentSuggestionsCell : MDCCollectionViewCell @property(nonatomic, readonly, strong) UILabel* titleLabel; // View for displaying the favicon. -@property(nonatomic, readonly, strong) FaviconViewNew* faviconView; +@property(nonatomic, readonly, strong) FaviconView* faviconView; // Whether the image should be displayed. @property(nonatomic, assign) BOOL displayImage;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm index 1f434a7..73c06350 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm
@@ -90,7 +90,7 @@ _noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero]; _additionalInformationLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _contentImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; - _faviconView = [[FaviconViewNew alloc] init]; + _faviconView = [[FaviconView alloc] init]; _contentImageView.contentMode = UIViewContentModeScaleAspectFill; _contentImageView.clipsToBounds = YES;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h index c368321..e6fd6f5 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h
@@ -7,14 +7,14 @@ #import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" -@class FaviconViewNew; +@class FaviconView; // Associated cell to display a Most Visited tile based on the suggestion. // It displays the favicon for this Most Visited suggestion and its title. @interface ContentSuggestionsMostVisitedCell : MDCCollectionViewCell // FaviconView displaying the favicon. -@property(nonatomic, strong, readonly, nonnull) FaviconViewNew* faviconView; +@property(nonatomic, strong, readonly, nonnull) FaviconView* faviconView; // Title of the Most Visited. @property(nonatomic, strong, readonly, nonnull) UILabel* titleLabel;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm index c0c11286..09a8bc3 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.mm
@@ -31,7 +31,7 @@ _titleLabel.preferredMaxLayoutWidth = [[self class] defaultSize].width; _titleLabel.numberOfLines = kLabelNumLines; - _faviconView = [[FaviconViewNew alloc] init]; + _faviconView = [[FaviconView alloc] init]; _faviconView.font = [UIFont systemFontOfSize:22]; _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; _faviconView.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.mm index e95c525..6730895 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.mm
@@ -6,8 +6,6 @@ #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_cell.h" #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion_identifier.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -59,16 +57,20 @@ // Configures the |textLabel|. - (void)configureTextLabel:(UILabel*)textLabel { textLabel.text = self.text; - textLabel.textColor = [[MDCPalette greyPalette] tint900]; - textLabel.font = [MDCTypography body2Font]; + textLabel.textColor = [UIColor colorWithWhite:0.13 alpha:1]; + textLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + textLabel.adjustsFontForContentSizeCategory = YES; textLabel.numberOfLines = 0; } // Configures the |detailTextLabel|. - (void)configureDetailTextLabel:(UILabel*)detailTextLabel { detailTextLabel.text = self.detailText; - detailTextLabel.textColor = [[MDCPalette greyPalette] tint500]; - detailTextLabel.font = [MDCTypography body1Font]; + detailTextLabel.textColor = [UIColor colorWithWhite:0.62 alpha:1]; + detailTextLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + detailTextLabel.adjustsFontForContentSizeCategory = YES; detailTextLabel.numberOfLines = 0; }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 1221f87f..b7c36cc 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -439,9 +439,16 @@ if ([self.collectionUpdater isHeaderSection:section]) { return CGSizeMake(0, [self.headerSynchronizer headerHeight]); } - return [super collectionView:collectionView - layout:collectionViewLayout - referenceSizeForHeaderInSection:section]; + CGSize defaultSize = [super collectionView:collectionView + layout:collectionViewLayout + referenceSizeForHeaderInSection:section]; + if (ContentSizeCategoryIsAccessibilityCategory( + self.traitCollection.preferredContentSizeCategory) && + [self.collectionUpdater isContentSuggestionsSection:section]) { + // Double the size of the header as it is now on two lines. + defaultSize.height *= 2; + } + return defaultSize; } - (BOOL)collectionView:(nonnull UICollectionView*)collectionView
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm index d620558c..d59fdf85 100644 --- a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm +++ b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm
@@ -201,32 +201,32 @@ @end @implementation SwitchView { - UISwitch* switch_; - CGFloat preferredTotalWidth_; + UISwitch* _switch; + CGFloat _preferredTotalWidth; // Layout metrics for calculating item placement. - const LayoutMetrics* metrics_; + const LayoutMetrics* _metrics; } - (instancetype)initWithText:(NSString*)labelText isOn:(BOOL)isOn { - metrics_ = &kLayoutMetrics; + _metrics = &kLayoutMetrics; self = [super initWithText:labelText]; if (!self) return nil; self.label.textColor = [UIColor blackColor]; - switch_ = [[UISwitch alloc] initWithFrame:CGRectZero]; - switch_.exclusiveTouch = YES; - switch_.accessibilityLabel = labelText; - switch_.onTintColor = [[MDCPalette cr_bluePalette] tint500]; - switch_.on = isOn; + _switch = [[UISwitch alloc] initWithFrame:CGRectZero]; + _switch.exclusiveTouch = YES; + _switch.accessibilityLabel = labelText; + _switch.onTintColor = [[MDCPalette cr_bluePalette] tint500]; + _switch.on = isOn; // Computes the size and initializes the view. CGSize labelSize = self.label.frame.size; - CGSize switchSize = switch_.frame.size; + CGSize switchSize = _switch.frame.size; CGRect frameRect = CGRectMake( 0, 0, - labelSize.width + metrics_->space_between_widgets + switchSize.width, + labelSize.width + _metrics->space_between_widgets + switchSize.width, std::max(labelSize.height, switchSize.height)); [self setFrame:frameRect]; @@ -244,30 +244,30 @@ switchFrame = AlignRectOriginAndSizeToPixels(switchFrame); [self.label setFrame:labelFrame]; - [switch_ setFrame:switchFrame]; - preferredTotalWidth_ = CGRectGetMaxX(switchFrame); + [_switch setFrame:switchFrame]; + _preferredTotalWidth = CGRectGetMaxX(switchFrame); self.preferredLabelWidth = CGRectGetMaxX(labelFrame); [self addSubview:self.label]; - [self addSubview:switch_]; + [self addSubview:_switch]; return self; } - (void)setTag:(NSInteger)tag target:(id)target action:(SEL)action { - [switch_ setTag:tag]; - [switch_ addTarget:target + [_switch setTag:tag]; + [_switch addTarget:target action:action forControlEvents:UIControlEventValueChanged]; } - (CGFloat)heightRequiredForFooterWithWidth:(CGFloat)width layout:(BOOL)layout { CGFloat widthLeftForLabel = - width - [switch_ frame].size.width - metrics_->space_between_widgets; + width - [_switch frame].size.width - _metrics->space_between_widgets; CGSize maxSize = CGSizeMake(widthLeftForLabel, CGFLOAT_MAX); CGSize labelSize = [[self.label text] cr_boundingSizeWithSize:maxSize font:[self.label font]]; - CGFloat viewHeight = std::max(labelSize.height, [switch_ frame].size.height); + CGFloat viewHeight = std::max(labelSize.height, [_switch frame].size.height); if (layout) { // Lays out the label and the switch to fit in {width, viewHeight}. CGRect newLabelFrame; @@ -278,17 +278,17 @@ [self.label setFrame:newLabelFrame]; CGRect newSwitchFrame; newSwitchFrame.origin.x = - CGRectGetMaxX(newLabelFrame) + metrics_->space_between_widgets; - newSwitchFrame.origin.y = (viewHeight - [switch_ frame].size.height) / 2; - newSwitchFrame.size = [switch_ frame].size; + CGRectGetMaxX(newLabelFrame) + _metrics->space_between_widgets; + newSwitchFrame.origin.y = (viewHeight - [_switch frame].size.height) / 2; + newSwitchFrame.size = [_switch frame].size; newSwitchFrame = AlignRectOriginAndSizeToPixels(newSwitchFrame); - [switch_ setFrame:newSwitchFrame]; + [_switch setFrame:newSwitchFrame]; } return viewHeight; } - (CGFloat)preferredWidth { - return preferredTotalWidth_; + return _preferredTotalWidth; } @end
diff --git a/ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h b/ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h index 06a4ee45..9658e21 100644 --- a/ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h +++ b/ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h
@@ -22,7 +22,7 @@ // Tells the delegate when a suggestion in|row| was chosen for appending to // omnibox. - (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender - didSelectRowForAppending:(NSUInteger)row; + didTapTrailingButtonForRow:(NSUInteger)row; // Tells the delegate when a suggestion in |row| was removed. - (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender didSelectRowForDeletion:(NSUInteger)row;
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index d92c3c5f..374dcdc5 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -52,6 +52,7 @@ "self_sizing_table_view.mm", ] deps = [ + "resources:omnibox_popup_tab_match", "//base", "//components/image_fetcher/ios", "//components/omnibox/browser", @@ -73,9 +74,12 @@ ] deps = [ ":popup", + ":popup_internal", "//base", + "//components/omnibox/browser", "//ios/chrome/app/strings", "//ios/chrome/browser", + "//ios/chrome/browser/ui/omnibox:omnibox_internal", "//testing/gtest", "//ui/base", ]
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm index 189072e3..20d31d8 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -61,6 +61,7 @@ self.mediator = [[OmniboxPopupMediator alloc] initWithFetcher:std::move(imageFetcher) delegate:_popupView.get()]; + self.mediator.dispatcher = (id<BrowserCommands>)self.dispatcher; self.popupViewController = [[OmniboxPopupViewController alloc] init]; self.popupViewController.incognito = self.browserState->IsOffTheRecord();
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h index 625210e9..16997a9 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h" #import "ios/chrome/browser/ui/omnibox/image_retriever.h" +@protocol BrowserCommands; @class OmniboxPopupPresenter; namespace image_fetcher { @@ -48,6 +49,7 @@ // Updates the popup with the |results|. - (void)updateWithResults:(const AutocompleteResult&)results; +@property(nonatomic, weak) id<BrowserCommands> dispatcher; @property(nonatomic, weak) id<AutocompleteResultConsumer> consumer; @property(nonatomic, assign, getter=isIncognito) BOOL incognito; // Whether the popup is open.
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm index ded70cc..e7a0859 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
@@ -10,6 +10,7 @@ #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_result.h" +#import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/omnibox/autocomplete_match_formatter.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h" @@ -113,19 +114,22 @@ } - (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender - didSelectRowForAppending:(NSUInteger)row { + didTapTrailingButtonForRow:(NSUInteger)row { const AutocompleteMatch& match = ((const AutocompleteResult&)_currentResult).match_at(row); - if (AutocompleteMatch::IsSearchType(match.type)) { - base::RecordAction( - base::UserMetricsAction("MobileOmniboxRefineSuggestion.Search")); + if (match.has_tab_match) { + [self.dispatcher unfocusOmniboxAndSwitchToTabWithURL:match.destination_url]; } else { - base::RecordAction( - base::UserMetricsAction("MobileOmniboxRefineSuggestion.Url")); + if (AutocompleteMatch::IsSearchType(match.type)) { + base::RecordAction( + base::UserMetricsAction("MobileOmniboxRefineSuggestion.Search")); + } else { + base::RecordAction( + base::UserMetricsAction("MobileOmniboxRefineSuggestion.Url")); + } + _delegate->OnMatchSelectedForAppending(match); } - - _delegate->OnMatchSelectedForAppending(match); } - (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h index d0e5196..74a208efd 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h
@@ -24,8 +24,11 @@ @property(nonatomic, readonly, strong) UIImageView* imageView; @property(nonatomic, readonly, strong) UIImageView* answerImageView; -@property(nonatomic, readonly, strong) UIButton* appendButton; +@property(nonatomic, readonly, strong) UIButton* trailingButton; @property(nonatomic, assign) CGFloat rowHeight; +// Whether this row is displaying a TabMatch. If YES, the trailing icon is +// updated to reflect that. +@property(nonatomic, assign, getter=isTabMatch) BOOL tabMatch; // Initialize the row with the given incognito state. The colors and styling are // dependent on whether or not the row is displayed in incognito mode.
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.mm index 44e31b0..ea0f8a3 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.mm
@@ -20,8 +20,8 @@ // Side (w or h) length for the leading image view. const CGFloat kImageViewSizeUIRefresh = 28.0; const CGFloat kImageViewCornerRadiusUIRefresh = 7.0; -const CGFloat kAppendButtonTrailingMargin = 4; -const CGFloat kAppendButtonSize = 48.0; +const CGFloat kTrailingButtonTrailingMargin = 4; +const CGFloat kTrailingButtonSize = 48.0; } @interface OmniboxPopupRow () { @@ -29,7 +29,7 @@ } // Set the append button normal and highlighted images. -- (void)updateAppendButtonImages; +- (void)updateTrailingButtonImages; @end @@ -38,7 +38,7 @@ @synthesize textTruncatingLabel = _textTruncatingLabel; @synthesize detailTruncatingLabel = _detailTruncatingLabel; @synthesize detailAnswerLabel = _detailAnswerLabel; -@synthesize appendButton = _appendButton; +@synthesize trailingButton = _trailingButton; @synthesize answerImageView = _answerImageView; @synthesize imageView = _imageView; @synthesize rowHeight = _rowHeight; @@ -73,12 +73,12 @@ _detailAnswerLabel.lineBreakMode = NSLineBreakByTruncatingTail; [self.contentView addSubview:_detailAnswerLabel]; - _appendButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [_appendButton setContentMode:UIViewContentModeRight]; - [self updateAppendButtonImages]; + _trailingButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_trailingButton setContentMode:UIViewContentModeRight]; + [self updateTrailingButtonImages]; // TODO(justincohen): Consider using the UITableViewCell's accessory view. // The current implementation is from before using a UITableViewCell. - [self.contentView addSubview:_appendButton]; + [self.contentView addSubview:_trailingButton]; // Before UI Refresh, the leading icon is only displayed on iPad. In UI // Refresh, it's only in Regular x Regular size class. @@ -134,11 +134,11 @@ LayoutRect trailingAccessoryLayout = LayoutRectMake(CGRectGetWidth(self.contentView.bounds) - - kAppendButtonSize - kAppendButtonTrailingMargin, + kTrailingButtonSize - kTrailingButtonTrailingMargin, CGRectGetWidth(self.contentView.bounds), - floor((_rowHeight - kAppendButtonSize) / 2), - kAppendButtonSize, kAppendButtonSize); - _appendButton.frame = LayoutRectGetRect(trailingAccessoryLayout); + floor((_rowHeight - kTrailingButtonSize) / 2), + kTrailingButtonSize, kTrailingButtonSize); + _trailingButton.frame = LayoutRectGetRect(trailingAccessoryLayout); } - (void)updateLeadingImage:(UIImage*)image { @@ -173,27 +173,38 @@ [self updateHighlightBackground:highlighted]; } -- (void)updateAppendButtonImages { - int appendResourceID = _incognito - ? IDR_IOS_OMNIBOX_KEYBOARD_VIEW_APPEND_INCOGNITO - : IDR_IOS_OMNIBOX_KEYBOARD_VIEW_APPEND; - UIImage* appendImage = NativeReversableImage(appendResourceID, YES); +- (void)setTabMatch:(BOOL)tabMatch { + _tabMatch = tabMatch; + [self updateTrailingButtonImages]; +} + +- (void)updateTrailingButtonImages { + UIImage* appendImage = nil; + if (self.tabMatch) { + appendImage = [UIImage imageNamed:@"omnibox_popup_tab_match"]; + } else { + int appendResourceID = _incognito + ? IDR_IOS_OMNIBOX_KEYBOARD_VIEW_APPEND_INCOGNITO + : IDR_IOS_OMNIBOX_KEYBOARD_VIEW_APPEND; + appendImage = NativeReversableImage(appendResourceID, YES); + } if (IsUIRefreshPhase1Enabled()) { appendImage = [appendImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - _appendButton.tintColor = _incognito ? [UIColor colorWithWhite:1 alpha:0.5] - : [UIColor colorWithWhite:0 alpha:0.3]; + _trailingButton.tintColor = _incognito + ? [UIColor colorWithWhite:1 alpha:0.5] + : [UIColor colorWithWhite:0 alpha:0.3]; } else { int appendSelectedResourceID = _incognito ? IDR_IOS_OMNIBOX_KEYBOARD_VIEW_APPEND_INCOGNITO_HIGHLIGHTED : IDR_IOS_OMNIBOX_KEYBOARD_VIEW_APPEND_HIGHLIGHTED; UIImage* appendImageSelected = NativeReversableImage(appendSelectedResourceID, YES); - [_appendButton setImage:appendImageSelected - forState:UIControlStateHighlighted]; + [_trailingButton setImage:appendImageSelected + forState:UIControlStateHighlighted]; } - [_appendButton setImage:appendImage forState:UIControlStateNormal]; + [_trailingButton setImage:appendImage forState:UIControlStateNormal]; } - (NSString*)accessibilityLabel {
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm index 16bb342..05ebb66 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -153,10 +153,10 @@ [NSString stringWithFormat:@"omnibox suggestion %i", i]; row.autoresizingMask = UIViewAutoresizingFlexibleWidth; [rowsBuilder addObject:row]; - [row.appendButton addTarget:self - action:@selector(appendButtonTapped:) - forControlEvents:UIControlEventTouchUpInside]; - [row.appendButton setTag:i]; + [row.trailingButton addTarget:self + action:@selector(trailingButtonTapped:) + forControlEvents:UIControlEventTouchUpInside]; + [row.trailingButton setTag:i]; row.rowHeight = kRowHeight; } _rows = [rowsBuilder copy]; @@ -284,7 +284,7 @@ const CGFloat kDetailCellTopPadding = 26; const CGFloat kTextLabelHeight = 24; const CGFloat kTextDetailLabelHeight = 22; - const CGFloat kAppendButtonWidth = 40; + const CGFloat kTrailingButtonWidth = 40; const CGFloat kAnswerLabelHeight = 36; const CGFloat kAnswerImageWidth = 30; const CGFloat kAnswerImageLeftPadding = -1; @@ -308,7 +308,7 @@ kTextCellLeadingPadding + kAnswerImageLeftPadding; if (alignmentRight) { imageLeftPadding = - row.frame.size.width - (kAnswerImageWidth + kAppendButtonWidth); + row.frame.size.width - (kAnswerImageWidth + kTrailingButtonWidth); } CGFloat imageTopPadding = kDetailCellTopPadding + kAnswerImageTopPadding; row.answerImageView.frame = @@ -396,22 +396,24 @@ [row updateLeadingImage:image]; } + row.tabMatch = match.isTabMatch; + // Show append button for search history/search suggestions as the right // control element (aka an accessory element of a table view cell). - row.appendButton.hidden = !match.isAppendable; - [row.appendButton cancelTrackingWithEvent:nil]; + row.trailingButton.hidden = !match.isAppendable && !match.isTabMatch; + [row.trailingButton cancelTrackingWithEvent:nil]; // If a right accessory element is present or the text alignment is right // aligned, adjust the width to align with the accessory element. if (match.isAppendable || alignmentRight) { LayoutRect layout = LayoutRectForRectInBoundingRect(textLabel.frame, self.view.frame); - layout.size.width -= kAppendButtonWidth; + layout.size.width -= kTrailingButtonWidth; textLabel.frame = LayoutRectGetRect(layout); layout = LayoutRectForRectInBoundingRect(detailTextLabel.frame, self.view.frame); layout.size.width -= - kAppendButtonWidth + (match.hasImage ? answerImagePadding : 0); + kTrailingButtonWidth + (match.hasImage ? answerImagePadding : 0); detailTextLabel.frame = LayoutRectGetRect(layout); } @@ -524,9 +526,10 @@ #pragma mark - #pragma mark Action for append UIButton -- (void)appendButtonTapped:(id)sender { +- (void)trailingButtonTapped:(id)sender { NSUInteger row = [sender tag]; - [self.delegate autocompleteResultConsumer:self didSelectRowForAppending:row]; + [self.delegate autocompleteResultConsumer:self + didTapTrailingButtonForRow:row]; } #pragma mark -
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller_unittest.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller_unittest.mm index 3117c0e..e864000 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller_unittest.mm
@@ -4,6 +4,9 @@ #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h" +#include "components/omnibox/browser/autocomplete_match.h" +#import "ios/chrome/browser/ui/omnibox/autocomplete_match_formatter.h" +#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -23,14 +26,14 @@ OmniboxPopupViewController* popup_view_controller_; }; -TEST_F(OmniboxPopupViewControllerTest, hasCellsWhenShortcutsEnabled) { +TEST_F(OmniboxPopupViewControllerTest, HasCellsWhenShortcutsEnabled) { // This test makes an assumption that this view controller is a datasource for // a table view. Rewrite this test if this is not the case anymore. EXPECT_TRUE([popup_view_controller_ conformsToProtocol:@protocol(UITableViewDataSource)]); id<UITableViewDataSource> datasource = (id<UITableViewDataSource>)popup_view_controller_; - UITableView* tableView = [[UITableView alloc] init]; + UITableView* table_view = [[UITableView alloc] init]; // A stub view controller. UIViewController* shortcutsViewController = [[UIViewController alloc] init]; @@ -40,17 +43,52 @@ // Check that the shorcuts row doesn't appear. [popup_view_controller_ updateMatches:@[] withAnimation:NO]; - EXPECT_EQ([datasource tableView:tableView numberOfRowsInSection:0], 0); + EXPECT_EQ([datasource tableView:table_view numberOfRowsInSection:0], 0); // Enable shortcuts and verify they appear. When enabling, the view controller // has to be non-nil. popup_view_controller_.shortcutsViewController = shortcutsViewController; popup_view_controller_.shortcutsEnabled = YES; - EXPECT_EQ([datasource tableView:tableView numberOfRowsInSection:0], 1); + EXPECT_EQ([datasource tableView:table_view numberOfRowsInSection:0], 1); // Disable and verify it disappears again. popup_view_controller_.shortcutsEnabled = NO; - EXPECT_EQ([datasource tableView:tableView numberOfRowsInSection:0], 0); + EXPECT_EQ([datasource tableView:table_view numberOfRowsInSection:0], 0); +} + +TEST_F(OmniboxPopupViewControllerTest, HasTabMatch) { + EXPECT_TRUE([popup_view_controller_ + conformsToProtocol:@protocol(UITableViewDataSource)]); + id<UITableViewDataSource> datasource = + (id<UITableViewDataSource>)popup_view_controller_; + UITableView* table_view = [[UITableView alloc] init]; + + // Check that if the match has a tab match, the cell's trailing button is + // visible. + AutocompleteMatch match; + match.has_tab_match = true; + AutocompleteMatchFormatter* formatter = + [[AutocompleteMatchFormatter alloc] initWithMatch:match]; + [popup_view_controller_ updateMatches:@[ formatter ] withAnimation:NO]; + + EXPECT_EQ([datasource tableView:table_view numberOfRowsInSection:0], 1); + OmniboxPopupRow* cell = static_cast<OmniboxPopupRow*>([datasource + tableView:table_view + cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]); + + EXPECT_FALSE(cell.trailingButton.hidden); + + // Check that it is not the case if the tab match isn't visible. + match.has_tab_match = false; + formatter = [[AutocompleteMatchFormatter alloc] initWithMatch:match]; + [popup_view_controller_ updateMatches:@[ formatter ] withAnimation:NO]; + + EXPECT_EQ([datasource tableView:table_view numberOfRowsInSection:0], 1); + cell = static_cast<OmniboxPopupRow*>([datasource + tableView:table_view + cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]); + + EXPECT_TRUE(cell.trailingButton.hidden); } } // namespace
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn new file mode 100644 index 0000000..c7ac8e48e --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ios/asset_catalog.gni") + +imageset("omnibox_popup_tab_match") { + sources = [ + "omnibox_popup_tab_match.imageset/Contents.json", + "omnibox_popup_tab_match.imageset/omnibox_popup_tab_match.png", + "omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@2x.png", + "omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/Contents.json b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/Contents.json new file mode 100644 index 0000000..3b1fa9d --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "omnibox_popup_tab_match.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "omnibox_popup_tab_match@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "omnibox_popup_tab_match@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match.png b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match.png new file mode 100644 index 0000000..0ee350d --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match.png Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@2x.png b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@2x.png new file mode 100644 index 0000000..3c5140b --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@3x.png b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@3x.png new file mode 100644 index 0000000..9bf6189 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_popup_tab_match.imageset/omnibox_popup_tab_match@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index f56c4d5..1c2ccc7a 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -73,8 +73,6 @@ source_set("reading_list_ui") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "empty_reading_list_background_view.h", - "empty_reading_list_background_view.mm", "empty_reading_list_message_util.h", "empty_reading_list_message_util.mm", "number_badge_view.h",
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h b/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h deleted file mode 100644 index 869735f6..0000000 --- a/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_BACKGROUND_VIEW_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_BACKGROUND_VIEW_H_ - -#import <UIKit/UIKit.h> - -// The view to use as the background view for an empty reading list list view. -@interface EmptyReadingListBackgroundView : UIView - -- (instancetype)init NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - -+ (NSString*)accessibilityIdentifier; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_BACKGROUND_VIEW_H_
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.mm b/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.mm deleted file mode 100644 index ca0ba69..0000000 --- a/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.mm +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h" - -#include "base/logging.h" -#import "ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -// Images name. -NSString* const kEmptyReadingListBackgroundIcon = @"reading_list_empty_state"; - -// Background view constants. -const CGFloat kImageHeight = 44; -const CGFloat kImageWidth = 60; -const CGFloat kPercentageFromTopForPosition = 0.4; -const CGFloat kTextHorizontalMinimumMargin = 32; -const CGFloat kTextImageSpacing = 10; -const CGFloat kTextMaximalWidth = 255; -} // namespace - -@interface EmptyReadingListBackgroundView () - -// Sets the constraints for this view, positionning the |imageView| in the X -// center and at 40% of the top. The |label| is positionned below. -- (void)setConstraintsToImageView:(UIImageView*)imageView - andLabel:(UILabel*)label; - -@end - -@implementation EmptyReadingListBackgroundView - -#pragma mark - Public - -- (instancetype)init { - self = [super initWithFrame:CGRectZero]; - if (self) { - - // Attach to the label. - UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; - label.attributedText = GetReadingListEmptyMessage(); - label.numberOfLines = 0; - label.textAlignment = NSTextAlignmentCenter; - label.accessibilityLabel = GetReadingListEmptyMessageA11yLabel(); - label.accessibilityIdentifier = - [EmptyReadingListBackgroundView accessibilityIdentifier]; - [label setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self addSubview:label]; - - UIImageView* imageView = [[UIImageView alloc] init]; - imageView.image = [UIImage imageNamed:kEmptyReadingListBackgroundIcon]; - [imageView setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self addSubview:imageView]; - - [self setConstraintsToImageView:imageView andLabel:label]; - } - return self; -} - -+ (NSString*)accessibilityIdentifier { - return @"ReadingListBackgroundViewIdentifier"; -} - -#pragma mark - Private - -- (void)setConstraintsToImageView:(UIImageView*)imageView - andLabel:(UILabel*)label { - [NSLayoutConstraint activateConstraints:@[ - [imageView.heightAnchor constraintEqualToConstant:kImageHeight], - [imageView.widthAnchor constraintEqualToConstant:kImageWidth], - [self.centerXAnchor constraintEqualToAnchor:label.centerXAnchor], - [self.centerXAnchor constraintEqualToAnchor:imageView.centerXAnchor], - [label.topAnchor constraintEqualToAnchor:imageView.bottomAnchor - constant:kTextImageSpacing], - [label.trailingAnchor - constraintLessThanOrEqualToAnchor:self.trailingAnchor - constant:-kTextHorizontalMinimumMargin], - [label.leadingAnchor - constraintGreaterThanOrEqualToAnchor:self.leadingAnchor - constant:kTextHorizontalMinimumMargin] - ]]; - - NSLayoutConstraint* widthConstraint = - [label.widthAnchor constraintEqualToConstant:kTextMaximalWidth]; - widthConstraint.priority = UILayoutPriorityDefaultHigh; - widthConstraint.active = YES; - - // Position the top of the image at 40% from the top. - NSLayoutConstraint* verticalAlignment = - [NSLayoutConstraint constraintWithItem:imageView - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:self - attribute:NSLayoutAttributeBottom - multiplier:kPercentageFromTopForPosition - constant:0]; - [self addConstraints:@[ verticalAlignment ]]; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm b/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm index de93e4f..430cad8c 100644 --- a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm +++ b/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm
@@ -27,9 +27,30 @@ // Background view constants. const CGFloat kLineSpacing = 4; +UIFont* FontWithMaximumForCategory(UIContentSizeCategory category, + UIFontTextStyle font_style) { + if (ContentSizeCategoryIsAccessibilityCategory(category)) { + return [UIFont + preferredFontForTextStyle:font_style + compatibleWithTraitCollection: + [UITraitCollection traitCollectionWithPreferredContentSizeCategory: + UIContentSizeCategoryAccessibilityLarge]]; + } + return [UIFont preferredFontForTextStyle:font_style]; +} + // Returns the font to use for the message text. UIFont* GetMessageFont() { - return [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + return FontWithMaximumForCategory( + [UIApplication sharedApplication].preferredContentSizeCategory, + UIFontTextStyleBody); +} + +// Returns the font to use for the message text. +UIFont* GetInstructionFont() { + return FontWithMaximumForCategory( + [UIApplication sharedApplication].preferredContentSizeCategory, + UIFontTextStyleHeadline); } // Returns the attributes to use for the message text. @@ -54,8 +75,7 @@ // Later" option. NSMutableDictionary* GetInstructionAttributes() { NSMutableDictionary* attributes = GetMessageAttributes(); - attributes[NSFontAttributeName] = - [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + attributes[NSFontAttributeName] = GetInstructionFont(); return attributes; }
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm index 8654318..b31f1fe 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -17,7 +17,6 @@ #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/ui/commands/reading_list_add_command.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" -#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h" #import "ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h" #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_identifiers.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_url_cell_favicon_badge_view.h"
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index e1701ea..04ef2f13 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -22,6 +22,7 @@ #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_commands.h" #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_manager.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -224,6 +225,15 @@ [self exitEditingModeAnimated:YES]; } +- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + if (!self.dataSource.hasElements && + self.traitCollection.preferredContentSizeCategory != + previousTraitCollection.preferredContentSizeCategory) { + [self tableIsEmpty]; + } +} + #pragma mark - UITableViewDataSource - (void)tableView:(UITableView*)tableView
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_url_item.h b/ios/chrome/browser/ui/table_view/cells/table_view_url_item.h index 20b7fce7..d44e41a53 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_url_item.h +++ b/ios/chrome/browser/ui/table_view/cells/table_view_url_item.h
@@ -10,7 +10,7 @@ #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" class GURL; -@class FaviconViewNew; +@class FaviconView; @class TableViewURLCellFaviconBadgeView; // TableViewURLItem contains the model data for a TableViewURLCell. @@ -41,7 +41,7 @@ // The imageview that is displayed on the leading edge of the cell. This // contains a favicon composited on top of an off-white background. -@property(nonatomic, readonly, strong) FaviconViewNew* faviconView; +@property(nonatomic, readonly, strong) FaviconView* faviconView; // Container View for the faviconView. @property(nonatomic, readonly, strong) UIImageView* faviconContainerView;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm index 55e5b8c..36e7bd3 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_url_item.mm
@@ -152,7 +152,7 @@ _faviconContainerView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"table_view_cell_favicon_background"]]; - _faviconView = [[FaviconViewNew alloc] init]; + _faviconView = [[FaviconView alloc] init]; _faviconView.contentMode = UIViewContentModeScaleAspectFit; _faviconView.clipsToBounds = YES; [_faviconContainerView addSubview:_faviconView];
diff --git a/ios/chrome/common/favicon/favicon_view.h b/ios/chrome/common/favicon/favicon_view.h index c0a05e2..41cd295 100644 --- a/ios/chrome/common/favicon/favicon_view.h +++ b/ios/chrome/common/favicon/favicon_view.h
@@ -16,7 +16,7 @@ const CGFloat kFaviconPreferredSize = 24.0f; } // namespace -@interface FaviconViewNew : UIView +@interface FaviconView : UIView // Configures this view with given attributes. - (void)configureWithAttributes:(nullable FaviconAttributes*)attributes;
diff --git a/ios/chrome/common/favicon/favicon_view.mm b/ios/chrome/common/favicon/favicon_view.mm index 947d7ee..c0f823c 100644 --- a/ios/chrome/common/favicon/favicon_view.mm +++ b/ios/chrome/common/favicon/favicon_view.mm
@@ -15,8 +15,8 @@ const CGFloat kDefaultCornerRadius = 3; } -@interface FaviconViewNew () { - // Property releaser for FaviconViewNew. +@interface FaviconView () { + // Property releaser for FaviconView. } // Image view for the favicon. @@ -26,7 +26,7 @@ @end -@implementation FaviconViewNew +@implementation FaviconView @synthesize faviconImageView = _faviconImageView; @synthesize faviconFallbackLabel = _faviconFallbackLabel;
diff --git a/ios/chrome/content_widget_extension/most_visited_tile_view.h b/ios/chrome/content_widget_extension/most_visited_tile_view.h index 1ea15fa4..90b6bbc4 100644 --- a/ios/chrome/content_widget_extension/most_visited_tile_view.h +++ b/ios/chrome/content_widget_extension/most_visited_tile_view.h
@@ -9,7 +9,7 @@ #import "ios/chrome/common/highlight_button.h" -@class FaviconViewNew; +@class FaviconView; // View to display a Most Visited tile based on the suggestion. // It displays the favicon for this Most Visited suggestion and its title. @@ -24,7 +24,7 @@ - (nonnull instancetype)initWithCoder:(nonnull NSCoder*)aDecoder NS_UNAVAILABLE; // FaviconView displaying the favicon. -@property(nonatomic, strong, readonly, nonnull) FaviconViewNew* faviconView; +@property(nonatomic, strong, readonly, nonnull) FaviconView* faviconView; // Title of the Most Visited. @property(nonatomic, strong, readonly, nonnull) UILabel* titleLabel;
diff --git a/ios/chrome/content_widget_extension/most_visited_tile_view.mm b/ios/chrome/content_widget_extension/most_visited_tile_view.mm index 8623ab02..dbfe663 100644 --- a/ios/chrome/content_widget_extension/most_visited_tile_view.mm +++ b/ios/chrome/content_widget_extension/most_visited_tile_view.mm
@@ -56,7 +56,7 @@ [titleLabelEffectView.contentView addSubview:_titleLabel]; AddSameConstraints(titleLabelEffectView, _titleLabel); - _faviconView = [[FaviconViewNew alloc] init]; + _faviconView = [[FaviconView alloc] init]; _faviconView.isAccessibilityElement = NO; _faviconView.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index 59b6e434..b616e028 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -402,6 +402,7 @@ "//components/browser_sync:test_support", "//components/prefs:test_support", "//components/signin/core/browser:test_support", + "//components/signin/ios/browser:test_support", "//components/sync:test_support_driver", "//ios/web/public/test", "//ios/web/public/test/fakes",
diff --git a/ios/web_view/internal/passwords/cwv_password_controller.mm b/ios/web_view/internal/passwords/cwv_password_controller.mm index 6d310a7..90603a7 100644 --- a/ios/web_view/internal/passwords/cwv_password_controller.mm +++ b/ios/web_view/internal/passwords/cwv_password_controller.mm
@@ -12,7 +12,7 @@ #include "components/autofill/ios/browser/autofill_util.h" #import "components/password_manager/core/browser/form_parsing/ios_form_parser.h" #include "components/password_manager/core/browser/password_manager.h" -#import "components/password_manager/ios/password_controller_helper.h" +#import "components/password_manager/ios/password_form_helper.h" #import "ios/web/public/origin_util.h" #include "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" @@ -36,14 +36,14 @@ @interface CWVPasswordController ()<CRWWebStateObserver, CWVPasswordManagerClientDelegate, CWVPasswordManagerDriverDelegate, - PasswordControllerHelperDelegate> + PasswordFormHelperDelegate> // The PasswordManagerDriver owned by this PasswordController. @property(nonatomic, readonly) password_manager::PasswordManagerDriver* passwordManagerDriver; -// Helper contains common password controller logic. -@property(nonatomic, readonly) PasswordControllerHelper* helper; +// Helper contains common password form processing logic. +@property(nonatomic, readonly) PasswordFormHelper* formHelper; // Delegate to receive password autofill suggestion callbacks. @property(nonatomic, weak, nullable) id<CWVPasswordControllerDelegate> delegate; @@ -83,7 +83,7 @@ #pragma mark - Properties -@synthesize helper = _helper; +@synthesize formHelper = _formHelper; @synthesize delegate = _delegate; - (password_manager::PasswordManagerDriver*)passwordManagerDriver { @@ -102,8 +102,8 @@ _webStateObserverBridge = std::make_unique<web::WebStateObserverBridge>(self); _webState->AddObserver(_webStateObserverBridge.get()); - _helper = [[PasswordControllerHelper alloc] initWithWebState:webState - delegate:self]; + _formHelper = + [[PasswordFormHelper alloc] initWithWebState:webState delegate:self]; _passwordManagerClient = std::make_unique<WebViewPasswordManagerClient>(self); @@ -186,7 +186,7 @@ } - (const GURL&)lastCommittedURL { - return self.helper.lastCommittedURL; + return self.formHelper.lastCommittedURL; } - (void)showSavePasswordInfoBar: @@ -259,7 +259,7 @@ - (void)fillPasswordForm:(const autofill::PasswordFormFillData&)formData { // TODO(crbug.com/865114): Add suggestion related logic. - [self.helper fillPasswordForm:formData completionHandler:nil]; + [self.formHelper fillPasswordForm:formData completionHandler:nil]; } // Informs delegate that there are no saved credentials for the current page. @@ -267,11 +267,11 @@ // TODO(crbug.com/865114): Implement remaining logic. } -#pragma mark - PasswordControllerHelperDelegate +#pragma mark - PasswordFormHelperDelegate -- (void)helper:(PasswordControllerHelper*)helper - didSubmitForm:(const PasswordForm&)form - inMainFrame:(BOOL)inMainFrame { +- (void)formHelper:(PasswordFormHelper*)formHelper + didSubmitForm:(const PasswordForm&)form + inMainFrame:(BOOL)inMainFrame { if (inMainFrame) { self.passwordManager->OnPasswordFormSubmitted(self.passwordManagerDriver, form); @@ -314,8 +314,8 @@ // Read all password forms from the page and send them to the password // manager. __weak CWVPasswordController* weakSelf = self; - [self.helper findPasswordFormsWithCompletionHandler:^( - const std::vector<autofill::PasswordForm>& forms) { + [self.formHelper findPasswordFormsWithCompletionHandler:^( + const std::vector<autofill::PasswordForm>& forms) { [weakSelf didFinishPasswordFormExtraction:forms]; }]; }
diff --git a/ios/web_view/internal/sync/cwv_sync_controller.mm b/ios/web_view/internal/sync/cwv_sync_controller.mm index 1266bb85..a13c08e1 100644 --- a/ios/web_view/internal/sync/cwv_sync_controller.mm +++ b/ios/web_view/internal/sync/cwv_sync_controller.mm
@@ -219,7 +219,7 @@ ProfileOAuth2TokenServiceIOSDelegate* tokenDelegate = static_cast<ProfileOAuth2TokenServiceIOSDelegate*>( _tokenService->GetDelegate()); - tokenDelegate->LoadCredentials(authenticatedID); + tokenDelegate->ReloadCredentials(authenticatedID); } }
diff --git a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm index a392318..e4bada1 100644 --- a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm +++ b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
@@ -15,7 +15,9 @@ #include "components/signin/core/browser/fake_gaia_cookie_manager_service.h" #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" #include "components/signin/core/browser/fake_signin_manager.h" +#include "components/signin/core/browser/signin_error_controller.h" #include "components/signin/core/browser/test_signin_client.h" +#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h" #include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h" #include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h" #include "components/sync/driver/fake_sync_client.h" @@ -47,7 +49,15 @@ CWVSyncControllerTest() : browser_state_(/*off_the_record=*/false), signin_client_(browser_state_.GetPrefs()), - token_service_(browser_state_.GetPrefs()), + sigin_error_controller_( + SigninErrorController::AccountMode::ANY_ACCOUNT), + token_service_( + browser_state_.GetPrefs(), + std::make_unique<ProfileOAuth2TokenServiceIOSDelegate>( + &signin_client_, + std::make_unique<FakeProfileOAuth2TokenServiceIOSProvider>(), + &account_tracker_service_, + &sigin_error_controller_)), gaia_cookie_manager_service_(&token_service_, "cookie-source", &signin_client_), @@ -99,6 +109,9 @@ std::unique_ptr<browser_sync::ProfileSyncServiceMock> profile_sync_service_; AccountTrackerService account_tracker_service_; TestSigninClient signin_client_; + SigninErrorController sigin_error_controller_; + // FakeProfileOAuth2TokenServiceIOSProvider token_service_provider_; + // ProfileOAuth2TokenServiceIOSDelegate token_service_delegate_; FakeProfileOAuth2TokenService token_service_; FakeGaiaCookieManagerService gaia_cookie_manager_service_; FakeSigninManager signin_manager_;
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm index c4ead59..888b8b67 100644 --- a/ios/web_view/internal/web_view_web_main_parts.mm +++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -5,6 +5,8 @@ #import "ios/web_view/internal/web_view_web_main_parts.h" #include "base/base_paths.h" +#include "base/feature_list.h" +#include "base/logging.h" #include "base/path_service.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "ios/web_view/cwv_web_view_features.h" @@ -38,6 +40,15 @@ DCHECK(local_state); ApplicationContext::GetInstance()->PreCreateThreads(); + +#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine( + /*enable_features=*/"", + // TODO(crbug.com/873790): Figure out if USER_CONSENTS need to be enabled. + /*disable_features=*/"SyncUserConsentSeparateType"); + base::FeatureList::SetInstance(std::move(feature_list)); +#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) } void WebViewWebMainParts::PreMainMessageLoopRun() {
diff --git a/ios/web_view/public/cwv_sync_controller.h b/ios/web_view/public/cwv_sync_controller.h index cd342e3..815127b 100644 --- a/ios/web_view/public/cwv_sync_controller.h +++ b/ios/web_view/public/cwv_sync_controller.h
@@ -70,7 +70,7 @@ dataSource: (__weak id<CWVSyncControllerDataSource>)dataSource; -// Stops syncs and nils out |currentIdentity|. +// Stops syncs and nils out |currentIdentity|. This method is idempotent. - (void)stopSyncAndClearIdentity; // If |passphraseNeeded| is |YES|. Call this to unlock the sync data.
diff --git a/media/gpu/v4l2/tegra_v4l2_device.cc b/media/gpu/v4l2/tegra_v4l2_device.cc index c48988b..15dd086 100644 --- a/media/gpu/v4l2/tegra_v4l2_device.cc +++ b/media/gpu/v4l2/tegra_v4l2_device.cc
@@ -61,7 +61,25 @@ } int TegraV4L2Device::Ioctl(int flags, void* arg) { - return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); + int ret = HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); + if (ret) + return ret; + + // Workarounds for Tegra's broken closed-source V4L2 interface. + struct v4l2_format* format; + switch (flags) { + // VIDIOC_G_FMT returns 0 planes for multiplanar formats with 1 plane. + case static_cast<int>(VIDIOC_G_FMT): + format = static_cast<struct v4l2_format*>(arg); + if (V4L2_TYPE_IS_MULTIPLANAR(format->type) && + format->fmt.pix_mp.num_planes == 0) + format->fmt.pix_mp.num_planes = 1; + break; + default: + break; + } + + return 0; } bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) {
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc index 024570f..eb8411a 100644 --- a/media/gpu/v4l2/v4l2_device.cc +++ b/media/gpu/v4l2/v4l2_device.cc
@@ -38,6 +38,7 @@ static std::unique_ptr<V4L2Buffer> Create(scoped_refptr<V4L2Device> device, enum v4l2_buf_type type, enum v4l2_memory memory, + size_t planes_count, size_t buffer_id); ~V4L2Buffer(); @@ -48,6 +49,7 @@ V4L2Buffer(scoped_refptr<V4L2Device> device, enum v4l2_buf_type type, enum v4l2_memory memory, + size_t planes_count, size_t buffer_id); bool Query(); @@ -56,6 +58,9 @@ // V4L2 data as queried by QUERYBUF. struct v4l2_buffer v4l2_buffer_ = {}; + // WARNING: do not change this to a vector or something smaller than + // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond + // the number of allocated planes, resulting in memory corruption. struct v4l2_plane v4l2_planes_[VIDEO_MAX_PLANES] = {{}}; DISALLOW_COPY_AND_ASSIGN(V4L2Buffer); @@ -64,10 +69,11 @@ std::unique_ptr<V4L2Buffer> V4L2Buffer::Create(scoped_refptr<V4L2Device> device, enum v4l2_buf_type type, enum v4l2_memory memory, + size_t planes_count, size_t buffer_id) { // Not using std::make_unique because constructor is private. std::unique_ptr<V4L2Buffer> buffer( - new V4L2Buffer(device, type, memory, buffer_id)); + new V4L2Buffer(device, type, memory, planes_count, buffer_id)); if (!buffer->Query()) return nullptr; @@ -78,14 +84,19 @@ V4L2Buffer::V4L2Buffer(scoped_refptr<V4L2Device> device, enum v4l2_buf_type type, enum v4l2_memory memory, + size_t planes_count, size_t buffer_id) - : device_(device), plane_mappings_(VIDEO_MAX_PLANES) { + : device_(device) { DCHECK(V4L2_TYPE_IS_MULTIPLANAR(type)); + DCHECK_LE(planes_count, base::size(v4l2_planes_)); v4l2_buffer_.m.planes = v4l2_planes_; - v4l2_buffer_.length = VIDEO_MAX_PLANES; + // Just in case we got more planes than we want. + v4l2_buffer_.length = std::min(planes_count, base::size(v4l2_planes_)); v4l2_buffer_.index = buffer_id; v4l2_buffer_.type = type; v4l2_buffer_.memory = memory; + + plane_mappings_.resize(v4l2_buffer_.length); } V4L2Buffer::~V4L2Buffer() { @@ -103,7 +114,7 @@ return false; } - plane_mappings_.resize(v4l2_buffer_.length); + DCHECK(plane_mappings_.size() == v4l2_buffer_.length); return true; } @@ -154,6 +165,9 @@ // Data from the buffer, that users can query and/or write. struct v4l2_buffer v4l2_buffer_; + // WARNING: do not change this to a vector or something smaller than + // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond + // the number of allocated planes, resulting in memory corruption. struct v4l2_plane v4l2_planes_[VIDEO_MAX_PLANES]; private: @@ -170,7 +184,7 @@ scoped_refptr<V4L2Queue> queue) : queue_(std::move(queue)) { DCHECK(V4L2_TYPE_IS_MULTIPLANAR(v4l2_buffer->type)); - DCHECK_LE(v4l2_buffer->length, static_cast<uint32_t>(VIDEO_MAX_PLANES)); + DCHECK_LE(v4l2_buffer->length, base::size(v4l2_planes_)); memcpy(&v4l2_buffer_, v4l2_buffer, sizeof(v4l2_buffer_)); memcpy(v4l2_planes_, v4l2_buffer->m.planes, @@ -526,13 +540,26 @@ return 0; } + // First query the number of planes in the buffers we are about to request. + // This should not be required, but Tegra's VIDIOC_QUERYBUF will fail on + // output buffers if the number of specified planes does not exactly match the + // format. + struct v4l2_format format = {.type = type_}; + int ret = device_->Ioctl(VIDIOC_G_FMT, &format); + if (ret) { + VPLOGF(1) << "VIDIOC_G_FMT failed: "; + return 0; + } + planes_count_ = format.fmt.pix_mp.num_planes; + DCHECK_LE(planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES)); + struct v4l2_requestbuffers reqbufs = {}; reqbufs.count = count; reqbufs.type = type_; reqbufs.memory = memory; DVLOGF(3) << "queue " << type_ << ": requesting " << count << " buffers."; - int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); + ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); if (ret) { VPLOGF(1) << "VIDIOC_REQBUFS failed: "; return 0; @@ -543,7 +570,7 @@ // Now query all buffer information. for (size_t i = 0; i < reqbufs.count; i++) { - auto buffer = V4L2Buffer::Create(device_, type_, memory_, i); + auto buffer = V4L2Buffer::Create(device_, type_, memory_, planes_count_, i); if (!buffer) { DeallocateBuffers(); @@ -649,12 +676,14 @@ } struct v4l2_buffer v4l2_buffer = {}; + // WARNING: do not change this to a vector or something smaller than + // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond + // the number of allocated planes, resulting in memory corruption. struct v4l2_plane planes[VIDEO_MAX_PLANES] = {{}}; v4l2_buffer.type = type_; v4l2_buffer.memory = memory_; v4l2_buffer.m.planes = planes; - // TODO(acourbot): use actual number of planes. - v4l2_buffer.length = VIDEO_MAX_PLANES; + v4l2_buffer.length = planes_count_; int ret = device_->Ioctl(VIDIOC_DQBUF, &v4l2_buffer); if (ret) { // TODO(acourbot): we should not have to check for EPIPE as codec clients
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h index d17657c9..7134fe3a2 100644 --- a/media/gpu/v4l2/v4l2_device.h +++ b/media/gpu/v4l2/v4l2_device.h
@@ -251,6 +251,7 @@ const enum v4l2_buf_type type_; enum v4l2_memory memory_ = V4L2_MEMORY_MMAP; bool is_streaming_ = false; + size_t planes_count_ = 0; std::vector<std::unique_ptr<V4L2Buffer>> buffers_;
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc index cb6adb2..de3fab9 100644 --- a/media/gpu/video_encode_accelerator_unittest.cc +++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -70,8 +70,6 @@ namespace media { namespace { -const VideoPixelFormat kInputFormat = PIXEL_FORMAT_I420; - // The absolute differences between original frame and decoded frame usually // ranges aroud 1 ~ 7. So we pick 10 as an extreme value to detect abnormal // decoded frames. @@ -116,10 +114,10 @@ // The syntax of each test stream is: // "in_filename:width:height:profile:out_filename:requested_bitrate // :requested_framerate:requested_subsequent_bitrate -// :requested_subsequent_framerate" +// :requested_subsequent_framerate:pixel_format" // Instead of ":", "," can be used as a seperator as well. Note that ":" does // not work on Windows as it interferes with file paths. -// - |in_filename| must be an I420 (YUV planar) raw stream +// - |in_filename| is YUV raw stream. Its format must be |pixel_format| // (see http://www.fourcc.org/yuv.php#IYUV). // - |width| and |height| are in pixels. // - |profile| to encode into (values of VideoCodecProfile). @@ -132,12 +130,15 @@ // Further parameters are optional (need to provide preceding positional // parameters if a specific subsequent parameter is required): // - |requested_bitrate| requested bitrate in bits per second. +// Bitrate is only forced for tests that test bitrate. // - |requested_framerate| requested initial framerate. // - |requested_subsequent_bitrate| bitrate to switch to in the middle of the // stream. // - |requested_subsequent_framerate| framerate to switch to in the middle // of the stream. -// Bitrate is only forced for tests that test bitrate. +// - |pixel_format| is the VideoPixelFormat of |in_filename|. Users needs to +// set the value corresponding to the desired format. If it is not specified, +// this would be PIXEL_FORMAT_I420. #if defined(OS_CHROMEOS) || defined(OS_LINUX) const char* g_default_in_filename = "bear_320x192_40frames.yuv"; @@ -237,12 +238,12 @@ requested_subsequent_framerate(0) {} ~TestStream() {} + VideoPixelFormat pixel_format; gfx::Size visible_size; gfx::Size coded_size; unsigned int num_frames; - // Original unaligned input file name provided as an argument to the test. - // And the file must be an I420 (YUV planar) raw stream. + // Original unaligned YUV input file name provided as an argument to the test. std::string in_filename; // A vector used to prepare aligned input buffers of |in_filename|. This @@ -323,7 +324,9 @@ coded_size == test_stream->coded_size); test_stream->coded_size = coded_size; - size_t num_planes = VideoFrame::NumPlanes(kInputFormat); + ASSERT_NE(test_stream->pixel_format, PIXEL_FORMAT_UNKNOWN); + const VideoPixelFormat pixel_format = test_stream->pixel_format; + size_t num_planes = VideoFrame::NumPlanes(pixel_format); std::vector<size_t> padding_sizes(num_planes); std::vector<size_t> coded_bpl(num_planes); std::vector<size_t> visible_bpl(num_planes); @@ -338,18 +341,18 @@ // copied into a row of coded_bpl bytes in the aligned file. for (size_t i = 0; i < num_planes; i++) { const size_t size = - VideoFrame::PlaneSize(kInputFormat, i, coded_size).GetArea(); + VideoFrame::PlaneSize(pixel_format, i, coded_size).GetArea(); test_stream->aligned_plane_size.push_back( AlignToPlatformRequirements(size)); test_stream->aligned_buffer_size += test_stream->aligned_plane_size.back(); - coded_bpl[i] = VideoFrame::RowBytes(i, kInputFormat, coded_size.width()); - visible_bpl[i] = VideoFrame::RowBytes(i, kInputFormat, + coded_bpl[i] = VideoFrame::RowBytes(i, pixel_format, coded_size.width()); + visible_bpl[i] = VideoFrame::RowBytes(i, pixel_format, test_stream->visible_size.width()); visible_plane_rows[i] = - VideoFrame::Rows(i, kInputFormat, test_stream->visible_size.height()); + VideoFrame::Rows(i, pixel_format, test_stream->visible_size.height()); const size_t padding_rows = - VideoFrame::Rows(i, kInputFormat, coded_size.height()) - + VideoFrame::Rows(i, pixel_format, coded_size.height()) - visible_plane_rows[i]; padding_sizes[i] = padding_rows * coded_bpl[i] + AlignToPlatformRequirements(size) - size; @@ -360,7 +363,7 @@ LOG_ASSERT(base::GetFileSize(src_file, &src_file_size)); size_t visible_buffer_size = - VideoFrame::AllocationSize(kInputFormat, test_stream->visible_size); + VideoFrame::AllocationSize(pixel_format, test_stream->visible_size); LOG_ASSERT(src_file_size % visible_buffer_size == 0U) << "Stream byte size is not a product of calculated frame byte size"; @@ -421,7 +424,7 @@ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); } LOG_ASSERT(fields.size() >= 4U) << data; - LOG_ASSERT(fields.size() <= 9U) << data; + LOG_ASSERT(fields.size() <= 10U) << data; auto test_stream = std::make_unique<TestStream>(); test_stream->in_filename = FilePathStringTypeToString(fields[0]); @@ -438,6 +441,7 @@ LOG_ASSERT(profile > VIDEO_CODEC_PROFILE_UNKNOWN); LOG_ASSERT(profile <= VIDEO_CODEC_PROFILE_MAX); test_stream->requested_profile = static_cast<VideoCodecProfile>(profile); + test_stream->pixel_format = PIXEL_FORMAT_I420; if (fields.size() >= 5 && !fields[4].empty()) test_stream->out_filename = FilePathStringTypeToString(fields[4]); @@ -459,6 +463,12 @@ LOG_ASSERT(base::StringToUint( fields[8], &test_stream->requested_subsequent_framerate)); } + + if (fields.size() >= 10 && !fields[9].empty()) { + unsigned int format = 0; + LOG_ASSERT(base::StringToUint(fields[9], &format)); + test_stream->pixel_format = static_cast<VideoPixelFormat>(format); + } test_streams->push_back(std::move(test_stream)); } } @@ -748,6 +758,7 @@ : public base::SupportsWeakPtr<VideoFrameQualityValidator> { public: VideoFrameQualityValidator(const VideoCodecProfile profile, + const VideoPixelFormat pixel_format, bool verify_quality, const base::Closure& flush_complete_cb, const base::Closure& decode_error_cb); @@ -774,10 +785,11 @@ uint64_t mse[VideoFrame::kMaxPlanes]; }; - static FrameStats CompareFrames(const VideoFrame& original_frame, - const VideoFrame& output_frame); + FrameStats CompareFrames(const VideoFrame& original_frame, + const VideoFrame& output_frame); MediaLog media_log_; const VideoCodecProfile profile_; + const VideoPixelFormat pixel_format_; const bool verify_quality_; std::unique_ptr<FFmpegVideoDecoder> decoder_; VideoDecoder::DecodeCB decode_cb_; @@ -795,10 +807,12 @@ VideoFrameQualityValidator::VideoFrameQualityValidator( const VideoCodecProfile profile, + const VideoPixelFormat pixel_format, const bool verify_quality, const base::Closure& flush_complete_cb, const base::Closure& decode_error_cb) : profile_(profile), + pixel_format_(pixel_format), verify_quality_(verify_quality), decoder_(new FFmpegVideoDecoder(&media_log_)), decode_cb_(base::BindRepeating(&VideoFrameQualityValidator::DecodeDone, @@ -820,12 +834,12 @@ // The default output format of ffmpeg video decoder is YV12. VideoDecoderConfig config; if (IsVP8(profile_)) - config.Initialize(kCodecVP8, VP8PROFILE_ANY, kInputFormat, + config.Initialize(kCodecVP8, VP8PROFILE_ANY, pixel_format_, COLOR_SPACE_UNSPECIFIED, VIDEO_ROTATION_0, coded_size, visible_size, natural_size, EmptyExtraData(), Unencrypted()); else if (IsH264(profile_)) - config.Initialize(kCodecH264, H264PROFILE_MAIN, kInputFormat, + config.Initialize(kCodecH264, H264PROFILE_MAIN, pixel_format_, COLOR_SPACE_UNSPECIFIED, VIDEO_ROTATION_0, coded_size, visible_size, natural_size, EmptyExtraData(), Unencrypted()); @@ -1077,12 +1091,6 @@ VideoFrameQualityValidator::FrameStats VideoFrameQualityValidator::CompareFrames(const VideoFrame& original_frame, const VideoFrame& output_frame) { - // This code assumes I420/NV12 (e.g. 12bpp YUV planar) and needs to be updated - // to support anything else. - CHECK(original_frame.format() == PIXEL_FORMAT_I420 || - original_frame.format() == PIXEL_FORMAT_YV12); - CHECK(output_frame.format() == PIXEL_FORMAT_I420 || - output_frame.format() == PIXEL_FORMAT_YV12); CHECK(original_frame.visible_rect().size() == output_frame.visible_rect().size()); @@ -1096,8 +1104,8 @@ &frame_stats.ssim[plane], &frame_stats.mse[plane], original_frame.data(plane), original_frame.stride(plane), output_frame.data(plane), output_frame.stride(plane), - VideoFrame::Columns(plane, kInputFormat, frame_stats.width), - VideoFrame::Rows(plane, kInputFormat, frame_stats.height)); + VideoFrame::Columns(plane, pixel_format_, frame_stats.width), + VideoFrame::Rows(plane, pixel_format_, frame_stats.height)); } return frame_stats; } @@ -1125,9 +1133,9 @@ uint8_t* output_plane = output_frame->data(plane); size_t rows = - VideoFrame::Rows(plane, kInputFormat, visible_size.height()); + VideoFrame::Rows(plane, pixel_format_, visible_size.height()); size_t columns = - VideoFrame::Columns(plane, kInputFormat, visible_size.width()); + VideoFrame::Columns(plane, pixel_format_, visible_size.width()); size_t stride = original_frame->stride(plane); for (size_t i = 0; i < rows; i++) { @@ -1139,7 +1147,7 @@ } // Divide the difference by the size of frame. - difference /= VideoFrame::AllocationSize(kInputFormat, visible_size); + difference /= VideoFrame::AllocationSize(pixel_format_, visible_size); EXPECT_TRUE(difference <= kDecodeSimilarityThreshold) << "difference = " << difference << " > decode similarity threshold"; } @@ -1435,7 +1443,8 @@ // validating encoder quality. if (verify_output_ || !g_env->frame_stats_path().empty()) { quality_validator_.reset(new VideoFrameQualityValidator( - test_stream_->requested_profile, verify_output_, + test_stream_->requested_profile, test_stream_->pixel_format, + verify_output_, base::BindRepeating(&VEAClient::DecodeCompleted, base::Unretained(this)), base::BindRepeating(&VEAClient::DecodeFailed, @@ -1489,8 +1498,9 @@ << ", initial bitrate: " << requested_bitrate_; const VideoEncodeAccelerator::Config config( - kInputFormat, test_stream_->visible_size, test_stream_->requested_profile, - requested_bitrate_, requested_framerate_); + test_stream_->pixel_format, test_stream_->visible_size, + test_stream_->requested_profile, requested_bitrate_, + requested_framerate_); encoder_ = CreateVideoEncodeAccelerator(config, this, gpu::GpuPreferences()); if (!encoder_) { LOG(ERROR) << "Failed creating a VideoEncodeAccelerator."; @@ -1742,10 +1752,10 @@ CHECK_GT(current_framerate_, 0U); scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalYuvData( - kInputFormat, input_coded_size_, gfx::Rect(test_stream_->visible_size), - test_stream_->visible_size, input_coded_size_.width(), - input_coded_size_.width() / 2, input_coded_size_.width() / 2, - frame_data_y, frame_data_u, frame_data_v, + test_stream_->pixel_format, input_coded_size_, + gfx::Rect(test_stream_->visible_size), test_stream_->visible_size, + input_coded_size_.width(), input_coded_size_.width() / 2, + input_coded_size_.width() / 2, frame_data_y, frame_data_u, frame_data_v, // Timestamp needs to avoid starting from 0. base::TimeDelta().FromMilliseconds((next_input_id_ + 1) * base::Time::kMillisecondsPerSecond / @@ -2108,8 +2118,8 @@ gfx::Size visible_size(width_, height_); const VideoEncodeAccelerator::Config config( - kInputFormat, visible_size, g_env->test_streams_[0]->requested_profile, - bitrate_, fps_); + g_env->test_streams_[0]->pixel_format, visible_size, + g_env->test_streams_[0]->requested_profile, bitrate_, fps_); encoder_ = CreateVideoEncodeAccelerator(config, this, gpu::GpuPreferences()); if (!encoder_) { LOG(ERROR) << "Failed creating a VideoEncodeAccelerator."; @@ -2268,20 +2278,21 @@ if (!has_encoder()) return; + const VideoPixelFormat pixel_format = g_env->test_streams_[0]->pixel_format; std::vector<char, AlignedAllocator<char, kPlatformBufferAlignment>> aligned_data_y, aligned_data_u, aligned_data_v; aligned_data_y.resize( - VideoFrame::PlaneSize(kInputFormat, 0, input_coded_size).GetArea()); + VideoFrame::PlaneSize(pixel_format, 0, input_coded_size).GetArea()); aligned_data_u.resize( - VideoFrame::PlaneSize(kInputFormat, 1, input_coded_size).GetArea()); + VideoFrame::PlaneSize(pixel_format, 1, input_coded_size).GetArea()); aligned_data_v.resize( - VideoFrame::PlaneSize(kInputFormat, 2, input_coded_size).GetArea()); + VideoFrame::PlaneSize(pixel_format, 2, input_coded_size).GetArea()); uint8_t* frame_data_y = reinterpret_cast<uint8_t*>(&aligned_data_y[0]); uint8_t* frame_data_u = reinterpret_cast<uint8_t*>(&aligned_data_u[0]); uint8_t* frame_data_v = reinterpret_cast<uint8_t*>(&aligned_data_v[0]); scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalYuvData( - kInputFormat, input_coded_size, gfx::Rect(input_coded_size), + pixel_format, input_coded_size, gfx::Rect(input_coded_size), input_coded_size, input_coded_size.width(), input_coded_size.width() / 2, input_coded_size.width() / 2, frame_data_y, frame_data_u, frame_data_v, base::TimeDelta().FromMilliseconds(base::Time::kMillisecondsPerSecond /
diff --git a/media/test/data/README.md b/media/test/data/README.md index f1d3aa1a..fa2d147 100644 --- a/media/test/data/README.md +++ b/media/test/data/README.md
@@ -574,6 +574,18 @@ First 40 raw i420 frames of bear-1280x720.mp4 scaled down to 320x192 for video_encode_accelerator_unittest. +#### bear_320x192_40frames.nv12.yuv +First 40 raw nv12 frames of bear-1280x720.mp4 scaled down to 320x192 for +video_encode_accelerator_unittest. + +#### bear_320x192_40frames.nv21.yuv +First 40 raw nv21 frames of bear-1280x720.mp4 scaled down to 320x192 for +video_encode_accelerator_unittest. + +#### bear_320x192_40frames.yv12.yuv +First 40 raw yv12 frames of bear-1280x720.mp4 scaled down to 320x192 for +video_encode_accelerator_unittest. + ### VP9 parser test files: #### bear-vp9.ivf
diff --git a/media/test/data/bear_320x192_40frames.nv12.yuv b/media/test/data/bear_320x192_40frames.nv12.yuv new file mode 100644 index 0000000..3bff3a4d --- /dev/null +++ b/media/test/data/bear_320x192_40frames.nv12.yuv Binary files differ
diff --git a/media/test/data/bear_320x192_40frames.nv21.yuv b/media/test/data/bear_320x192_40frames.nv21.yuv new file mode 100644 index 0000000..9ef82dd --- /dev/null +++ b/media/test/data/bear_320x192_40frames.nv21.yuv Binary files differ
diff --git a/media/test/data/bear_320x192_40frames.yv12.yuv b/media/test/data/bear_320x192_40frames.yv12.yuv new file mode 100644 index 0000000..65eca63 --- /dev/null +++ b/media/test/data/bear_320x192_40frames.yv12.yuv Binary files differ
diff --git a/net/proxy_resolution/proxy_config_service_android.cc b/net/proxy_resolution/proxy_config_service_android.cc index 1661b2c..3dcbfab 100644 --- a/net/proxy_resolution/proxy_config_service_android.cc +++ b/net/proxy_resolution/proxy_config_service_android.cc
@@ -231,8 +231,8 @@ ProxyConfigWithAnnotation proxy_config; GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); network_task_runner_->PostTask( - FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, - proxy_config)); + FROM_HERE, base::BindOnce(&Delegate::SetNewConfigInNetworkSequence, + this, proxy_config)); } void Shutdown() { @@ -272,8 +272,8 @@ ProxyConfigWithAnnotation proxy_config; GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); network_task_runner_->PostTask( - FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, - proxy_config)); + FROM_HERE, base::BindOnce(&Delegate::SetNewConfigInNetworkSequence, + this, proxy_config)); } // Called in the JNI sequence. @@ -293,8 +293,8 @@ &proxy_config); } network_task_runner_->PostTask( - FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, - proxy_config)); + FROM_HERE, base::BindOnce(&Delegate::SetNewConfigInNetworkSequence, + this, proxy_config)); } void set_exclude_pac_url(bool enabled) { @@ -304,27 +304,34 @@ // Called in the JNI sequence. void SetProxyOverride(const std::string& host, int port, - const std::vector<std::string>& exclusion_list) { + const std::vector<std::string>& exclusion_list, + base::OnceClosure callback) { DCHECK(InJNISequence()); has_proxy_override_ = true; ProxyConfigWithAnnotation proxy_config; CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config); - network_task_runner_->PostTask( - FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, - proxy_config)); + network_task_runner_->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&Delegate::SetNewConfigInNetworkSequence, this, + proxy_config), + std::move(callback)); } // Called in the JNI sequence. - void ClearProxyOverride() { + void ClearProxyOverride(base::OnceClosure callback) { DCHECK(InJNISequence()); - if (!has_proxy_override_) + if (!has_proxy_override_) { + std::move(callback).Run(); return; + } ProxyConfigWithAnnotation proxy_config; GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); - network_task_runner_->PostTask( - FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, - proxy_config)); + network_task_runner_->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&Delegate::SetNewConfigInNetworkSequence, this, + proxy_config), + std::move(callback)); has_proxy_override_ = false; } @@ -453,12 +460,13 @@ void ProxyConfigServiceAndroid::SetProxyOverride( const std::string& host, int port, - const std::vector<std::string>& exclusion_list) { - delegate_->SetProxyOverride(host, port, exclusion_list); + const std::vector<std::string>& exclusion_list, + base::OnceClosure callback) { + delegate_->SetProxyOverride(host, port, exclusion_list, std::move(callback)); } -void ProxyConfigServiceAndroid::ClearProxyOverride() { - delegate_->ClearProxyOverride(); +void ProxyConfigServiceAndroid::ClearProxyOverride(base::OnceClosure callback) { + delegate_->ClearProxyOverride(std::move(callback)); } } // namespace net
diff --git a/net/proxy_resolution/proxy_config_service_android.h b/net/proxy_resolution/proxy_config_service_android.h index ed70a5df..55394552 100644 --- a/net/proxy_resolution/proxy_config_service_android.h +++ b/net/proxy_resolution/proxy_config_service_android.h
@@ -78,8 +78,9 @@ void SetProxyOverride(const std::string& host, int port, - const std::vector<std::string>& exclusion_list); - void ClearProxyOverride(); + const std::vector<std::string>& exclusion_list, + base::OnceClosure callback); + void ClearProxyOverride(base::OnceClosure callback); private: friend class ProxyConfigServiceAndroidTestBase;
diff --git a/net/proxy_resolution/proxy_config_service_android_unittest.cc b/net/proxy_resolution/proxy_config_service_android_unittest.cc index 8c89180..61ece7dd 100644 --- a/net/proxy_resolution/proxy_config_service_android_unittest.cc +++ b/net/proxy_resolution/proxy_config_service_android_unittest.cc
@@ -112,13 +112,14 @@ void SetProxyOverride(const std::string& host, int port, - const std::vector<std::string>& exclusion_list) { - service_.SetProxyOverride(host, port, exclusion_list); + const std::vector<std::string>& exclusion_list, + base::OnceClosure callback) { + service_.SetProxyOverride(host, port, exclusion_list, std::move(callback)); base::RunLoop().RunUntilIdle(); } - void ClearProxyOverride() { - service_.ClearProxyOverride(); + void ClearProxyOverride(base::OnceClosure callback) { + service_.ClearProxyOverride(std::move(callback)); base::RunLoop().RunUntilIdle(); } @@ -178,6 +179,26 @@ TestMapping("http://example.com/", "PROXY httpproxy.com:80"); } +struct ProxyCallback { + ProxyCallback() + : called(false), + callback(base::BindOnce(&ProxyCallback::Call, base::Unretained(this))) { + } + + void Call() { called = true; } + + bool called; + base::OnceClosure callback; +}; + +TEST_F(ProxyConfigServiceAndroidTest, TestProxyOverrideCallback) { + ProxyCallback proxyCallback; + ASSERT_FALSE(proxyCallback.called); + ClearProxyOverride(std::move(proxyCallback.callback)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(proxyCallback.called); +} + TEST_F(ProxyConfigServiceAndroidTest, TestOverrideNoProxy) { std::vector<std::string> exclusion_list; @@ -185,11 +206,12 @@ TestMapping("http://example.com/", "DIRECT"); // Check that webview uses the custom proxy - SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list, + base::DoNothing()); TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); // Check that webview uses the default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://example.com/", "DIRECT"); } @@ -200,7 +222,8 @@ TestMapping("http://example.com/", "DIRECT"); // Check that webview uses the custom proxy - SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list, + base::DoNothing()); TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); // Check that webview continues to use the custom proxy @@ -209,7 +232,7 @@ TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); // Check that webview uses the non default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); } @@ -225,11 +248,12 @@ TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); // Check that webview uses the custom proxy - SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list, + base::DoNothing()); TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); // Check that webview uses the non default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); } @@ -240,11 +264,12 @@ TestMapping("http://example.com/", "DIRECT"); // Check that webview uses the custom proxy - SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list, + base::DoNothing()); TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); // Check that webview uses the default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://example.com/", "DIRECT"); // Check that webview uses the non default proxy @@ -260,7 +285,7 @@ TestMapping("http://example.com/", "DIRECT"); // Check that webview uses the default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://example.com/", "DIRECT"); } @@ -273,7 +298,7 @@ TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); // Check that webview uses the non default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); } @@ -286,12 +311,13 @@ TestMapping("http://example.com/", "DIRECT"); // Check that webview handles the exclusion list correctly - SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list, + base::DoNothing()); TestMapping("http://excluded.com/", "DIRECT"); TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); // Check that webview uses the default proxy - ClearProxyOverride(); + ClearProxyOverride(base::DoNothing()); TestMapping("http://excluded.com/", "DIRECT"); TestMapping("http://example.com/", "DIRECT"); }
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index f0eb6249..1dc14e465 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1030,7 +1030,7 @@ } } -bool QuicChromiumClientSession::ShouldCreateOutgoingDynamicStream() { +bool QuicChromiumClientSession::ShouldCreateOutgoingStream() { if (!crypto_stream_->encryption_established()) { DVLOG(1) << "Encryption not active so no outgoing stream created."; return false; @@ -1213,10 +1213,10 @@ hostname); } -bool QuicChromiumClientSession::ShouldCreateIncomingDynamicStream( +bool QuicChromiumClientSession::ShouldCreateIncomingStream( quic::QuicStreamId id) { if (!connection()->connected()) { - LOG(DFATAL) << "ShouldCreateIncomingDynamicStream called when disconnected"; + LOG(DFATAL) << "ShouldCreateIncomingStream called when disconnected"; return false; } if (goaway_received()) { @@ -1237,9 +1237,9 @@ return true; } -QuicChromiumClientStream* -QuicChromiumClientSession::CreateIncomingDynamicStream(quic::QuicStreamId id) { - if (!ShouldCreateIncomingDynamicStream(id)) { +QuicChromiumClientStream* QuicChromiumClientSession::CreateIncomingStream( + quic::QuicStreamId id) { + if (!ShouldCreateIncomingStream(id)) { return nullptr; } net::NetworkTrafficAnnotationTag traffic_annotation =
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index dfcc477..d6591b0 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -644,10 +644,10 @@ protected: // quic::QuicSession methods: - bool ShouldCreateIncomingDynamicStream(quic::QuicStreamId id) override; - bool ShouldCreateOutgoingDynamicStream() override; + bool ShouldCreateIncomingStream(quic::QuicStreamId id) override; + bool ShouldCreateOutgoingStream() override; - QuicChromiumClientStream* CreateIncomingDynamicStream( + QuicChromiumClientStream* CreateIncomingStream( quic::QuicStreamId id) override; private:
diff --git a/net/quic/quic_chromium_client_session_peer.cc b/net/quic/quic_chromium_client_session_peer.cc index d6e4fb81..b37a2f4 100644 --- a/net/quic/quic_chromium_client_session_peer.cc +++ b/net/quic/quic_chromium_client_session_peer.cc
@@ -32,10 +32,9 @@ } // static -QuicChromiumClientStream* -QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( +QuicChromiumClientStream* QuicChromiumClientSessionPeer::CreateOutgoingStream( QuicChromiumClientSession* session) { - return session->ShouldCreateOutgoingDynamicStream() + return session->ShouldCreateOutgoingStream() ? session->CreateOutgoingReliableStreamImpl( TRAFFIC_ANNOTATION_FOR_TESTS) : nullptr;
diff --git a/net/quic/quic_chromium_client_session_peer.h b/net/quic/quic_chromium_client_session_peer.h index 8bdf717..23cdd51 100644 --- a/net/quic/quic_chromium_client_session_peer.h +++ b/net/quic/quic_chromium_client_session_peer.h
@@ -29,7 +29,7 @@ static uint64_t GetPushedAndUnclaimedBytesCount( QuicChromiumClientSession* session); - static QuicChromiumClientStream* CreateOutgoingDynamicStream( + static QuicChromiumClientStream* CreateOutgoingStream( QuicChromiumClientSession* session); private:
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index 4c46ee0..030ab19 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc
@@ -510,7 +510,7 @@ // can not proceed immediately. const size_t kMaxOpenStreams = session_->max_open_outgoing_streams(); for (size_t i = 0; i < kMaxOpenStreams; i++) { - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream(session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); @@ -552,7 +552,7 @@ // can not proceed immediately. const size_t kMaxOpenStreams = session_->max_open_outgoing_streams(); for (size_t i = 0; i < kMaxOpenStreams; i++) { - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream(session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); @@ -605,7 +605,7 @@ // can not proceed immediately. const size_t kMaxOpenStreams = session_->max_open_outgoing_streams(); for (size_t i = 0; i < kMaxOpenStreams; i++) { - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream(session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); @@ -711,7 +711,7 @@ // can not proceed immediately. const size_t kMaxOpenStreams = session_->max_open_outgoing_streams(); for (size_t i = 0; i < kMaxOpenStreams; i++) { - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream(session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); } EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); @@ -754,13 +754,12 @@ std::vector<QuicChromiumClientStream*> streams; for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); streams.push_back(stream); } - EXPECT_FALSE(QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get())); + EXPECT_FALSE( + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get())); EXPECT_EQ(kMaxOpenStreams, session_->GetNumOpenOutgoingStreams()); @@ -768,14 +767,14 @@ quic::QuicStreamId stream_id = streams[0]->id(); session_->CloseStream(stream_id); - EXPECT_FALSE(QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get())); + EXPECT_FALSE( + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get())); quic::QuicRstStreamFrame rst1(quic::kInvalidControlFrameId, stream_id, quic::QUIC_STREAM_NO_ERROR, 0); session_->OnRstStream(rst1); EXPECT_EQ(kMaxOpenStreams - 1, session_->GetNumOpenOutgoingStreams()); - EXPECT_TRUE(QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get())); + EXPECT_TRUE( + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get())); } TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutNoResponse) { @@ -801,8 +800,7 @@ session_->OnProofVerifyDetailsAvailable(details); QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); spdy::SpdyHeaderBlock promise_headers; @@ -852,8 +850,7 @@ session_->OnProofVerifyDetailsAvailable(details); QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); spdy::SpdyHeaderBlock promise_headers; @@ -908,8 +905,7 @@ session_->OnProofVerifyDetailsAvailable(details); QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); spdy::SpdyHeaderBlock promise_headers; @@ -963,8 +959,7 @@ session_->OnProofVerifyDetailsAvailable(details); QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); spdy::SpdyHeaderBlock promise_headers; @@ -1014,8 +1009,7 @@ session_->OnProofVerifyDetailsAvailable(details); QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); spdy::SpdyHeaderBlock promise_headers; @@ -1068,8 +1062,7 @@ std::vector<QuicChromiumClientStream*> streams; for (size_t i = 0; i < kMaxOpenStreams; i++) { QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); EXPECT_TRUE(stream); streams.push_back(stream); } @@ -1108,7 +1101,7 @@ session_->connection()->OnGoAwayFrame( quic::QuicGoAwayFrame(quic::kInvalidControlFrameId, quic::QUIC_PEER_GOING_AWAY, 1u, "Going away.")); - EXPECT_EQ(nullptr, QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( + EXPECT_EQ(nullptr, QuicChromiumClientSessionPeer::CreateOutgoingStream( session_.get())); } @@ -1303,8 +1296,7 @@ // Write data to session. QuicChromiumClientStream* stream = - QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get()); + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get()); struct iovec iov[1]; iov[0].iov_base = data; iov[0].iov_len = 4; @@ -1519,8 +1511,8 @@ // Open a stream since the connection only sends PINGs to keep a // retransmittable packet on the wire if there's an open stream. - EXPECT_TRUE(QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream( - session_.get())); + EXPECT_TRUE( + QuicChromiumClientSessionPeer::CreateOutgoingStream(session_.get())); quic::QuicAlarm* alarm = quic::test::QuicConnectionPeer::GetRetransmittableOnWireAlarm(
diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc index 99924ba..869042c 100644 --- a/net/quic/quic_chromium_client_stream_test.cc +++ b/net/quic/quic_chromium_client_stream_test.cc
@@ -60,7 +60,7 @@ void(quic::QuicErrorCode error, const std::string& error_details, quic::ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, + MOCK_METHOD1(CreateIncomingStream, quic::QuicSpdyStream*(quic::QuicStreamId id)); MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicChromiumClientStream*()); MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicChromiumClientStream*()); @@ -129,8 +129,8 @@ bool IsAuthorized(const std::string& hostname) override { return true; } protected: - MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(quic::QuicStreamId id)); - MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool()); + MOCK_METHOD1(ShouldCreateIncomingStream, bool(quic::QuicStreamId id)); + MOCK_METHOD0(ShouldCreateOutgoingStream, bool()); private: std::unique_ptr<quic::QuicCryptoStream> crypto_stream_;
diff --git a/net/third_party/quic/core/http/quic_server_session_base.cc b/net/third_party/quic/core/http/quic_server_session_base.cc index 1326676..fd73f2c7 100644 --- a/net/third_party/quic/core/http/quic_server_session_base.cc +++ b/net/third_party/quic/core/http/quic_server_session_base.cc
@@ -192,9 +192,9 @@ connection()->sent_packet_manager().GetLargestSentPacket(); } -bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) { +bool QuicServerSessionBase::ShouldCreateIncomingStream(QuicStreamId id) { if (!connection()->connected()) { - QUIC_BUG << "ShouldCreateIncomingDynamicStream called when disconnected"; + QUIC_BUG << "ShouldCreateIncomingStream called when disconnected"; return false; } @@ -208,9 +208,9 @@ return true; } -bool QuicServerSessionBase::ShouldCreateOutgoingDynamicStream() { +bool QuicServerSessionBase::ShouldCreateOutgoingStream() { if (!connection()->connected()) { - QUIC_BUG << "ShouldCreateOutgoingDynamicStream called when disconnected"; + QUIC_BUG << "ShouldCreateOutgoingStream called when disconnected"; return false; } if (!crypto_stream_->encryption_established()) {
diff --git a/net/third_party/quic/core/http/quic_server_session_base.h b/net/third_party/quic/core/http/quic_server_session_base.h index 1ff4691..67f39b0 100644 --- a/net/third_party/quic/core/http/quic_server_session_base.h +++ b/net/third_party/quic/core/http/quic_server_session_base.h
@@ -79,12 +79,12 @@ // Return false when connection is closed or forward secure encryption hasn't // established yet or number of server initiated streams already reaches the // upper limit. - bool ShouldCreateOutgoingDynamicStream() override; + bool ShouldCreateOutgoingStream() override; // If we should create an incoming stream, returns true. Otherwise // does error handling, including communicating the error to the client and // possibly closing the connection, and returns false. - bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override; + bool ShouldCreateIncomingStream(QuicStreamId id) override; virtual QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( const QuicCryptoServerConfig* crypto_config,
diff --git a/net/third_party/quic/core/http/quic_server_session_base_test.cc b/net/third_party/quic/core/http/quic_server_session_base_test.cc index 01d134c..f6816a46 100644 --- a/net/third_party/quic/core/http/quic_server_session_base_test.cc +++ b/net/third_party/quic/core/http/quic_server_session_base_test.cc
@@ -63,8 +63,8 @@ ~TestServerSession() override { delete connection(); }; protected: - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override { - if (!ShouldCreateIncomingDynamicStream(id)) { + QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override { + if (!ShouldCreateIncomingStream(id)) { return nullptr; } QuicSpdyStream* stream = new QuicSimpleServerStream( @@ -79,7 +79,7 @@ } QuicSpdyStream* CreateOutgoingUnidirectionalStream() override { - if (!ShouldCreateOutgoingDynamicStream()) { + if (!ShouldCreateOutgoingStream()) { return nullptr; } @@ -355,7 +355,7 @@ QuicConnectionPeer::TearDownLocalConnectionState(connection_); EXPECT_QUIC_BUG(QuicServerSessionBasePeer::GetOrCreateDynamicStream( session_.get(), GetNthClientInitiatedId(0)), - "ShouldCreateIncomingDynamicStream called when disconnected"); + "ShouldCreateIncomingStream called when disconnected"); } class MockQuicCryptoServerStream : public QuicCryptoServerStream {
diff --git a/net/third_party/quic/core/http/quic_spdy_client_session.cc b/net/third_party/quic/core/http/quic_spdy_client_session.cc index 24ff19b6..b756662 100644 --- a/net/third_party/quic/core/http/quic_spdy_client_session.cc +++ b/net/third_party/quic/core/http/quic_spdy_client_session.cc
@@ -41,7 +41,7 @@ void QuicSpdyClientSession::OnProofVerifyDetailsAvailable( const ProofVerifyDetails& /*verify_details*/) {} -bool QuicSpdyClientSession::ShouldCreateOutgoingDynamicStream() { +bool QuicSpdyClientSession::ShouldCreateOutgoingStream() { if (!crypto_stream_->encryption_established()) { QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created."; return false; @@ -70,7 +70,7 @@ QuicSpdyClientStream* QuicSpdyClientSession::CreateOutgoingBidirectionalStream() { - if (!ShouldCreateOutgoingDynamicStream()) { + if (!ShouldCreateOutgoingStream()) { return nullptr; } std::unique_ptr<QuicSpdyClientStream> stream = CreateClientStream(); @@ -113,9 +113,9 @@ return crypto_stream_->num_scup_messages_received(); } -bool QuicSpdyClientSession::ShouldCreateIncomingDynamicStream(QuicStreamId id) { +bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) { if (!connection()->connected()) { - QUIC_BUG << "ShouldCreateIncomingDynamicStream called when disconnected"; + QUIC_BUG << "ShouldCreateIncomingStream called when disconnected"; return false; } if (goaway_received() && respect_goaway_) { @@ -133,9 +133,8 @@ return true; } -QuicSpdyStream* QuicSpdyClientSession::CreateIncomingDynamicStream( - QuicStreamId id) { - if (!ShouldCreateIncomingDynamicStream(id)) { +QuicSpdyStream* QuicSpdyClientSession::CreateIncomingStream(QuicStreamId id) { + if (!ShouldCreateIncomingStream(id)) { return nullptr; } QuicSpdyStream* stream =
diff --git a/net/third_party/quic/core/http/quic_spdy_client_session.h b/net/third_party/quic/core/http/quic_spdy_client_session.h index 9e1bc11..a3ca1669 100644 --- a/net/third_party/quic/core/http/quic_spdy_client_session.h +++ b/net/third_party/quic/core/http/quic_spdy_client_session.h
@@ -65,12 +65,12 @@ protected: // QuicSession methods: - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override; + QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override; // If an outgoing stream can be created, return true. - bool ShouldCreateOutgoingDynamicStream() override; + bool ShouldCreateOutgoingStream() override; // If an incoming stream can be created, return true. - bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override; + bool ShouldCreateIncomingStream(QuicStreamId id) override; // Create the crypto stream. Called by Initialize(). virtual std::unique_ptr<QuicCryptoClientStreamBase> CreateQuicCryptoStream();
diff --git a/net/third_party/quic/core/http/quic_spdy_client_session_test.cc b/net/third_party/quic/core/http/quic_spdy_client_session_test.cc index a9058c2..dcb4567 100644 --- a/net/third_party/quic/core/http/quic_spdy_client_session_test.cc +++ b/net/third_party/quic/core/http/quic_spdy_client_session_test.cc
@@ -58,8 +58,7 @@ this, BIDIRECTIONAL); } - MockQuicSpdyClientStream* CreateIncomingDynamicStream( - QuicStreamId id) override { + MockQuicSpdyClientStream* CreateIncomingStream(QuicStreamId id) override { MockQuicSpdyClientStream* stream = new MockQuicSpdyClientStream(id, this, READ_UNIDIRECTIONAL); ActivateStream(QuicWrapUnique(stream));
diff --git a/net/third_party/quic/core/http/quic_spdy_session.h b/net/third_party/quic/core/http/quic_spdy_session.h index 937a765..1bea32e9 100644 --- a/net/third_party/quic/core/http/quic_spdy_session.h +++ b/net/third_party/quic/core/http/quic_spdy_session.h
@@ -135,21 +135,20 @@ } protected: - // Override CreateIncomingDynamicStream(), - // CreateOutgoingBidirectionalStream() and + // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to // make sure that all data streams are QuicSpdyStreams. - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override = 0; + QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0; QuicSpdyStream* CreateOutgoingBidirectionalStream() override = 0; QuicSpdyStream* CreateOutgoingUnidirectionalStream() override = 0; QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id); // If an incoming stream can be created, return true. - virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id) = 0; + virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0; // If an outgoing stream can be created, return true. - virtual bool ShouldCreateOutgoingDynamicStream() = 0; + virtual bool ShouldCreateOutgoingStream() = 0; // This was formerly QuicHeadersStream::WriteHeaders. Needs to be // separate from QuicSpdySession::WriteHeaders because tests call
diff --git a/net/third_party/quic/core/http/quic_spdy_session_test.cc b/net/third_party/quic/core/http/quic_spdy_session_test.cc index c1f9400c..206b47397 100644 --- a/net/third_party/quic/core/http/quic_spdy_session_test.cc +++ b/net/third_party/quic/core/http/quic_spdy_session_test.cc
@@ -168,7 +168,7 @@ return stream; } - TestStream* CreateIncomingDynamicStream(QuicStreamId id) override { + TestStream* CreateIncomingStream(QuicStreamId id) override { // Enforce the limit on the number of open streams. if (GetNumOpenIncomingStreams() + 1 > max_open_incoming_streams()) { connection()->CloseConnection( @@ -182,11 +182,9 @@ } } - bool ShouldCreateIncomingDynamicStream(QuicStreamId /*id*/) override { - return true; - } + bool ShouldCreateIncomingStream(QuicStreamId /*id*/) override { return true; } - bool ShouldCreateOutgoingDynamicStream() override { return true; } + bool ShouldCreateOutgoingStream() override { return true; } bool IsClosedStream(QuicStreamId id) { return QuicSession::IsClosedStream(id); @@ -1605,7 +1603,7 @@ TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) { QuicStreamId stream_id = GetNthClientInitiatedId(0); - TestStream* stream = session_.CreateIncomingDynamicStream(stream_id); + TestStream* stream = session_.CreateIncomingStream(stream_id); session_.OnPriorityFrame(stream_id, kV3HighestPriority); EXPECT_EQ(kV3HighestPriority, stream->priority()); }
diff --git a/net/third_party/quic/core/quic_dispatcher_test.cc b/net/third_party/quic/core/quic_dispatcher_test.cc index ee06318..8c5ab72 100644 --- a/net/third_party/quic/core/quic_dispatcher_test.cc +++ b/net/third_party/quic/core/quic_dispatcher_test.cc
@@ -75,7 +75,7 @@ void(QuicErrorCode error, const QuicString& error_details, ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); + MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*()); MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
diff --git a/net/third_party/quic/core/quic_session.cc b/net/third_party/quic/core/quic_session.cc index 69587ef3..e4d7450 100644 --- a/net/third_party/quic/core/quic_session.cc +++ b/net/third_party/quic/core/quic_session.cc
@@ -931,7 +931,7 @@ return nullptr; } - return CreateIncomingDynamicStream(stream_id); + return CreateIncomingStream(stream_id); } void QuicSession::set_max_open_incoming_streams(
diff --git a/net/third_party/quic/core/quic_session.h b/net/third_party/quic/core/quic_session.h index b4d757d..da9bd76 100644 --- a/net/third_party/quic/core/quic_session.h +++ b/net/third_party/quic/core/quic_session.h
@@ -356,7 +356,7 @@ // Creates a new stream to handle a peer-initiated stream. // Caller does not own the returned stream. // Returns nullptr and does error handling if the stream can not be created. - virtual QuicStream* CreateIncomingDynamicStream(QuicStreamId id) = 0; + virtual QuicStream* CreateIncomingStream(QuicStreamId id) = 0; // Create a new stream to handle a locally-initiated bidirectional stream. // Caller does not own the returned stream.
diff --git a/net/third_party/quic/core/quic_session_test.cc b/net/third_party/quic/core/quic_session_test.cc index d3b255c..d0d61f7 100644 --- a/net/third_party/quic/core/quic_session_test.cc +++ b/net/third_party/quic/core/quic_session_test.cc
@@ -158,7 +158,7 @@ return stream; } - TestStream* CreateIncomingDynamicStream(QuicStreamId id) override { + TestStream* CreateIncomingStream(QuicStreamId id) override { // Enforce the limit on the number of open streams. if (GetNumOpenIncomingStreams() + 1 > max_open_incoming_streams()) { connection()->CloseConnection(
diff --git a/net/third_party/quic/quartc/quartc_session.cc b/net/third_party/quic/quartc/quartc_session.cc index 93de609..c08e0c9 100644 --- a/net/third_party/quic/quartc/quartc_session.cc +++ b/net/third_party/quic/quartc/quartc_session.cc
@@ -309,7 +309,7 @@ // TODO(zhihuang): Handle the proof verification. } -QuicStream* QuartcSession::CreateIncomingDynamicStream(QuicStreamId id) { +QuicStream* QuartcSession::CreateIncomingStream(QuicStreamId id) { return ActivateDataStream(CreateDataStream(id, QuicStream::kDefaultPriority)); }
diff --git a/net/third_party/quic/quartc/quartc_session.h b/net/third_party/quic/quartc/quartc_session.h index d0dd8af..742d9da 100644 --- a/net/third_party/quic/quartc/quartc_session.h +++ b/net/third_party/quic/quartc/quartc_session.h
@@ -137,7 +137,7 @@ protected: // QuicSession override. - QuicStream* CreateIncomingDynamicStream(QuicStreamId id) override; + QuicStream* CreateIncomingStream(QuicStreamId id) override; std::unique_ptr<QuartcStream> CreateDataStream(QuicStreamId id, spdy::SpdyPriority priority);
diff --git a/net/third_party/quic/quartc/quartc_stream_test.cc b/net/third_party/quic/quartc/quartc_stream_test.cc index cc8858a..f2ff1c4 100644 --- a/net/third_party/quic/quartc/quartc_stream_test.cc +++ b/net/third_party/quic/quartc/quartc_stream_test.cc
@@ -58,7 +58,7 @@ return QuicConsumedData(write_length, state != StreamSendingState::NO_FIN); } - QuartcStream* CreateIncomingDynamicStream(QuicStreamId id) override { + QuartcStream* CreateIncomingStream(QuicStreamId id) override { return nullptr; }
diff --git a/net/third_party/quic/test_tools/quic_test_server.cc b/net/third_party/quic/test_tools/quic_test_server.cc index edcef09..6bbfe0b 100644 --- a/net/third_party/quic/test_tools/quic_test_server.cc +++ b/net/third_party/quic/test_tools/quic_test_server.cc
@@ -37,8 +37,8 @@ stream_factory_(stream_factory), crypto_stream_factory_(crypto_stream_factory) {} - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override { - if (!ShouldCreateIncomingDynamicStream(id)) { + QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override { + if (!ShouldCreateIncomingStream(id)) { return nullptr; } if (stream_factory_) { @@ -47,7 +47,7 @@ ActivateStream(QuicWrapUnique(stream)); return stream; } - return QuicSimpleServerSession::CreateIncomingDynamicStream(id); + return QuicSimpleServerSession::CreateIncomingStream(id); } QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h index 78273700..30a2d6c6 100644 --- a/net/third_party/quic/test_tools/quic_test_utils.h +++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -557,11 +557,11 @@ void(QuicErrorCode error, const QuicString& error_details, ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, QuicStream*(QuicStreamId id)); + MOCK_METHOD1(CreateIncomingStream, QuicStream*(QuicStreamId id)); MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicStream*()); MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicStream*()); - MOCK_METHOD1(ShouldCreateIncomingDynamicStream2, bool(QuicStreamId id)); - MOCK_METHOD0(ShouldCreateOutgoingDynamicStream2, bool()); + MOCK_METHOD1(ShouldCreateIncomingStream2, bool(QuicStreamId id)); + MOCK_METHOD0(ShouldCreateOutgoingStream2, bool()); MOCK_METHOD5(WritevData, QuicConsumedData(QuicStream* stream, QuicStreamId id, @@ -635,11 +635,11 @@ void(QuicErrorCode error, const QuicString& error_details, ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); + MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*()); MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*()); - MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id)); - MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool()); + MOCK_METHOD1(ShouldCreateIncomingStream, bool(QuicStreamId id)); + MOCK_METHOD0(ShouldCreateOutgoingStream, bool()); MOCK_METHOD5(WritevData, QuicConsumedData(QuicStream* stream, QuicStreamId id, @@ -718,7 +718,7 @@ delete; ~TestQuicSpdyServerSession() override; - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); + MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*()); MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*()); QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( @@ -781,11 +781,11 @@ void(const ProofVerifyDetails& verify_details)); // TestQuicSpdyClientSession - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); + MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*()); MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*()); - MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id)); - MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool()); + MOCK_METHOD1(ShouldCreateIncomingStream, bool(QuicStreamId id)); + MOCK_METHOD0(ShouldCreateOutgoingStream, bool()); // Override to not send max header list size. void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
diff --git a/net/third_party/quic/tools/quic_simple_server_session.cc b/net/third_party/quic/tools/quic_simple_server_session.cc index 64d081f..2288691 100644 --- a/net/third_party/quic/tools/quic_simple_server_session.cc +++ b/net/third_party/quic/tools/quic_simple_server_session.cc
@@ -86,9 +86,8 @@ HandlePromisedPushRequests(); } -QuicSpdyStream* QuicSimpleServerSession::CreateIncomingDynamicStream( - QuicStreamId id) { - if (!ShouldCreateIncomingDynamicStream(id)) { +QuicSpdyStream* QuicSimpleServerSession::CreateIncomingStream(QuicStreamId id) { + if (!ShouldCreateIncomingStream(id)) { return nullptr; } @@ -106,7 +105,7 @@ QuicSimpleServerStream* QuicSimpleServerSession::CreateOutgoingUnidirectionalStream() { - if (!ShouldCreateOutgoingDynamicStream()) { + if (!ShouldCreateOutgoingStream()) { return nullptr; } @@ -187,7 +186,7 @@ } void QuicSimpleServerSession::HandlePromisedPushRequests() { - while (!promised_streams_.empty() && ShouldCreateOutgoingDynamicStream()) { + while (!promised_streams_.empty() && ShouldCreateOutgoingStream()) { PromisedStreamInfo& promised_info = promised_streams_.front(); DCHECK_EQ(next_outgoing_stream_id(), promised_info.stream_id);
diff --git a/net/third_party/quic/tools/quic_simple_server_session.h b/net/third_party/quic/tools/quic_simple_server_session.h index bc105b9..6e5160a 100644 --- a/net/third_party/quic/tools/quic_simple_server_session.h +++ b/net/third_party/quic/tools/quic_simple_server_session.h
@@ -85,7 +85,7 @@ protected: // QuicSession methods: - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override; + QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override; QuicSimpleServerStream* CreateOutgoingBidirectionalStream() override; QuicSimpleServerStream* CreateOutgoingUnidirectionalStream() override; // Closing an outgoing stream can reduce open outgoing stream count, try
diff --git a/net/third_party/quic/tools/quic_simple_server_session_test.cc b/net/third_party/quic/tools/quic_simple_server_session_test.cc index 4f555619..e24d917 100644 --- a/net/third_party/quic/tools/quic_simple_server_session_test.cc +++ b/net/third_party/quic/tools/quic_simple_server_session_test.cc
@@ -58,9 +58,9 @@ s->RegisterStaticStream(kCryptoStreamId, crypto_stream); } - static QuicSpdyStream* CreateIncomingDynamicStream(QuicSimpleServerSession* s, - QuicStreamId id) { - return s->CreateIncomingDynamicStream(id); + static QuicSpdyStream* CreateIncomingStream(QuicSimpleServerSession* s, + QuicStreamId id) { + return s->CreateIncomingStream(id); } static QuicSimpleServerStream* CreateOutgoingUnidirectionalStream( @@ -326,7 +326,7 @@ EXPECT_TRUE(connection_->connected()); } -TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStreamDisconnected) { +TEST_P(QuicSimpleServerSessionTest, CreateIncomingStreamDisconnected) { // EXPECT_QUIC_BUG tests are expensive so only run one instance of them. if (GetParam() != AllSupportedVersions()[0]) { return; @@ -335,9 +335,9 @@ // Tests that incoming stream creation fails when connection is not connected. size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams(); QuicConnectionPeer::TearDownLocalConnectionState(connection_); - EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingDynamicStream( + EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingStream( session_.get(), GetNthClientInitiatedId(0)), - "ShouldCreateIncomingDynamicStream called when disconnected"); + "ShouldCreateIncomingStream called when disconnected"); EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams()); } @@ -347,14 +347,13 @@ EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, "Client created even numbered stream", _)); - QuicSimpleServerSessionPeer::CreateIncomingDynamicStream(session_.get(), 2); + QuicSimpleServerSessionPeer::CreateIncomingStream(session_.get(), 2); EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams()); } -TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) { - QuicSpdyStream* stream = - QuicSimpleServerSessionPeer::CreateIncomingDynamicStream( - session_.get(), GetNthClientInitiatedId(0)); +TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) { + QuicSpdyStream* stream = QuicSimpleServerSessionPeer::CreateIncomingStream( + session_.get(), GetNthClientInitiatedId(0)); EXPECT_NE(nullptr, stream); EXPECT_EQ(GetNthClientInitiatedId(0), stream->id()); } @@ -371,7 +370,7 @@ EXPECT_QUIC_BUG( QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream( session_.get()), - "ShouldCreateOutgoingDynamicStream called when disconnected"); + "ShouldCreateOutgoingStream called when disconnected"); EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); }
diff --git a/net/third_party/quic/tools/quic_simple_server_stream_test.cc b/net/third_party/quic/tools/quic_simple_server_stream_test.cc index 026b8a1..23324ca0 100644 --- a/net/third_party/quic/tools/quic_simple_server_stream_test.cc +++ b/net/third_party/quic/tools/quic_simple_server_stream_test.cc
@@ -115,7 +115,7 @@ void(QuicErrorCode error, const QuicString& error_details, ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); + MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id)); MOCK_METHOD5(WritevData, QuicConsumedData(QuicStream* stream, QuicStreamId id,
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc index 686229f..46e8eb7 100644 --- a/services/identity/public/cpp/identity_test_environment.cc +++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -5,33 +5,19 @@ #include "services/identity/public/cpp/identity_test_environment.h" #include "base/run_loop.h" -#include "components/signin/core/browser/account_tracker_service.h" -#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h" -#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" -#include "components/signin/core/browser/fake_signin_manager.h" #include "components/signin/core/browser/profile_management_switches.h" #include "components/signin/core/browser/test_signin_client.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "google_apis/gaia/oauth2_access_token_consumer.h" #include "services/identity/public/cpp/identity_test_utils.h" -#if defined(OS_CHROMEOS) -using SigninManagerForTest = FakeSigninManagerBase; -#else -using SigninManagerForTest = FakeSigninManager; -#endif // OS_CHROMEOS - namespace identity { -// Internal class that abstracts the dependencies out of the public interface. -class IdentityTestEnvironmentInternal { +class IdentityManagerDependenciesOwner { public: - IdentityTestEnvironmentInternal( + IdentityManagerDependenciesOwner( bool use_fake_url_loader_for_gaia_cookie_manager); - ~IdentityTestEnvironmentInternal(); - - // The IdentityManager instance created and owned by this instance. - IdentityManager* identity_manager(); + ~IdentityManagerDependenciesOwner(); AccountTrackerService* account_tracker_service(); @@ -48,12 +34,11 @@ FakeProfileOAuth2TokenService token_service_; SigninManagerForTest signin_manager_; FakeGaiaCookieManagerService gaia_cookie_manager_service_; - std::unique_ptr<IdentityManager> identity_manager_; - DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironmentInternal); + DISALLOW_COPY_AND_ASSIGN(IdentityManagerDependenciesOwner); }; -IdentityTestEnvironmentInternal::IdentityTestEnvironmentInternal( +IdentityManagerDependenciesOwner::IdentityManagerDependenciesOwner( bool use_fake_url_loader_for_gaia_cookie_manager) : signin_client_(&pref_service_), token_service_(&pref_service_), @@ -86,119 +71,157 @@ account_tracker_.Initialize(&pref_service_, base::FilePath()); - identity_manager_.reset(new IdentityManager(&signin_manager_, &token_service_, - &account_tracker_, - &gaia_cookie_manager_service_)); } -IdentityTestEnvironmentInternal::~IdentityTestEnvironmentInternal() {} - -IdentityManager* IdentityTestEnvironmentInternal::identity_manager() { - return identity_manager_.get(); -} +IdentityManagerDependenciesOwner::~IdentityManagerDependenciesOwner() {} AccountTrackerService* -IdentityTestEnvironmentInternal::account_tracker_service() { +IdentityManagerDependenciesOwner::account_tracker_service() { return &account_tracker_; } -SigninManagerForTest* IdentityTestEnvironmentInternal::signin_manager() { +SigninManagerForTest* IdentityManagerDependenciesOwner::signin_manager() { return &signin_manager_; } FakeProfileOAuth2TokenService* -IdentityTestEnvironmentInternal::token_service() { +IdentityManagerDependenciesOwner::token_service() { return &token_service_; } FakeGaiaCookieManagerService* -IdentityTestEnvironmentInternal::gaia_cookie_manager_service() { +IdentityManagerDependenciesOwner::gaia_cookie_manager_service() { return &gaia_cookie_manager_service_; } IdentityTestEnvironment::IdentityTestEnvironment( bool use_fake_url_loader_for_gaia_cookie_manager) - : internals_(std::make_unique<IdentityTestEnvironmentInternal>( - use_fake_url_loader_for_gaia_cookie_manager)) { - internals_->identity_manager()->AddDiagnosticsObserver(this); + : IdentityTestEnvironment( + /*account_tracker_service=*/nullptr, + /*token_service=*/nullptr, + /*signin_manager=*/nullptr, + /*gaia_cookie_manager_service=*/nullptr, + std::make_unique<IdentityManagerDependenciesOwner>( + use_fake_url_loader_for_gaia_cookie_manager)) {} + +IdentityTestEnvironment::IdentityTestEnvironment( + AccountTrackerService* account_tracker_service, + FakeProfileOAuth2TokenService* token_service, + SigninManagerForTest* signin_manager, + FakeGaiaCookieManagerService* gaia_cookie_manager_service) + : IdentityTestEnvironment(account_tracker_service, + token_service, + signin_manager, + gaia_cookie_manager_service, + /*dependency_owner=*/nullptr) {} + +IdentityTestEnvironment::IdentityTestEnvironment( + AccountTrackerService* account_tracker_service, + FakeProfileOAuth2TokenService* token_service, + SigninManagerForTest* signin_manager, + FakeGaiaCookieManagerService* gaia_cookie_manager_service, + std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner) { + if (dependencies_owner) { + DCHECK(!(account_tracker_service || token_service || signin_manager || + gaia_cookie_manager_service)); + + dependencies_owner_ = std::move(dependencies_owner); + + account_tracker_service_ = dependencies_owner_->account_tracker_service(); + token_service_ = dependencies_owner_->token_service(); + signin_manager_ = dependencies_owner_->signin_manager(); + gaia_cookie_manager_service_ = + dependencies_owner_->gaia_cookie_manager_service(); + + } else { + DCHECK(account_tracker_service && token_service && signin_manager && + gaia_cookie_manager_service); + + account_tracker_service_ = account_tracker_service; + token_service_ = token_service; + signin_manager_ = signin_manager; + gaia_cookie_manager_service_ = gaia_cookie_manager_service; + } + + identity_manager_ = std::make_unique<IdentityManager>( + signin_manager_, token_service_, account_tracker_service_, + gaia_cookie_manager_service_); + + identity_manager_->AddDiagnosticsObserver(this); } IdentityTestEnvironment::~IdentityTestEnvironment() { - internals_->identity_manager()->RemoveDiagnosticsObserver(this); + identity_manager_->RemoveDiagnosticsObserver(this); } IdentityManager* IdentityTestEnvironment::identity_manager() { - return internals_->identity_manager(); + return identity_manager_.get(); } AccountInfo IdentityTestEnvironment::SetPrimaryAccount( const std::string& email) { - return identity::SetPrimaryAccount(internals_->signin_manager(), - internals_->identity_manager(), email); + return identity::SetPrimaryAccount(signin_manager_, identity_manager(), + email); } void IdentityTestEnvironment::SetRefreshTokenForPrimaryAccount() { - identity::SetRefreshTokenForPrimaryAccount(internals_->token_service(), - internals_->identity_manager()); + identity::SetRefreshTokenForPrimaryAccount(token_service_, + identity_manager()); } void IdentityTestEnvironment::SetInvalidRefreshTokenForPrimaryAccount() { - identity::SetInvalidRefreshTokenForPrimaryAccount( - internals_->token_service(), internals_->identity_manager()); + identity::SetInvalidRefreshTokenForPrimaryAccount(token_service_, + identity_manager()); } void IdentityTestEnvironment::RemoveRefreshTokenForPrimaryAccount() { - identity::RemoveRefreshTokenForPrimaryAccount(internals_->token_service(), - internals_->identity_manager()); + identity::RemoveRefreshTokenForPrimaryAccount(token_service_, + identity_manager()); } AccountInfo IdentityTestEnvironment::MakePrimaryAccountAvailable( const std::string& email) { - return identity::MakePrimaryAccountAvailable( - internals_->signin_manager(), internals_->token_service(), - internals_->identity_manager(), email); + return identity::MakePrimaryAccountAvailable(signin_manager_, token_service_, + identity_manager(), email); } void IdentityTestEnvironment::ClearPrimaryAccount( ClearPrimaryAccountPolicy policy) { - identity::ClearPrimaryAccount(internals_->signin_manager(), - internals_->identity_manager(), policy); + identity::ClearPrimaryAccount(signin_manager_, identity_manager(), policy); } AccountInfo IdentityTestEnvironment::MakeAccountAvailable( const std::string& email) { - return identity::MakeAccountAvailable(internals_->account_tracker_service(), - internals_->token_service(), - internals_->identity_manager(), email); + return identity::MakeAccountAvailable( + account_tracker_service_, token_service_, identity_manager(), email); } void IdentityTestEnvironment::SetRefreshTokenForAccount( const std::string& account_id) { - return identity::SetRefreshTokenForAccount( - internals_->token_service(), internals_->identity_manager(), account_id); + return identity::SetRefreshTokenForAccount(token_service_, identity_manager(), + account_id); } void IdentityTestEnvironment::SetInvalidRefreshTokenForAccount( const std::string& account_id) { return identity::SetInvalidRefreshTokenForAccount( - internals_->token_service(), internals_->identity_manager(), account_id); + token_service_, identity_manager(), account_id); } void IdentityTestEnvironment::RemoveRefreshTokenForAccount( const std::string& account_id) { - return identity::RemoveRefreshTokenForAccount( - internals_->token_service(), internals_->identity_manager(), account_id); + return identity::RemoveRefreshTokenForAccount(token_service_, + identity_manager(), account_id); } void IdentityTestEnvironment::SetCookieAccounts( const std::vector<CookieParams>& cookie_accounts) { - identity::SetCookieAccounts(internals_->gaia_cookie_manager_service(), - internals_->identity_manager(), cookie_accounts); + identity::SetCookieAccounts(gaia_cookie_manager_service_, identity_manager(), + cookie_accounts); } void IdentityTestEnvironment::SetAutomaticIssueOfAccessTokens(bool grant) { - internals_->token_service()->set_auto_post_fetch_response_on_message_loop( - grant); + token_service_->set_auto_post_fetch_response_on_message_loop(grant); } void IdentityTestEnvironment:: @@ -206,8 +229,7 @@ const std::string& token, const base::Time& expiration) { WaitForAccessTokenRequestIfNecessary(base::nullopt); - internals_->token_service()->IssueTokenForAllPendingRequests(token, - expiration); + token_service_->IssueTokenForAllPendingRequests(token, expiration); } void IdentityTestEnvironment:: @@ -216,7 +238,7 @@ const base::Time& expiration, const std::string& id_token) { WaitForAccessTokenRequestIfNecessary(base::nullopt); - internals_->token_service()->IssueTokenForAllPendingRequests( + token_service_->IssueTokenForAllPendingRequests( OAuth2AccessTokenConsumer::TokenResponse(token, expiration, id_token)); } @@ -226,15 +248,14 @@ const std::string& token, const base::Time& expiration) { WaitForAccessTokenRequestIfNecessary(account_id); - internals_->token_service()->IssueAllTokensForAccount(account_id, token, - expiration); + token_service_->IssueAllTokensForAccount(account_id, token, expiration); } void IdentityTestEnvironment:: WaitForAccessTokenRequestIfNecessaryAndRespondWithError( const GoogleServiceAuthError& error) { WaitForAccessTokenRequestIfNecessary(base::nullopt); - internals_->token_service()->IssueErrorForAllPendingRequests(error); + token_service_->IssueErrorForAllPendingRequests(error); } void IdentityTestEnvironment:: @@ -242,8 +263,7 @@ const std::string& account_id, const GoogleServiceAuthError& error) { WaitForAccessTokenRequestIfNecessary(account_id); - internals_->token_service()->IssueErrorForAllPendingRequestsForAccount( - account_id, error); + token_service_->IssueErrorForAllPendingRequestsForAccount(account_id, error); } void IdentityTestEnvironment::SetCallbackForNextAccessTokenRequest(
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h index e473eec..9c1700a 100644 --- a/services/identity/public/cpp/identity_test_environment.h +++ b/services/identity/public/cpp/identity_test_environment.h
@@ -6,21 +6,52 @@ #define SERVICES_IDENTITY_PUBLIC_CPP_IDENTITY_TEST_ENVIRONMENT_H_ #include "base/optional.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h" +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" +#include "components/signin/core/browser/fake_signin_manager.h" #include "services/identity/public/cpp/identity_manager.h" #include "services/identity/public/cpp/identity_test_utils.h" namespace identity { -class IdentityTestEnvironmentInternal; +// Internal class that creates and owns dependencies of IdentityManager +// when those dependencies are not passed in externally. +class IdentityManagerDependenciesOwner; // Class that creates an IdentityManager for use in testing contexts and // provides facilities for driving that IdentityManager. The IdentityManager // instance is brought up in an environment where the primary account is // not available; call MakePrimaryAccountAvailable() as needed. class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver { +#if defined(OS_CHROMEOS) + using SigninManagerForTest = FakeSigninManagerBase; +#else + using SigninManagerForTest = FakeSigninManager; +#endif // OS_CHROMEOS + public: + // Preferred constructor: constructs an IdentityManager object and its + // dependencies internally. Cannot be used if the client of this class + // is still interacting directly with those dependencies (e.g., if + // IdentityTestEnvironment is being introduced to incrementally convert + // a test). In that case, use the below constructor and switch to this + // constructor once the conversion is complete. IdentityTestEnvironment( bool use_fake_url_loader_for_gaia_cookie_manager = false); + + // Constructor that takes in instances of the dependencies of + // IdentityManager and constructs an IdentityManager instance from those + // dependencies. For use in contexts where those dependencies are still + // being used directly by the creator of this object (i.e., while a test is + // being incrementally converted). Prefer the above constructor, and switch to + // that constructor once possible (e.g., when an incremental conversion is + // completed). NOTE: The passed-in objects must all outlive this object. + IdentityTestEnvironment( + AccountTrackerService* account_tracker_service, + FakeProfileOAuth2TokenService* token_service, + SigninManagerForTest* signin_manager, + FakeGaiaCookieManagerService* gaia_cookie_manager_service); ~IdentityTestEnvironment() override; // The IdentityManager instance created and owned by this instance. @@ -180,6 +211,17 @@ base::OnceClosure on_available; }; + // Constructs this object and its IdentityManager instance from the supplied + // dependencies of IdentityManager, which must be either: + // (1) non-null instances of the backing classes, OR + // (2) a non-null instance of |dependencies_owner|. + IdentityTestEnvironment( + AccountTrackerService* account_tracker_service, + FakeProfileOAuth2TokenService* token_service, + SigninManagerForTest* signin_manager, + FakeGaiaCookieManagerService* gaia_cookie_manager_service, + std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner); + // IdentityManager::DiagnosticsObserver: void OnAccessTokenRequested( const std::string& account_id, @@ -199,7 +241,16 @@ void WaitForAccessTokenRequestIfNecessary( base::Optional<std::string> account_id); - std::unique_ptr<IdentityTestEnvironmentInternal> internals_; + // NOTE: This object must be first in the list, as it owns the objects + // pointed to below in the case where those objects are not passed in via + // the IdentityTestEnvironment constructor. + std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner_; + AccountTrackerService* account_tracker_service_ = nullptr; + FakeProfileOAuth2TokenService* token_service_ = nullptr; + SigninManagerForTest* signin_manager_ = nullptr; + FakeGaiaCookieManagerService* gaia_cookie_manager_service_ = nullptr; + std::unique_ptr<IdentityManager> identity_manager_; + base::OnceClosure on_access_token_requested_callback_; std::vector<AccessTokenRequestState> requesters_;
diff --git a/third_party/OWNERS b/third_party/OWNERS index 6447bcb..7b36d33 100644 --- a/third_party/OWNERS +++ b/third_party/OWNERS
@@ -14,10 +14,6 @@ # Eng reviewer file://ENG_REVIEW_OWNERS -# Automatic round-robin assignment of reviewer for third-party licenses. -# No one receives email to this list, just use it as a reviewer. -chromium-third-party@google.com - thakis@chromium.org per-file .gitignore=*
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index b6ad3cd..92389fa9 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -25,7 +25,7 @@ crbug.com/636993 external/wpt/css/css-text-decor/text-decoration-color.html [ Failure ] # text-overflow:ellipsis and paint fragment -crbug.com/873957 accessibility/ellipsis-text.html [ Failure ] +crbug.com/873957 accessibility/ellipsis-text.html [ Failure Pass ] crbug.com/873957 http/tests/devtools/network/network-cookies-pane.js [ Failure ] # rightsizing-grid.html is truly flaky, show flakiness on reload @@ -84,6 +84,8 @@ crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-003.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html [ Pass ] +crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Pass ] +crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Pass ] crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ] @@ -194,6 +196,11 @@ crbug.com/591099 external/wpt/css/selectors/selector-placeholder-shown-type-change-001.html [ Pass ] crbug.com/591099 external/wpt/css/selectors/selector-read-write-type-change-002.html [ Pass ] crbug.com/591099 external/wpt/css/selectors/selector-required-type-change-002.html [ Pass ] +crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-block-001.html [ Pass ] +crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-fieldset-001.html [ Pass ] +crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-fieldset-002.html [ Pass ] +crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-inline-block-001.html [ Pass ] +crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-inline-flex-001.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Pass ] @@ -249,9 +256,9 @@ crbug.com/591099 external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html [ Pass ] crbug.com/591099 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html [ Pass ] crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Pass ] -crbug.com/591099 external/wpt/picture-in-picture/request-picture-in-picture-twice.html [ Pass ] +crbug.com/591099 external/wpt/picture-in-picture/request-picture-in-picture-twice.html [ Failure Pass Timeout ] crbug.com/591099 external/wpt/quirks/line-height-calculation.html [ Failure ] -crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass ] +crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass Timeout ] crbug.com/591099 external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ] crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ] crbug.com/591099 external/wpt/workers/Worker_ErrorEvent_error.htm [ Pass ] @@ -287,7 +294,7 @@ crbug.com/835484 fast/inline/outline-offset.html [ Failure ] crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ] crbug.com/591099 fast/replaced/table-replaced-element.html [ Failure ] -crbug.com/591099 fast/scrolling/scrollbar-tickmarks-hittest.html [ Failure ] +crbug.com/591099 fast/scrolling/scrollbar-tickmarks-hittest.html [ Failure Pass ] crbug.com/591099 fast/sub-pixel/sub-pixel-border-2.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/004-vertical.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/composited-cell-collapsed-border.html [ Failure ] @@ -327,7 +334,7 @@ crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] -crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Pass Timeout ] +crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass ] crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ] crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ] @@ -385,9 +392,10 @@ crbug.com/591099 tables/mozilla/bugs/bug2973.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug55527.html [ Failure ] +crbug.com/591099 transforms/3d/general/perspective-units.html [ Failure ] crbug.com/591099 transforms/svg-vs-css.xhtml [ Failure ] -crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure ] -crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document.html [ Failure Pass ] +crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure Pass ] +crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document.html [ Failure ] crbug.com/591099 virtual/exotic-color-space/ [ Skip ] crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ] @@ -408,7 +416,6 @@ crbug.com/591099 virtual/outofblink-cors-ns/http/tests/fetch/chromium/release-handle-crash.html [ Crash Pass ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] -crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/document-domain-canonicalizes.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/video-poster-cross-origin-crash2.html [ Pass ] crbug.com/591099 virtual/outofblink-cors/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/css-shadow-parts/double-forward.html b/third_party/WebKit/LayoutTests/css-shadow-parts/double-forward.html index 6e2f26f..ad052bd 100644 --- a/third_party/WebKit/LayoutTests/css-shadow-parts/double-forward.html +++ b/third_party/WebKit/LayoutTests/css-shadow-parts/double-forward.html
@@ -17,9 +17,9 @@ <span id="green_part" part="partp">This text</span> </template> <script>installCustomElement("custom-element-middle", "custom-element-middle-template");</script> - <template id="custom-element-middle-template"><custom-element-inner id="c-e-inner" partmap="partp part-forwarded1"></custom-element-inner></template> + <template id="custom-element-middle-template"><custom-element-inner id="c-e-inner" partmap="partp: part-forwarded1"></custom-element-inner></template> <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-middle id="c-e-middle" partmap="part-forwarded1 part-forwarded2"></custom-element-middle></template> + <template id="custom-element-outer-template"><custom-element-middle id="c-e-middle" partmap="part-forwarded1: part-forwarded2"></custom-element-middle></template> The following text should be green: <custom-element-outer id="c-e-outer"></custom-element-outer> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-part-name-forward.html b/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-part-name-forward.html index 02973e29..452567b0 100644 --- a/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-part-name-forward.html +++ b/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-part-name-forward.html
@@ -17,7 +17,7 @@ <span id="part" part="partp">This text</span> </template> <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp part-forwarded"></custom-element-inner></template> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp: part-forwarded"></custom-element-inner></template> The following text should be green: <custom-element-outer id="c-e-outer"></custom-element-outer> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-partmap-forward.html b/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-partmap-forward.html index c67f656..dc70430 100644 --- a/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-partmap-forward.html +++ b/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-change-partmap-forward.html
@@ -17,7 +17,7 @@ <span id="part" part="partp">This text</span> </template> <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp part-forwarded"></custom-element-inner></template> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp: part-forwarded"></custom-element-inner></template> The following text should be green: <custom-element-outer id="c-e-outer"></custom-element-outer> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-complex-selector-forward.html b/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-complex-selector-forward.html index fbd2a2b..25fc710 100644 --- a/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-complex-selector-forward.html +++ b/third_party/WebKit/LayoutTests/css-shadow-parts/invalidation-complex-selector-forward.html
@@ -17,7 +17,7 @@ <span id="part" part="partp">This text</span> </template> <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp part-forwarded"></custom-element-inner></template> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp: part-forwarded"></custom-element-inner></template> The following text should be green: <div id="elem"><custom-element-outer id="c-e-outer"></custom-element-outer></div> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/css-shadow-parts/precedence-part-vs-part.html b/third_party/WebKit/LayoutTests/css-shadow-parts/precedence-part-vs-part.html index e87a1c8..8a46fa3 100644 --- a/third_party/WebKit/LayoutTests/css-shadow-parts/precedence-part-vs-part.html +++ b/third_party/WebKit/LayoutTests/css-shadow-parts/precedence-part-vs-part.html
@@ -19,7 +19,7 @@ <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> <template id="custom-element-outer-template"> <style>#c-e-inner::part(partp) { color: red; }</style> - <custom-element-inner id="c-e-inner" partmap="partp part-forwarded"></custom-element-inner> + <custom-element-inner id="c-e-inner" partmap="partp: part-forwarded"></custom-element-inner> </template> The following text should be green: <custom-element-outer id="c-e-outer"></custom-element-outer>
diff --git a/third_party/WebKit/LayoutTests/css-shadow-parts/simple-forward.html b/third_party/WebKit/LayoutTests/css-shadow-parts/simple-forward.html index 1bf4557..1cc3faa 100644 --- a/third_party/WebKit/LayoutTests/css-shadow-parts/simple-forward.html +++ b/third_party/WebKit/LayoutTests/css-shadow-parts/simple-forward.html
@@ -17,7 +17,7 @@ <span id="green_part" part="partp">This text</span> </template> <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp part-forwarded"></custom-element-inner></template> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" partmap="partp: part-forwarded"></custom-element-inner></template> The following text should be green: <custom-element-outer id="c-e-outer"></custom-element-outer> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json index 1195a15..d5c6dcf 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -151483,6 +151483,11 @@ {} ] ], + "feature-policy/reporting/generic-sensor-reporting.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/geolocation-reporting.https.html.headers": [ [ {} @@ -177893,6 +177898,16 @@ {} ] ], + "wasm/jsapi/idlharness.any-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/idlharness.any.worker-expected.txt": [ + [ + {} + ] + ], "wasm/jsapi/instanceTestFactory.js": [ [ {} @@ -221495,6 +221510,12 @@ {} ] ], + "feature-policy/reporting/generic-sensor-reporting.https.html": [ + [ + "/feature-policy/reporting/generic-sensor-reporting.https.html", + {} + ] + ], "feature-policy/reporting/geolocation-reporting.https.html": [ [ "/feature-policy/reporting/geolocation-reporting.https.html", @@ -266171,16 +266192,6 @@ {} ] ], - "wasm/idlharness.any.js": [ - [ - "/wasm/idlharness.any.html", - {} - ], - [ - "/wasm/idlharness.any.worker.html", - {} - ] - ], "wasm/jsapi/constructor/compile.any.js": [ [ "/wasm/jsapi/constructor/compile.any.html", @@ -266309,6 +266320,16 @@ {} ] ], + "wasm/jsapi/idlharness.any.js": [ + [ + "/wasm/jsapi/idlharness.any.html", + {} + ], + [ + "/wasm/jsapi/idlharness.any.worker.html", + {} + ] + ], "wasm/jsapi/instance/constructor-bad-imports.any.js": [ [ "/wasm/jsapi/instance/constructor-bad-imports.any.html", @@ -267569,6 +267590,12 @@ {} ] ], + "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-reuse.html": [ + [ + "/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-reuse.html", + {} + ] + ], "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer.html": [ [ "/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer.html", @@ -335985,7 +336012,7 @@ "support" ], "css/css-properties-values-api/typedom.tentative.html": [ - "6d0623bba420dfe5becafb9eb59cbdf4ad115954", + "51e45e887721a3e32325eefe62d984d3c1966922", "testharness" ], "css/css-properties-values-api/unit-cycles.html": [ @@ -362285,7 +362312,7 @@ "testharness" ], "css/geometry/interfaces-expected.txt": [ - "757d30bebc32a7a7be1eff7f501a9006f4bfe8ff", + "0e6decf1cc9af129823094dcc5cb444d8b76783e", "support" ], "css/geometry/interfaces.html": [ @@ -370005,7 +370032,7 @@ "testharness" ], "dom/interfaces_exclude=Node-expected.txt": [ - "cc031315525997f8247cbfbfa749f48a7626978f", + "33ba6302ac10570d37fa9b0f229142761ab21151", "support" ], "dom/lists/DOMTokenList-Iterable.html": [ @@ -375212,6 +375239,14 @@ "d35e48ba40dc65a3b043a3e41a11332c42bfdba9", "support" ], + "feature-policy/reporting/generic-sensor-reporting.https.html": [ + "c60e3e81a1dddbdc000d799c19719c48ad55376c", + "testharness" + ], + "feature-policy/reporting/generic-sensor-reporting.https.html.headers": [ + "80cc02753044a3730695bce65bc2b4c22d7a8a6b", + "support" + ], "feature-policy/reporting/geolocation-reporting.https.html": [ "22e258563b799c7d48db2452f15eb6124d1f2d0e", "testharness" @@ -398241,7 +398276,7 @@ "support" ], "interfaces/webrtc.idl": [ - "cdeb5204e6a0b5735948b94d5e30931bc2fd062e", + "7496fff41dcbbeda6759977d56e12c21568b49f5", "support" ], "interfaces/webusb.idl": [ @@ -420097,7 +420132,7 @@ "support" ], "resources/idlharness.js": [ - "950df6fa34b82a3f4afe2ab925d90a72ddcf3872", + "0f49a725c33736d6ff4cb395234d2bf0c78970f9", "support" ], "resources/idlharness.js.headers": [ @@ -423477,7 +423512,7 @@ "support" ], "service-workers/service-worker/resources/service-worker-header.py": [ - "2e82e78107ad4f70b3e88d700139195f8a5b029e", + "74f57a72a9041762f9f50732d2ce890d889810c5", "support" ], "service-workers/service-worker/resources/service-worker-interception-dynamic-import-worker.js": [ @@ -423689,7 +423724,7 @@ "testharness" ], "service-workers/service-worker/service-worker-header.https.html": [ - "2584485c65ab60e8b429c3db66fc43a8157a8ed5", + "fb902cd1b455d130c899cf06bf05c32184d2b543", "testharness" ], "service-workers/service-worker/serviceworker-message-event-historical.https.html": [ @@ -424541,7 +424576,7 @@ "support" ], "shape-detection/idlharness.any-expected.txt": [ - "24c619327dbc1917215950282a7a727ba63ecea3", + "d6bc9aa971cd4103ee67a99ca4f8854ae2d3a325", "support" ], "shape-detection/idlharness.any.js": [ @@ -428468,10 +428503,6 @@ "b55d60b65e2754e19f3464ca34ba67125f5ac2b1", "support" ], - "wasm/idlharness.any.js": [ - "9c29ad14559382eba1d4c10cf5782e3e04682f2c", - "testharness" - ], "wasm/idlharness.any.worker-expected.txt": [ "4aabd115ec68f2dbe9427f0c1569114ad3f33ca0", "support" @@ -428544,6 +428575,18 @@ "d4a84b254f76ea50284619967ab6dc98c99bfea2", "testharness" ], + "wasm/jsapi/idlharness.any-expected.txt": [ + "d120c0a8f6dac128cc75921b4f4220210b4ccf74", + "support" + ], + "wasm/jsapi/idlharness.any.js": [ + "25298d3dabfbbce7490fa040258f3e06cd94b582", + "testharness" + ], + "wasm/jsapi/idlharness.any.worker-expected.txt": [ + "d120c0a8f6dac128cc75921b4f4220210b4ccf74", + "support" + ], "wasm/jsapi/instance/constructor-bad-imports.any.js": [ "24c51c10dc5df9d52c06bfb0715e435b17f24f7a", "testharness" @@ -428693,7 +428736,7 @@ "support" ], "wasm/resources/load_wasm.js": [ - "512324639059da8a9d76e9d740d97fc56ebdebc4", + "8316dcfbc89bd02073e4e08db1bee7f65d37e86c", "support" ], "wasm/serialization/broadcastchannel-success-and-failure.html": [ @@ -429816,6 +429859,10 @@ "612a91cf4ef60f6f1d441d27e2ab86f32b94f0fd", "testharness" ], + "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-reuse.html": [ + "dabe323cbe2226d32c63576199eda61c1aecb168", + "testharness" + ], "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer.html": [ "a2c4581c4e80069f227fe29078bc3eb6409c8b4e", "testharness" @@ -431945,7 +431992,7 @@ "support" ], "webrtc/idlharness.https.window-expected.txt": [ - "2730fbb3b2606b4599af0b6c317ca87948a71e90", + "794763f85fa85e75d061590307bdae997e742071", "support" ], "webrtc/idlharness.https.window.js": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html index 6d0623b..0255b8f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html
@@ -221,86 +221,86 @@ let name2 = gen_prop('<length>', '0px'); styleDecl.setProperty(name2, `var(${name1})`); assert_true(propertyMap.get(name2) instanceof CSSUnparsedValue); -}, name => `${name}.get returns CSSUnparsedValue for value with var references`); +}, name => `StylePropertyMap.get returns CSSUnparsedValue for value with var references (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ let name1 = gen_prop('<length>', '100px'); let name2 = gen_prop('<length>#', '0px'); styleDecl.setProperty(name2, `1px, var(${name1}), 3px`); assert_true(propertyMap.get(name2) instanceof CSSUnparsedValue); -}, name => `${name}.get returns CSSUnparsedValue for value with var references in list`); +}, name => `StylePropertyMap.get returns CSSUnparsedValue for value with var references in list (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '*', 'if(){}', CSSUnparsedValue); -}, name => `${name}.get returns CSSUnparsedValue for *`); +}, name => `StylePropertyMap.get returns CSSUnparsedValue for * (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<angle>', '42deg', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <angle>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <angle> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<color>', '#fefefe', CSSStyleValue); -}, name => `${name}.get returns CSSStyleValue for <color>`); +}, name => `StylePropertyMap.get returns CSSStyleValue for <color> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<custom-ident>', 'none', CSSKeywordValue); -}, name => `${name}.get returns CSSKeywordValue for <custom-ident>`); +}, name => `StylePropertyMap.get returns CSSKeywordValue for <custom-ident> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<image>', 'url(thing.png)', CSSImageValue); -}, name => `${name}.get returns CSSImageValue for <image>`); +}, name => `StylePropertyMap.get returns CSSImageValue for <image> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<integer>', '100', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <integer>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <integer> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<length-percentage>', '10%', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <length-percentage> [10%]`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <length-percentage> [10%] (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<length-percentage>', '10px', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <length-percentage> [10px]`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <length-percentage> [10px] (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<length-percentage>', 'calc(10px + 10%)', CSSMathSum); -}, name => `${name}.get returns CSSMathSum for <length-percentage> [calc(10px + 10%)]`); +}, name => `StylePropertyMap.get returns CSSMathSum for <length-percentage> [calc(10px + 10%)] (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<length>', '10px', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <length>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <length> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<number>', '42', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <number>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <number> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<percentage>', '10%', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <percentage>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <percentage> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<resolution>', '300dpi', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <resolution>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <resolution> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<time>', '42s', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <time>`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <time> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<url>', 'url(a)', CSSStyleValue); -}, name => `${name}.get returns CSSStyleValue for <url>`); +}, name => `StylePropertyMap.get returns CSSStyleValue for <url> (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, 'thing1 | THING2', 'thing1', CSSKeywordValue); -}, name => `${name}.get returns CSSKeywordValue for thing1 | THING2`); +}, name => `StylePropertyMap.get returns CSSKeywordValue for thing1 | THING2 (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<length>+', '10px 20px', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <length>+`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <length>+ (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ assert_attribute_get_type(styleDecl, propertyMap, '<length>#', '10px 20px', CSSUnitValue); -}, name => `${name}.get returns CSSUnitValue for <length>#`); +}, name => `StylePropertyMap.get returns CSSUnitValue for <length># (${name})`); // attributeStyleMap.getAll @@ -309,14 +309,14 @@ styleDecl.setProperty(name, '10px 20px 30px'); assert_equals(propertyMap.getAll(name).length, 3); assert_true(propertyMap.getAll(name).every(x => x instanceof CSSUnitValue)); -}, name => `${name}.getAll returns a list of CSSUnitValues for <length>+`); +}, name => `StylePropertyMap.getAll returns a list of CSSUnitValues for <length>+ (${name})`); test_style_property_map_get(function(styleDecl, propertyMap){ let name = gen_prop('<length>#', '0px'); styleDecl.setProperty(name, '10px, 20px, 30px'); assert_equals(propertyMap.getAll(name).length, 3); assert_true(propertyMap.getAll(name).every(x => x instanceof CSSUnitValue)); -}, name => `${name}.getAll returns a list of CSSUnitValues for <length>#`); +}, name => `StylePropertyMap.getAll returns a list of CSSUnitValues for <length># (${name})`); // StylePropertyMap.set @@ -325,13 +325,15 @@ let name = gen_prop(options.syntax, options.initialValue); propertyMap.clear(); + let ensureArray = v => v.constructor === Array ? v : [v]; + for (let value of options.shouldAccept) - propertyMap.set(name, value); + propertyMap.set(name, ...ensureArray(value)); for (let value of options.shouldReject) { - assert_throws(new TypeError(), () => propertyMap.set(name, value)); + assert_throws(new TypeError(), () => propertyMap.set(name, ...ensureArray(value))); } - }, `${propertyMapName}.set accepts correct CSSUnitValues for ${options.syntax}`); + }, `StylePropertyMap.set accepts correct CSSStyleValues for ${options.syntax} (${propertyMapName})`); } // Verify that the correct CSSStyleValues are accepted/rejected for a registered @@ -360,77 +362,77 @@ syntax: '<angle>', initialValue: '0deg', shouldAccept: [CSS.deg(42), CSS.turn(2), '42deg'], - shouldReject: [unparsed('42deg'), CSS.px(15), '50px'], + shouldReject: [unparsed('42deg'), CSS.px(15), '50px', [CSS.deg(15), '10deg']], }); test_style_property_map_set({ syntax: '<custom-ident>', initialValue: 'none', shouldAccept: [keyword('foo'), 'foo'], - shouldReject: [unparsed('foo'), CSS.px(15), '15px'], + shouldReject: [unparsed('foo'), CSS.px(15), '15px', [keyword('foo'), 'foo']], }); test_style_property_map_set({ syntax: '<image>', initialValue: 'url(a)', shouldAccept: [url_image('url(b)'), 'url(b)'], - shouldReject: [unparsed('url(b)'), CSS.px(100), '50px'], + shouldReject: [unparsed('url(b)'), CSS.px(100), '50px', [url_image('url(1)'), 'url(2)']], }); test_style_property_map_set({ syntax: '<integer>', initialValue: '0', shouldAccept: [CSS.number(1), CSS.number(-42), '1', '-42'], - shouldReject: [unparsed('42'), CSS.px(100), '50px'], + shouldReject: [unparsed('42'), CSS.px(100), '50px', [CSS.number(42), '42']], }); test_style_property_map_set({ syntax: '<length-percentage>', initialValue: '0px', shouldAccept: [CSS.percent(10), CSS.px(1), CSS.em(1), '10px', '10%'], - shouldReject: [unparsed('10%'), unparsed('10px'), CSS.dpi(1), 'url(b)'], + shouldReject: [unparsed('10%'), unparsed('10px'), CSS.dpi(1), 'url(b)', [CSS.percent(10), '10%']], }); test_style_property_map_set({ syntax: '<length>', initialValue: '0px', shouldAccept: [CSS.px(10), CSS.em(10), CSS.vh(200), sum(CSS.px(10), CSS.em(20)), '10em', 'calc(10px + 10em)'], - shouldReject: [unparsed('10px'), CSS.percent(1), 'url(b)'], + shouldReject: [unparsed('10px'), CSS.percent(1), 'url(b)', [CSS.em(10), '10px']], }); test_style_property_map_set({ syntax: '<number>', initialValue: '0', shouldAccept: [CSS.number(1337), CSS.number(-42.5), '1337', '-42.5'], - shouldReject: [unparsed('42'), CSS.px(15), '#fef'], + shouldReject: [unparsed('42'), CSS.px(15), '#fef', [CSS.number(-42.5), '42.5']], }); test_style_property_map_set({ syntax: '<percentage>', initialValue: '0%', shouldAccept: [CSS.percent(10), '10%'], - shouldReject: [unparsed('10%'), CSS.px(1), '#fef'], + shouldReject: [unparsed('10%'), CSS.px(1), '#fef', [CSS.percent(10), '1%']], }); test_style_property_map_set({ syntax: '<resolution>', initialValue: '0dpi', shouldAccept: [CSS.dpi(100), CSS.dpcm(10), CSS.dppx(50), '100dpi'], - shouldReject: [unparsed('42'), CSS.px(15), '#fef'], + shouldReject: [unparsed('42'), CSS.px(15), '#fef', [CSS.dpi(1), '2dpi']], }); test_style_property_map_set({ syntax: '<time>', initialValue: '0s', shouldAccept: [CSS.s(42), CSS.ms(16), '16ms'], - shouldReject: [unparsed('42s'), CSS.px(15), '#fef'], + shouldReject: [unparsed('42s'), CSS.px(15), '#fef', [CSS.s(5), '6s']], }); test_style_property_map_set({ syntax: '<url>', initialValue: 'url(a)', shouldAccept: [url_image('url(b)')], - shouldReject: [unparsed('url(b)'), CSS.px(100), '#fef'], + shouldReject: [unparsed('url(b)'), CSS.px(100), '#fef', [url_image('url(1)'), 'url(2)']], }); test_style_property_map_set({ @@ -444,14 +446,308 @@ syntax: 'none | thing | THING', initialValue: 'none', shouldAccept: [keyword('thing'), keyword('THING'), 'thing'], - shouldReject: [unparsed('thing'), CSS.px(15), keyword('notathing'), 'notathing'], + shouldReject: [unparsed('thing'), CSS.px(15), keyword('notathing'), 'notathing', [keyword('thing'), keyword('thing')]], }); test_style_property_map_set({ syntax: '<angle> | <length>', initialValue: '0deg', shouldAccept: [CSS.deg(42), CSS.turn(2), CSS.px(10), CSS.em(10), '10deg', '10px'], - shouldReject: [unparsed('42deg'), unparsed('20px'), CSS.s(1), '#fef'], + shouldReject: [unparsed('42deg'), unparsed('20px'), CSS.s(1), '#fef', [CSS.deg(42), '21deg']], +}); + +// StylePropertyMap.set for list-valued properties: + +test_style_property_map_set({ + syntax: '<angle>+', + initialValue: '0deg', + shouldAccept: [CSS.deg(15), [CSS.deg(15), '10deg'], '15deg 10deg'], + shouldReject: [[CSS.deg(15), CSS.px(10)], '15deg 10px'], +}); + +test_style_property_map_set({ + syntax: '<custom-ident>+', + initialValue: 'none', + shouldAccept: [keyword('foo'), [keyword('foo'), 'bar'], 'foo bar'], + shouldReject: [[keyword('foo'), CSS.px(10)], 'foo 10px'], +}); + +test_style_property_map_set({ + syntax: '<image>+', + initialValue: 'url(a)', + shouldAccept: [url_image('url(1)'), [url_image('url(1)'), 'url(2)'], 'url(1) url(2)'], + shouldReject: [[url_image('url(1)'), CSS.px(10)], 'url(1) 10px'], +}); + +test_style_property_map_set({ + syntax: '<integer>+', + initialValue: '0', + shouldAccept: [CSS.number(42), [CSS.number(42), '42'], '42 42'], + shouldReject: [[CSS.number(42), keyword('noint')], '42 noint'], +}); + +test_style_property_map_set({ + syntax: '<length-percentage>+', + initialValue: '0px', + shouldAccept: [CSS.percent(10), [CSS.percent(10), '10%']], + shouldReject: [[CSS.percent(10), keyword('nolength')], '10% nolength'], +}); + +test_style_property_map_set({ + syntax: '<length>+', + initialValue: '0px', + shouldAccept: [CSS.em(10), [CSS.em(10), '10px']], + shouldReject: [[CSS.em(10), keyword('nolength'), '10em nolength']], +}); + +test_style_property_map_set({ + syntax: '<number>+', + initialValue: '0', + shouldAccept: [CSS.number(-42.5), [CSS.number(-42.5), '42.5'], '-42.5 42.5'], + shouldReject: [[CSS.number(-42.5), CSS.px(10)], '-42.5 10px'], +}); + +test_style_property_map_set({ + syntax: '<percentage>+', + initialValue: '0%', + shouldAccept: [CSS.percent(10), [CSS.percent(10), '1%'], '10% 1%'], + shouldReject: [[CSS.percent(10), keyword('foo')], '10% foo'], +}); + +test_style_property_map_set({ + syntax: '<resolution>+', + initialValue: '0dpi', + shouldAccept: [CSS.dpi(1), [CSS.dpi(1), '2dpi'], '1dpi 2dpi'], + shouldReject: [[CSS.dpi(1), keyword('foo')], '1dpi foo'], +}); + +test_style_property_map_set({ + syntax: '<time>+', + initialValue: '0s', + shouldAccept: [CSS.s(5), [CSS.s(5), '6s'], '5s 6s'], + shouldReject: [[CSS.s(5), keyword('foo')], '5s foo'], +}); + +test_style_property_map_set({ + syntax: '<url>+', + initialValue: 'url(a)', + shouldAccept: [url_image('url(1)'), [url_image('url(1)'), 'url(2)'], 'url(1) url(2)'], + shouldReject: [[url_image('url(1)'), CSS.px(10)], 'url(1) 10px'], +}); + +test_style_property_map_set({ + syntax: 'thing+', + initialValue: 'thing', + shouldAccept: [keyword('thing'), [keyword('thing'), 'thing'], 'thing thing'], + shouldReject: [[keyword('thing'), CSS.px(10)], 'thing 10px'], +}); + +test_style_property_map_set({ + syntax: '<length>#', + initialValue: '0px', + shouldAccept: [CSS.em(10), [CSS.em(10), '10px']], + shouldReject: [[CSS.em(10), keyword('nolength'), '10em nolength']], +}); + +function test_append_for_property_map(propertyMapName, propertyMap, options) { + test(function(){ + let name = gen_prop(options.syntax, options.initialValue); + + let ensureArray = v => v.constructor === Array ? v : [v]; + + for (let value of options.values) { + propertyMap.clear(); + + if (value.base !== null) + propertyMap.set(name, ...ensureArray(value.base)); + + // If 'null' is expected, it means we expect the append to fail. + if (value.expect !== null) { + propertyMap.append(name, ...ensureArray(value.append)); + let actual = Array.from(propertyMap.getAll(name)).join(' '); + assert_equals(actual, value.expect); + } else { + assert_throws(new TypeError(), () => propertyMap.append(name, ...ensureArray(value.append))); + } + } + }, `StylePropertyMap.append accepts correct CSSStyleValues for ${options.syntax} (${propertyMapName})`); +} + +// Verify that the correct CSSStyleValues are accepted/rejected when +// appending values to list-valued properties. +// +// The same test is performed twice: once for attributeStyleMap, and once +// for styleMap. +function test_append(options) { + test_append_for_property_map('attributeStyleMap', target.attributeStyleMap, options); + test_append_for_property_map('styleMap', style.sheet.rules[0].styleMap, options); +} + +test_append({ + syntax: '<angle>+', + initialValue: '0deg', + values: [ + { base: [CSS.deg(1)], append: [CSS.px(1)], expect: null }, + { base: [CSS.deg(1)], append: [CSS.deg(2), CSS.px(1)], expect: null }, + { base: [CSS.deg(1)], append: [CSS.deg(2), '1px'], expect: null }, + { base: [CSS.deg(1)], append: [CSS.turn(2), CSS.deg(3)], expect: '1deg 2turn 3deg' }, + { base: [CSS.deg(1), CSS.deg(2)], append: [CSS.deg(3)], expect: '1deg 2deg 3deg' }, + { base: [CSS.deg(1)], append: [CSS.deg(2), '3deg'], expect: '1deg 2deg 3deg' }, + { base: [CSS.deg(1)], append: [CSS.deg(2), '3turn 4deg'], expect: '1deg 2deg 3turn 4deg' }, + { base: null, append: [CSS.deg(1), '2deg'], expect: '1deg 2deg' }, + ], +}); + +test_append({ + syntax: '<custom-ident>+', + initialValue: 'none', + values: [ + { base: [keyword('foo')], append: [CSS.px(1)], expect: null }, + { base: [keyword('foo')], append: [keyword('bar'), CSS.px(1)], expect: null }, + { base: [keyword('foo')], append: [keyword('bar'), '1px'], expect: null }, + { base: [keyword('foo')], append: [keyword('bar'), keyword('baz')], expect: 'foo bar baz' }, + { base: [keyword('foo'), keyword('bar')], append: [keyword('baz')], expect: 'foo bar baz' }, + { base: [keyword('foo')], append: [keyword('bar'), 'baz'], expect: 'foo bar baz' }, + { base: [keyword('foo')], append: [keyword('bar'), 'baz zim'], expect: 'foo bar baz zim' }, + { base: null, append: [keyword('foo'), 'bar'], expect: 'foo bar' }, + ], +}); + +['<image>+', '<url>+'].forEach((syntax) => { + test_append({ + syntax: syntax, + initialValue: 'url(0)', + values: [ + { base: [url_image('url("1")')], append: [CSS.px(1)], expect: null }, + { base: [url_image('url("1")')], append: [url_image('url("2")'), CSS.px(1)], expect: null }, + { base: [url_image('url("1")')], append: [url_image('url("2")'), '1px'], expect: null }, + { base: [url_image('url("1")')], append: [url_image('url("2")'), url_image('url("3")')], expect: 'url("1") url("2") url("3")' }, + { base: [url_image('url("1")'), url_image('url("2")')], append: [url_image('url("3")')], expect: 'url("1") url("2") url("3")' }, + { base: [url_image('url("1")')], append: [url_image('url("2")'), 'url("3")'], expect: 'url("1") url("2") url("3")' }, + { base: [url_image('url("1")')], append: [url_image('url("2")'), 'url("3") url("4")'], expect: 'url("1") url("2") url("3") url("4")' }, + { base: null, append: [url_image('url("1")'), 'url("2")'], expect: 'url("1") url("2")' }, + ], + }); +}); + +test_append({ + syntax: '<integer>+', + initialValue: '0', + values: [ + { base: [CSS.number(1)], append: [CSS.px(1)], expect: null }, + { base: [CSS.number(1)], append: [CSS.number(2), CSS.px(1)], expect: null }, + { base: [CSS.number(1)], append: [CSS.number(2), 'noint'], expect: null }, + { base: [CSS.number(1)], append: [CSS.number(2), CSS.number(3)], expect: '1 2 3' }, + { base: [CSS.number(1), CSS.number(2)], append: [CSS.number(3)], expect: '1 2 3' }, + { base: [CSS.number(1)], append: [CSS.number(2), '3'], expect: '1 2 3' }, + { base: [CSS.number(1)], append: [CSS.number(2), '3 4'], expect: '1 2 3 4' }, + { base: null, append: [CSS.number(1), '2'], expect: '1 2' }, + ], +}); + +test_append({ + syntax: '<length-percentage>+', + initialValue: '0px', + values: [ + { base: [CSS.px(1)], append: [keyword('nolength')], expect: null }, + { base: [CSS.px(1)], append: [CSS.px(2), keyword('nolength')], expect: null }, + { base: [CSS.px(1)], append: [CSS.px(2), 'nolength'], expect: null }, + { base: [CSS.px(1)], append: [CSS.px(2), CSS.percent(3)], expect: '1px 2px 3%' }, + { base: [CSS.px(1), CSS.px(2)], append: [CSS.percent(3)], expect: '1px 2px 3%' }, + { base: [CSS.px(1)], append: [CSS.percent(2), '3px'], expect: '1px 2% 3px' }, + { base: [CSS.px(1)], append: [CSS.px(2), '3% 4px'], expect: '1px 2px 3% 4px' }, + { base: null, append: [CSS.px(1), '2%'], expect: '1px 2%' }, + ], +}); + +test_append({ + syntax: '<length>+', + initialValue: '0', + values: [ + { base: [CSS.px(1)], append: [keyword('nolength')], expect: null }, + { base: [CSS.px(1)], append: [CSS.px(2), keyword('nolength')], expect: null }, + { base: [CSS.px(1)], append: [CSS.px(2), 'nolength'], expect: null }, + { base: [CSS.px(1)], append: [CSS.em(2), CSS.px(3)], expect: '1px 2em 3px' }, + { base: [CSS.px(1), CSS.em(2)], append: [CSS.vh(3)], expect: '1px 2em 3vh' }, + { base: [CSS.px(1)], append: [CSS.em(2), '3px'], expect: '1px 2em 3px' }, + { base: [CSS.px(1)], append: [CSS.px(2), '3em 4cm'], expect: '1px 2px 3em 4cm' }, + { base: null, append: [CSS.vh(1), '2px'], expect: '1vh 2px' }, + ], +}); + +test_append({ + syntax: '<number>+', + initialValue: '0', + values: [ + { base: [CSS.number(-1)], append: [keyword('NaN')], expect: null }, + { base: [CSS.number(-1)], append: [CSS.number(2.5), keyword('NaN')], expect: null }, + { base: [CSS.number(-1)], append: [CSS.number(2.5), '1px'], expect: null }, + { base: [CSS.number(-1)], append: [CSS.number(2.5), CSS.number(3.2)], expect: '-1 2.5 3.2' }, + { base: [CSS.number(-1), CSS.number(2.5)], append: [CSS.number(3.2)], expect: '-1 2.5 3.2' }, + { base: [CSS.number(-1)], append: [CSS.number(2.5), '3.2'], expect: '-1 2.5 3.2' }, + { base: [CSS.number(-1)], append: [CSS.number(2.5), '3.2 4'], expect: '-1 2.5 3.2 4' }, + { base: null, append: [CSS.number(-1), '2.5'], expect: '-1 2.5' }, + ], +}); + +test_append({ + syntax: '<percentage>+', + initialValue: '0%', + values: [ + { base: [CSS.percent(1)], append: [CSS.px(1)], expect: null }, + { base: [CSS.percent(1)], append: [CSS.percent(2), CSS.px(1)], expect: null }, + { base: [CSS.percent(1)], append: [CSS.percent(2), '1px'], expect: null }, + { base: [CSS.percent(1)], append: [CSS.percent(2), CSS.percent(3)], expect: '1% 2% 3%' }, + { base: [CSS.percent(1), CSS.percent(2)], append: [CSS.percent(3)], expect: '1% 2% 3%' }, + { base: [CSS.percent(1)], append: [CSS.percent(2), '3%'], expect: '1% 2% 3%' }, + { base: [CSS.percent(1)], append: [CSS.percent(2), '3% 4%'], expect: '1% 2% 3% 4%' }, + { base: null, append: [CSS.percent(1), '2%'], expect: '1% 2%' }, + ], +}); + +test_append({ + syntax: '<resolution>+', + initialValue: '0dpi', + values: [ + { base: [CSS.dpi(1)], append: [CSS.px(1)], expect: null }, + { base: [CSS.dpi(1)], append: [CSS.dpi(2), CSS.px(1)], expect: null }, + { base: [CSS.dpi(1)], append: [CSS.dpi(2), '1px'], expect: null }, + { base: [CSS.dpi(1)], append: [CSS.dpi(2), CSS.dpi(3)], expect: '1dpi 2dpi 3dpi' }, + { base: [CSS.dpi(1), CSS.dpi(2)], append: [CSS.dpi(3)], expect: '1dpi 2dpi 3dpi' }, + { base: [CSS.dpi(1)], append: [CSS.dpi(2), '3dpi'], expect: '1dpi 2dpi 3dpi' }, + { base: [CSS.dpi(1)], append: [CSS.dpi(2), '3dpi 4dpi'], expect: '1dpi 2dpi 3dpi 4dpi' }, + { base: null, append: [CSS.dpi(1), '2dpi'], expect: '1dpi 2dpi' }, + ], +}); + +test_append({ + syntax: '<time>+', + initialValue: '0s', + values: [ + { base: [CSS.s(1)], append: [CSS.px(1)], expect: null }, + { base: [CSS.s(1)], append: [CSS.s(2), CSS.px(1)], expect: null }, + { base: [CSS.s(1)], append: [CSS.ms(2), '1px'], expect: null }, + { base: [CSS.s(1)], append: [CSS.ms(2), CSS.s(3)], expect: '1s 2ms 3s' }, + { base: [CSS.s(1), CSS.s(2)], append: [CSS.s(3)], expect: '1s 2s 3s' }, + { base: [CSS.s(1)], append: [CSS.s(2), '3s'], expect: '1s 2s 3s' }, + { base: [CSS.s(1)], append: [CSS.s(2), '3ms 4s'], expect: '1s 2s 3ms 4s' }, + { base: null, append: [CSS.s(1), '2s'], expect: '1s 2s' }, + ], +}); + +test_append({ + syntax: 'foo+', + initialValue: 'foo', + values: [ + { base: [keyword('foo')], append: [CSS.px(1)], expect: null }, + { base: [keyword('foo')], append: [keyword('foo'), CSS.px(1)], expect: null }, + { base: [keyword('foo')], append: [keyword('foo'), '1px'], expect: null }, + { base: [keyword('foo')], append: [keyword('foo'), keyword('foo')], expect: 'foo foo foo' }, + { base: [keyword('foo'), keyword('foo')], append: [keyword('foo')], expect: 'foo foo foo' }, + { base: [keyword('foo')], append: [keyword('foo'), 'foo'], expect: 'foo foo foo' }, + { base: [keyword('foo')], append: [keyword('foo'), 'foo foo'], expect: 'foo foo foo foo' }, + { base: null, append: [keyword('foo'), keyword('foo')], expect: 'foo foo' }, + ], }); // CSSStyleValue.parse/parseAll
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/geometry/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/geometry/interfaces-expected.txt index 757d30b..0e6decf 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/geometry/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/css/geometry/interfaces-expected.txt
@@ -29,7 +29,7 @@ PASS DOMPoint interface: existence and properties of interface object PASS DOMPoint interface object length PASS DOMPoint interface object name -FAIL DOMPoint interface: legacy window alias assert_equals: self.SVGPoint should be the same value as self.DOMPoint expected function "function DOMPoint() { [native code] }" but got function "function SVGPoint() { [native code] }" +FAIL DOMPoint interface: legacy window alias assert_equals: self.SVGPoint should be the same value as the interface object expected function "function DOMPoint() { [native code] }" but got function "function SVGPoint() { [native code] }" PASS DOMPoint interface: existence and properties of interface prototype object PASS DOMPoint interface: existence and properties of interface prototype object's "constructor" property PASS DOMPoint interface: existence and properties of interface prototype object's @@unscopables property @@ -89,7 +89,7 @@ PASS DOMRect interface: existence and properties of interface object PASS DOMRect interface object length PASS DOMRect interface object name -FAIL DOMRect interface: legacy window alias assert_equals: self.SVGRect should be the same value as self.DOMRect expected function "function DOMRect() { [native code] }" but got function "function SVGRect() { [native code] }" +FAIL DOMRect interface: legacy window alias assert_equals: self.SVGRect should be the same value as the interface object expected function "function DOMRect() { [native code] }" but got function "function SVGRect() { [native code] }" PASS DOMRect interface: existence and properties of interface prototype object PASS DOMRect interface: existence and properties of interface prototype object's "constructor" property PASS DOMRect interface: existence and properties of interface prototype object's @@unscopables property @@ -272,7 +272,7 @@ PASS DOMMatrix interface: existence and properties of interface object PASS DOMMatrix interface object length PASS DOMMatrix interface object name -FAIL DOMMatrix interface: legacy window alias assert_equals: self.SVGMatrix should be the same value as self.DOMMatrix expected function "function DOMMatrix() { [native code] }" but got function "function SVGMatrix() { [native code] }" +FAIL DOMMatrix interface: legacy window alias assert_equals: self.SVGMatrix should be the same value as the interface object expected function "function DOMMatrix() { [native code] }" but got function "function SVGMatrix() { [native code] }" PASS DOMMatrix interface: existence and properties of interface prototype object PASS DOMMatrix interface: existence and properties of interface prototype object's "constructor" property PASS DOMMatrix interface: existence and properties of interface prototype object's @@unscopables property
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt index cc031315..33ba630 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt
@@ -839,16 +839,16 @@ FAIL AbstractRange interface: attribute endContainer assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing FAIL AbstractRange interface: attribute endOffset assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing FAIL AbstractRange interface: attribute collapsed assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing -FAIL StaticRange interface: existence and properties of interface object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing +FAIL StaticRange interface: existence and properties of interface object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing PASS StaticRange interface object length PASS StaticRange interface object name -FAIL StaticRange interface: existence and properties of interface prototype object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing +FAIL StaticRange interface: existence and properties of interface prototype object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing PASS StaticRange interface: existence and properties of interface prototype object's "constructor" property PASS StaticRange interface: existence and properties of interface prototype object's @@unscopables property -FAIL Range interface: existence and properties of interface object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing +FAIL Range interface: existence and properties of interface object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing PASS Range interface object length PASS Range interface object name -FAIL Range interface: existence and properties of interface prototype object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing +FAIL Range interface: existence and properties of interface prototype object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing PASS Range interface: existence and properties of interface prototype object's "constructor" property PASS Range interface: existence and properties of interface prototype object's @@unscopables property PASS Range interface: attribute commonAncestorContainer
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/reporting/generic-sensor-reporting.https.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/reporting/generic-sensor-reporting.https.html new file mode 100644 index 0000000..c60e3e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/reporting/generic-sensor-reporting.https.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> + <head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + </head> + <body> + <script> +var sensor_features_verified = { + "accelerometer": false, + "ambient-light-sensor": false, + "magnetometer": false, + "gyroscope": false +}; + +var check_report_format = function(reports, observer) { + // Check each report in this batch. This observer callback may be called + // multiple times before all reports have been processed. + for (const report of reports) { + + // Validate that the reported feature is one of the sensor features, and that + // we have not seen a report for this feature before. + assert_true(sensor_features_verified.hasOwnProperty(report.body.feature)); + assert_false(sensor_features_verified[report.body.feature]); + + // Validate the remainder of the report + assert_equals(report.type, "feature-policy"); + assert_equals(report.url, document.location.href); + assert_equals(report.body.sourceFile, document.location.href); + assert_equals(typeof report.body.message, "string"); + assert_equals(typeof report.body.lineNumber, "number"); + assert_equals(typeof report.body.columnNumber, "number"); + + sensor_features_verified[report.body.feature] = true; + } + + // Test is only done when reports for all features have been seen + for (let result of Object.values(sensor_features_verified)) { + if (!result) + return; + } + this.done(); +}; + +async_test(t => { + new ReportingObserver(t.step_func(check_report_format), + {types: ['feature-policy']}).observe(); + assert_throws("SecurityError", () => new Accelerometer(), "Constructing sensors should be blocked by policy"); + assert_throws("SecurityError", () => new AmbientLightSensor(), "Constructing sensors should be blocked by policy"); + assert_throws("SecurityError", () => new Gyroscope(), "Constructing sensors should be blocked by policy"); + assert_throws("SecurityError", () => new Magnetometer(), "Constructing sensors should be blocked by policy"); +}, "Generic Sensor Report Format"); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/reporting/generic-sensor-reporting.https.html.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/reporting/generic-sensor-reporting.https.html.headers new file mode 100644 index 0000000..80cc027 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/reporting/generic-sensor-reporting.https.html.headers
@@ -0,0 +1 @@ +Feature-Policy: ambient-light-sensor 'none'; accelerometer 'none'; gyroscope 'none'; magnetometer 'none'
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/webrtc.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/webrtc.idl index cdeb520..7496fff4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/webrtc.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/webrtc.idl
@@ -297,6 +297,7 @@ required DOMString transactionId; required sequence<RTCRtpEncodingParameters> encodings; RTCDegradationPreference degradationPreference = "balanced"; + RTCPriorityType priority = "low"; }; dictionary RTCRtpReceiveParameters : RTCRtpParameters { @@ -314,7 +315,6 @@ octet codecPayloadType; RTCDtxStatus dtx; boolean active = true; - RTCPriorityType priority = "low"; unsigned long ptime; unsigned long maxBitrate; double maxFramerate;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js index 950df6fa..0f49a725 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -1256,6 +1256,48 @@ }); }; +/** + * Value of the LegacyNamespace extended attribute, if any. + * + * https://heycam.github.io/webidl/#LegacyNamespace + */ +IdlInterface.prototype.get_legacy_namespace = function() +{ + var legacyNamespace = this.extAttrs.find(function(attribute) { + return attribute.name === "LegacyNamespace"; + }); + return legacyNamespace ? legacyNamespace.rhs.value : undefined; +}; + +IdlInterface.prototype.get_interface_object_owner = function() +{ + var legacyNamespace = this.get_legacy_namespace(); + return legacyNamespace ? self[legacyNamespace] : self; +}; + +IdlInterface.prototype.assert_interface_object_exists = function() +{ + var owner = this.get_legacy_namespace() || "self"; + assert_own_property(self[owner], this.name, owner + " does not have own property " + format_value(this.name)); +}; + +IdlInterface.prototype.get_interface_object = function() { + if (this.has_extended_attribute("NoInterfaceObject")) { + throw new IdlHarnessError(this.name + " has no interface object due to NoInterfaceObject"); + } + + return this.get_interface_object_owner()[this.name]; +}; + +IdlInterface.prototype.get_qualified_name = function() { + // https://heycam.github.io/webidl/#qualified-name + var legacyNamespace = this.get_legacy_namespace(); + if (legacyNamespace) { + return legacyNamespace + "." + this.name; + } + return this.name; +}; + IdlInterface.prototype.has_to_json_regular_operation = function() { return this.members.some(function(m) { return m.is_to_json_regular_operation(); @@ -1436,9 +1478,8 @@ // TODO: Should we test here that the property is actually writable // etc., or trust getOwnPropertyDescriptor? - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); - var desc = Object.getOwnPropertyDescriptor(self, this.name); + this.assert_interface_object_exists(); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object_owner(), this.name); assert_false("get" in desc, "self's property " + format_value(this.name) + " should not have a getter"); assert_false("set" in desc, "self's property " + format_value(this.name) + " should not have a setter"); assert_true(desc.writable, "self's property " + format_value(this.name) + " should be writable"); @@ -1448,7 +1489,7 @@ if (this.is_callback()) { // "The internal [[Prototype]] property of an interface object for // a callback interface must be the Function.prototype object." - assert_equals(Object.getPrototypeOf(self[this.name]), Function.prototype, + assert_equals(Object.getPrototypeOf(this.get_interface_object()), Function.prototype, "prototype of self's property " + format_value(this.name) + " is not Object.prototype"); return; @@ -1478,24 +1519,19 @@ // ES6 (rev 30) 19.1.3.6: // "Else, if O has a [[Call]] internal method, then let builtinTag be // "Function"." - assert_class_string(self[this.name], "Function", "class string of " + this.name); + assert_class_string(this.get_interface_object(), "Function", "class string of " + this.name); // "The [[Prototype]] internal property of an interface object for a // non-callback interface is determined as follows:" - var prototype = Object.getPrototypeOf(self[this.name]); + var prototype = Object.getPrototypeOf(this.get_interface_object()); if (this.base) { // "* If the interface inherits from some other interface, the // value of [[Prototype]] is the interface object for that other // interface." - var has_interface_object = - !this.array - .members[this.base] - .has_extended_attribute("NoInterfaceObject"); - if (has_interface_object) { - assert_own_property(self, this.base, - 'should inherit from ' + this.base + - ', but self has no such property'); - assert_equals(prototype, self[this.base], + var inherited_interface = this.array.members[this.base]; + if (!inherited_interface.has_extended_attribute("NoInterfaceObject")) { + inherited_interface.assert_interface_object_exists(); + assert_equals(prototype, inherited_interface.get_interface_object(), 'prototype of ' + this.name + ' is not ' + this.base); } @@ -1513,12 +1549,13 @@ // // "If I was not declared with a [Constructor] extended attribute, // then throw a TypeError." + var interface_object = this.get_interface_object(); assert_throws(new TypeError(), function() { - self[this.name](); - }.bind(this), "interface object didn't throw TypeError when called as a function"); + interface_object(); + }, "interface object didn't throw TypeError when called as a function"); assert_throws(new TypeError(), function() { - new self[this.name](); - }.bind(this), "interface object didn't throw TypeError when called as a constructor"); + new interface_object(); + }, "interface object didn't throw TypeError when called as a constructor"); } }.bind(this), this.name + " interface: existence and properties of interface object"); @@ -1527,15 +1564,14 @@ // This function tests WebIDL as of 2014-10-25. // https://heycam.github.io/webidl/#es-interface-call - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); // "Interface objects for non-callback interfaces MUST have a // property named “length” with attributes { [[Writable]]: false, // [[Enumerable]]: false, [[Configurable]]: true } whose value is // a Number." - assert_own_property(self[this.name], "length"); - var desc = Object.getOwnPropertyDescriptor(self[this.name], "length"); + assert_own_property(this.get_interface_object(), "length"); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "length"); assert_false("get" in desc, this.name + ".length should not have a getter"); assert_false("set" in desc, this.name + ".length should not have a setter"); assert_false(desc.writable, this.name + ".length should not be writable"); @@ -1545,7 +1581,7 @@ var constructors = this.extAttrs .filter(function(attr) { return attr.name == "Constructor"; }); var expected_length = minOverloadLength(constructors); - assert_equals(self[this.name].length, expected_length, "wrong value for " + this.name + ".length"); + assert_equals(this.get_interface_object().length, expected_length, "wrong value for " + this.name + ".length"); }.bind(this), this.name + " interface object length"); } @@ -1554,22 +1590,21 @@ // This function tests WebIDL as of 2015-11-17. // https://heycam.github.io/webidl/#interface-object - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); // "All interface objects must have a property named “name” with // attributes { [[Writable]]: false, [[Enumerable]]: false, // [[Configurable]]: true } whose value is the identifier of the // corresponding interface." - assert_own_property(self[this.name], "name"); - var desc = Object.getOwnPropertyDescriptor(self[this.name], "name"); + assert_own_property(this.get_interface_object(), "name"); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "name"); assert_false("get" in desc, this.name + ".name should not have a getter"); assert_false("set" in desc, this.name + ".name should not have a setter"); assert_false(desc.writable, this.name + ".name should not be writable"); assert_false(desc.enumerable, this.name + ".name should not be enumerable"); assert_true(desc.configurable, this.name + ".name should be configurable"); - assert_equals(self[this.name].name, this.name, "wrong value for " + this.name + ".name"); + assert_equals(this.get_interface_object().name, this.name, "wrong value for " + this.name + ".name"); }.bind(this), this.name + " interface object name"); } @@ -1608,9 +1643,9 @@ if (exposed_in(exposure_set(this, this.exposureSet)) && 'document' in self) { for (alias of aliases) { assert_true(alias in self, alias + " should exist"); - assert_equals(self[alias], self[this.name], "self." + alias + " should be the same value as self." + this.name); + assert_equals(self[alias], this.get_interface_object(), "self." + alias + " should be the same value as the interface object"); var desc = Object.getOwnPropertyDescriptor(self, alias); - assert_equals(desc.value, self[this.name], "wrong value in " + alias + " property descriptor"); + assert_equals(desc.value, this.get_interface_object(), "wrong value in " + alias + " property descriptor"); assert_true(desc.writable, alias + " should be writable"); assert_false(desc.enumerable, alias + " should not be enumerable"); assert_true(desc.configurable, alias + " should be configurable"); @@ -1636,11 +1671,10 @@ return; } - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); if (this.is_callback()) { - assert_false("prototype" in self[this.name], + assert_false("prototype" in this.get_interface_object(), this.name + ' should not have a "prototype" property'); return; } @@ -1652,9 +1686,9 @@ // properties that correspond to the regular attributes and regular // operations defined on the interface, and is described in more detail // in section 4.5.4 below." - assert_own_property(self[this.name], "prototype", + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); - var desc = Object.getOwnPropertyDescriptor(self[this.name], "prototype"); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "prototype"); assert_false("get" in desc, this.name + ".prototype should not have a getter"); assert_false("set" in desc, this.name + ".prototype should not have a setter"); assert_false(desc.writable, this.name + ".prototype should not be writable"); @@ -1687,38 +1721,39 @@ // object %ErrorPrototype%." // if (this.name === "Window") { - assert_class_string(Object.getPrototypeOf(self[this.name].prototype), + assert_class_string(Object.getPrototypeOf(this.get_interface_object().prototype), 'WindowProperties', 'Class name for prototype of Window' + '.prototype is not "WindowProperties"'); } else { - var inherit_interface, inherit_interface_has_interface_object; + var inherit_interface, inherit_interface_interface_object; if (this.base) { inherit_interface = this.base; - inherit_interface_has_interface_object = - !this.array - .members[inherit_interface] - .has_extended_attribute("NoInterfaceObject"); + var parent = this.array.members[inherit_interface]; + if (!parent.has_extended_attribute("NoInterfaceObject")) { + parent.assert_interface_object_exists(); + inherit_interface_interface_object = parent.get_interface_object(); + } } else if (this.name === "DOMException") { inherit_interface = 'Error'; - inherit_interface_has_interface_object = true; + inherit_interface_interface_object = self.Error; } else { inherit_interface = 'Object'; - inherit_interface_has_interface_object = true; + inherit_interface_interface_object = self.Object; } - if (inherit_interface_has_interface_object) { - assert_own_property(self, inherit_interface, - 'should inherit from ' + inherit_interface + ', but self has no such property'); - assert_own_property(self[inherit_interface], 'prototype', + if (inherit_interface_interface_object) { + assert_not_equals(inherit_interface_interface_object, undefined, + 'should inherit from ' + inherit_interface + ', but there is no such property'); + assert_own_property(inherit_interface_interface_object, 'prototype', 'should inherit from ' + inherit_interface + ', but that object has no "prototype" property'); - assert_equals(Object.getPrototypeOf(self[this.name].prototype), - self[inherit_interface].prototype, + assert_equals(Object.getPrototypeOf(this.get_interface_object().prototype), + inherit_interface_interface_object.prototype, 'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype'); } else { // We can't test that we get the correct object, because this is the // only way to get our hands on it. We only test that its class // string, at least, is correct. - assert_class_string(Object.getPrototypeOf(self[this.name].prototype), + assert_class_string(Object.getPrototypeOf(this.get_interface_object().prototype), inherit_interface + 'Prototype', 'Class name for prototype of ' + this.name + '.prototype is not "' + inherit_interface + 'Prototype"'); @@ -1726,20 +1761,20 @@ } // "The class string of an interface prototype object is the - // concatenation of the interface’s identifier and the string + // concatenation of the interface’s qualified identifier and the string // “Prototype”." // Skip these tests for now due to a specification issue about // prototype name. // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244 - // assert_class_string(self[this.name].prototype, this.name + "Prototype", + // assert_class_string(this.get_interface_object().prototype, this.get_qualified_name() + "Prototype", // "class string of " + this.name + ".prototype"); // String() should end up calling {}.toString if nothing defines a // stringifier. if (!this.has_stringifier()) { - // assert_equals(String(self[this.name].prototype), "[object " + this.name + "Prototype]", + // assert_equals(String(this.get_interface_object().prototype), "[object " + this.get_qualified_name() + "Prototype]", // "String(" + this.name + ".prototype)"); } }.bind(this), this.name + " interface: existence and properties of interface prototype object"); @@ -1751,7 +1786,7 @@ // prototype exotic object." // https://heycam.github.io/webidl/#interface-prototype-object if (this.is_global()) { - this.test_immutable_prototype("interface prototype object", self[this.name].prototype); + this.test_immutable_prototype("interface prototype object", this.get_interface_object().prototype); } subsetTestByKey(this.name, test, function() @@ -1760,16 +1795,15 @@ return; } - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); if (this.is_callback()) { - assert_false("prototype" in self[this.name], + assert_false("prototype" in this.get_interface_object(), this.name + ' should not have a "prototype" property'); return; } - assert_own_property(self[this.name], "prototype", + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); // "If the [NoInterfaceObject] extended attribute was not specified on @@ -1777,15 +1811,15 @@ // property named “constructor” with attributes { [[Writable]]: true, // [[Enumerable]]: false, [[Configurable]]: true } whose value is a // reference to the interface object for the interface." - assert_own_property(self[this.name].prototype, "constructor", + assert_own_property(this.get_interface_object().prototype, "constructor", this.name + '.prototype does not have own property "constructor"'); - var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, "constructor"); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, "constructor"); assert_false("get" in desc, this.name + ".prototype.constructor should not have a getter"); assert_false("set" in desc, this.name + ".prototype.constructor should not have a setter"); assert_true(desc.writable, this.name + ".prototype.constructor should be writable"); assert_false(desc.enumerable, this.name + ".prototype.constructor should not be enumerable"); assert_true(desc.configurable, this.name + ".prototype.constructor should be configurable"); - assert_equals(self[this.name].prototype.constructor, self[this.name], + assert_equals(this.get_interface_object().prototype.constructor, this.get_interface_object(), this.name + '.prototype.constructor is not the same object as ' + this.name); }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property'); @@ -1796,16 +1830,15 @@ return; } - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); if (this.is_callback()) { - assert_false("prototype" in self[this.name], + assert_false("prototype" in this.get_interface_object(), this.name + ' should not have a "prototype" property'); return; } - assert_own_property(self[this.name], "prototype", + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); // If the interface has any member declared with the [Unscopable] extended @@ -1814,7 +1847,7 @@ // { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }, // and whose value is an object created as follows... var unscopables = this.get_unscopables().map(m => m.name); - var proto = self[this.name].prototype; + var proto = this.get_interface_object().prototype; if (unscopables.length != 0) { assert_own_property( proto, Symbol.unscopables, @@ -1845,7 +1878,7 @@ this.name + '.prototype[Symbol.unscopables] has unexpected property "' + prop + '"'); } } else { - assert_equals(Object.getOwnPropertyDescriptor(self[this.name].prototype, Symbol.unscopables), + assert_equals(Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.unscopables), undefined, this.name + '.prototype should not have @@unscopables'); } @@ -1962,21 +1995,20 @@ subsetTestByKey(this.name, test, function() { - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); // "For each constant defined on an interface A, there must be // a corresponding property on the interface object, if it // exists." - assert_own_property(self[this.name], member.name); + assert_own_property(this.get_interface_object(), member.name); // "The value of the property is that which is obtained by // converting the constant’s IDL value to an ECMAScript // value." - assert_equals(self[this.name][member.name], constValue(member.value), + assert_equals(this.get_interface_object()[member.name], constValue(member.value), "property has wrong value"); // "The property has attributes { [[Writable]]: false, // [[Enumerable]]: true, [[Configurable]]: false }." - var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), member.name); assert_false("get" in desc, "property should not have a getter"); assert_false("set" in desc, "property should not have a setter"); assert_false(desc.writable, "property should not be writable"); @@ -1988,22 +2020,21 @@ // exist on the interface prototype object." subsetTestByKey(this.name, test, function() { - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); if (this.is_callback()) { - assert_false("prototype" in self[this.name], + assert_false("prototype" in this.get_interface_object(), this.name + ' should not have a "prototype" property'); return; } - assert_own_property(self[this.name], "prototype", + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); - assert_own_property(self[this.name].prototype, member.name); - assert_equals(self[this.name].prototype[member.name], constValue(member.value), + assert_own_property(this.get_interface_object().prototype, member.name); + assert_equals(this.get_interface_object().prototype[member.name], constValue(member.value), "property has wrong value"); - var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name); + var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), member.name); assert_false("get" in desc, "property should not have a getter"); assert_false("set" in desc, "property should not have a setter"); assert_false(desc.writable, "property should not be writable"); @@ -2026,13 +2057,12 @@ return; } - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); - assert_own_property(self[this.name], "prototype", + this.assert_interface_object_exists(); + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); if (member["static"]) { - assert_own_property(self[this.name], member.name, + assert_own_property(this.get_interface_object(), member.name, "The interface object must have a property " + format_value(member.name)); a_test.done(); @@ -2045,7 +2075,7 @@ assert_own_property(self, member.name, "The global object must have a property " + format_value(member.name)); - assert_false(member.name in self[this.name].prototype, + assert_false(member.name in this.get_interface_object().prototype, "The prototype object should not have a property " + format_value(member.name)); @@ -2073,34 +2103,34 @@ // since it will call done() on a_test. this.do_interface_attribute_asserts(self, member, a_test); } else { - assert_true(member.name in self[this.name].prototype, + assert_true(member.name in this.get_interface_object().prototype, "The prototype object must have a property " + format_value(member.name)); if (!member.has_extended_attribute("LenientThis")) { if (member.idlType.generic !== "Promise") { assert_throws(new TypeError(), function() { - self[this.name].prototype[member.name]; + this.get_interface_object().prototype[member.name]; }.bind(this), "getting property on prototype object must throw TypeError"); // do_interface_attribute_asserts must be the last thing we // do, since it will call done() on a_test. - this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test); + this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test); } else { promise_rejects(a_test, new TypeError(), - self[this.name].prototype[member.name]) + this.get_interface_object().prototype[member.name]) .then(function() { // do_interface_attribute_asserts must be the last // thing we do, since it will call done() on a_test. - this.do_interface_attribute_asserts(self[this.name].prototype, + this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test); }.bind(this)); } } else { - assert_equals(self[this.name].prototype[member.name], undefined, + assert_equals(this.get_interface_object().prototype[member.name], undefined, "getting property on prototype object must return undefined"); // do_interface_attribute_asserts must be the last thing we do, // since it will call done() on a_test. - this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test); + this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test); } } }.bind(this)); @@ -2125,17 +2155,16 @@ return; } - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); if (this.is_callback()) { - assert_false("prototype" in self[this.name], + assert_false("prototype" in this.get_interface_object(), this.name + ' should not have a "prototype" property'); a_test.done(); return; } - assert_own_property(self[this.name], "prototype", + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); // "For each unique identifier of an exposed operation defined on the @@ -2150,9 +2179,9 @@ // "* If the operation is static, then the property exists on the // interface object." if (member["static"]) { - assert_own_property(self[this.name], member.name, + assert_own_property(this.get_interface_object(), member.name, "interface object missing static operation"); - memberHolderObject = self[this.name]; + memberHolderObject = this.get_interface_object(); // "* Otherwise, [...] if the interface was declared with the [Global] // extended attribute, then the property exists // on every object that implements the interface." @@ -2163,9 +2192,9 @@ // "* Otherwise, the property exists solely on the interface’s // interface prototype object." } else { - assert_own_property(self[this.name].prototype, member.name, + assert_own_property(this.get_interface_object().prototype, member.name, "interface prototype object missing non-static operation"); - memberHolderObject = self[this.name].prototype; + memberHolderObject = this.get_interface_object().prototype; } this.do_member_unscopable_asserts(member); this.do_member_operation_asserts(memberHolderObject, member, a_test); @@ -2180,7 +2209,7 @@ return; } - var unscopables = self[this.name].prototype[Symbol.unscopables]; + var unscopables = this.get_interface_object().prototype[Symbol.unscopables]; var prop = member.name; var propDesc = Object.getOwnPropertyDescriptor(unscopables, prop); assert_equals(typeof propDesc, "object", @@ -2308,27 +2337,26 @@ IdlInterface.prototype.test_member_iterable = function(member) { - var interfaceName = this.name; var isPairIterator = member.idlType.length === 2; subsetTestByKey(this.name, test, function() { - var descriptor = Object.getOwnPropertyDescriptor(self[interfaceName].prototype, Symbol.iterator); + var descriptor = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.iterator); assert_true(descriptor.writable, "property should be writable"); assert_true(descriptor.configurable, "property should be configurable"); assert_false(descriptor.enumerable, "property should not be enumerable"); - assert_equals(self[interfaceName].prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name"); - }, "Testing Symbol.iterator property of iterable interface " + interfaceName); + assert_equals(this.get_interface_object().prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name"); + }.bind(this), "Testing Symbol.iterator property of iterable interface " + this.name); if (isPairIterator) { subsetTestByKey(this.name, test, function() { - assert_equals(self[interfaceName].prototype[Symbol.iterator], self[interfaceName].prototype["entries"], "entries method is not the same as @@iterator"); - }, "Testing pair iterable interface " + interfaceName); + assert_equals(this.get_interface_object().prototype[Symbol.iterator], this.get_interface_object().prototype["entries"], "entries method is not the same as @@iterator"); + }.bind(this), "Testing pair iterable interface " + this.name); } else { subsetTestByKey(this.name, test, function() { ["entries", "keys", "values", "forEach", Symbol.Iterator].forEach(function(property) { - assert_equals(self[interfaceName].prototype[property], Array.prototype[property], property + " function is not the same as Array one"); - }); - }, "Testing value iterable interface " + interfaceName); + assert_equals(this.get_interface_object().prototype[property], Array.prototype[property], property + " function is not the same as Array one"); + }.bind(this)); + }.bind(this), "Testing value iterable interface " + this.name); } }; @@ -2340,21 +2368,20 @@ return; } - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); + this.assert_interface_object_exists(); if (this.is_callback()) { - assert_false("prototype" in self[this.name], + assert_false("prototype" in this.get_interface_object(), this.name + ' should not have a "prototype" property'); return; } - assert_own_property(self[this.name], "prototype", + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); // ". . . the property exists on the interface prototype object." - var interfacePrototypeObject = self[this.name].prototype; - assert_own_property(self[this.name].prototype, "toString", + var interfacePrototypeObject = this.get_interface_object().prototype; + assert_own_property(interfacePrototypeObject, "toString", "interface prototype object missing non-static operation"); var stringifierUnforgeable = member.isUnforgeable; @@ -2380,7 +2407,7 @@ // "Let O be the result of calling ToObject on the this value." assert_throws(new TypeError(), function() { - self[this.name].prototype.toString.apply(null, []); + interfacePrototypeObject.toString.apply(null, []); }, "calling stringifier with this = null didn't throw TypeError"); // "If O is not an object that implements the interface on which the @@ -2389,7 +2416,7 @@ // TODO: Test a platform object that implements some other // interface. (Have to be sure to get inheritance right.) assert_throws(new TypeError(), function() { - self[this.name].prototype.toString.apply({}, []); + interfacePrototypeObject.toString.apply({}, []); }, "calling stringifier with this = {} didn't throw TypeError"); }.bind(this), this.name + " interface: stringifier"); }; @@ -2419,10 +2446,10 @@ if (!exposed_in(exposure_set(member, this.exposureSet))) { subsetTestByKey(this.name, test, function() { // It's not exposed, so we shouldn't find it anywhere. - assert_false(member.name in self[this.name], + assert_false(member.name in this.get_interface_object(), "The interface object must not have a property " + format_value(member.name)); - assert_false(member.name in self[this.name].prototype, + assert_false(member.name in this.get_interface_object().prototype, "The prototype object must not have a property " + format_value(member.name)); }.bind(this), this.name + " interface: member " + member.name); @@ -2538,9 +2565,8 @@ { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - assert_own_property(self, this.name, - "self does not have own property " + format_value(this.name)); - assert_own_property(self[this.name], "prototype", + this.assert_interface_object_exists(); + assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); // "The value of the internal [[Prototype]] property of the @@ -2548,22 +2574,22 @@ // interface from the platform object’s associated global // environment." assert_equals(Object.getPrototypeOf(obj), - self[this.name].prototype, + this.get_interface_object().prototype, desc + "'s prototype is not " + this.name + ".prototype"); }.bind(this), this.name + " must be primary interface of " + desc); } // "The class string of a platform object that implements one or more - // interfaces must be the identifier of the primary interface of the + // interfaces must be the qualified name of the primary interface of the // platform object." subsetTestByKey(this.name, test, function() { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - assert_class_string(obj, this.name, "class string of " + desc); + assert_class_string(obj, this.get_qualified_name(), "class string of " + desc); if (!this.has_stringifier()) { - assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")"); + assert_equals(String(obj), "[object " + this.get_qualified_name() + "]", "String(" + desc + ")"); } }.bind(this), "Stringification of " + desc); };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/service-worker-header.py b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/service-worker-header.py index 2e82e78..74f57a72a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/service-worker-header.py +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/service-worker-header.py
@@ -1,7 +1,20 @@ def main(request, response): service_worker_header = request.headers.get('service-worker') - if service_worker_header == 'script': - body = '// Request has `Service-Worker: script` header' - return 200, [('Content-Type', 'application/javascript')], body - else: + + if 'header' in request.GET and service_worker_header != 'script': return 400, [('Content-Type', 'text/plain')], 'Bad Request' + + if 'no-header' in request.GET and service_worker_header == 'script': + return 400, [('Content-Type', 'text/plain')], 'Bad Request' + + # no-cache itself to ensure the user agent finds a new version for each + # update. + headers = [('Cache-Control', 'no-cache, must-revalidate'), + ('Pragma', 'no-cache'), + ('Content-Type', 'application/javascript')] + body = '/* This is a service worker script */\n' + + if 'import' in request.GET: + body += "importScripts('%s');" % request.GET['import'] + + return 200, headers, body
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/service-worker-header.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/service-worker-header.https.html index 2584485..fb902cd1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/service-worker-header.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/service-worker-header.https.html
@@ -5,14 +5,19 @@ <script src="resources/test-helpers.sub.js"></script> <script> -promise_test(t => { - const script = 'resources/service-worker-header.py'; +promise_test(async t => { + const script = 'resources/service-worker-header.py' + + '?header&import=service-worker-header.py?no-header'; const scope = 'resources/service-worker-header'; - return service_worker_unregister_and_register(t, script, scope) - .then(registration => { - assert_true(registration instanceof ServiceWorkerRegistration); - return registration.unregister(); - }); -}, 'A request to fetch service worker script should have Service-Worker header'); + const expected_url = normalizeURL(script); + const registration = + await service_worker_unregister_and_register(t, script, scope); + t.add_cleanup(() => registration.unregister()); + assert_true(registration instanceof ServiceWorkerRegistration); + + await wait_for_state(t, registration.installing, 'activated'); + await registration.update(); +}, 'A request to fetch service worker main script should have Service-Worker ' + + 'header and imported scripts should not have one'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/shape-detection/idlharness.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/shape-detection/idlharness.any-expected.txt index 24c61932..d6bc9aa 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/shape-detection/idlharness.any-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/shape-detection/idlharness.any-expected.txt
@@ -7,7 +7,9 @@ PASS FaceDetector interface: existence and properties of interface prototype object's "constructor" property PASS FaceDetector interface: existence and properties of interface prototype object's @@unscopables property PASS FaceDetector interface: operation detect(ImageBitmapSource) -FAIL DetectedFace interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function () { [native code] }" did not throw +FAIL DetectedFace interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function() { + new interface_object(); + }" did not throw PASS DetectedFace interface object length PASS DetectedFace interface object name PASS DetectedFace interface: existence and properties of interface prototype object @@ -23,7 +25,9 @@ PASS BarcodeDetector interface: existence and properties of interface prototype object's @@unscopables property FAIL BarcodeDetector interface: attribute supportedFormats assert_true: The prototype object must have a property "supportedFormats" expected true got false PASS BarcodeDetector interface: operation detect(ImageBitmapSource) -FAIL DetectedBarcode interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function () { [native code] }" did not throw +FAIL DetectedBarcode interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function() { + new interface_object(); + }" did not throw PASS DetectedBarcode interface object length PASS DetectedBarcode interface object name PASS DetectedBarcode interface: existence and properties of interface prototype object
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/idlharness.any.js deleted file mode 100644 index 9c29ad1..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/wasm/idlharness.any.js +++ /dev/null
@@ -1,33 +0,0 @@ -// META: script=/resources/WebIDLParser.js -// META: script=/resources/idlharness.js -// META: script=resources/load_wasm.js - -'use strict'; - -// https://webassembly.github.io/spec/js-api/ - -promise_test(async () => { - const srcs = ['wasm-js-api']; - const [wasm] = await Promise.all( - srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text()))); - - const idl_array = new IdlArray(); - idl_array.add_idls(wasm); - // Ignored errors are surfaced in idlharness.js's test_object below. - try { - self.memory = new Memory({initial: 1024}); - } catch (e) { } - - try { - self.mod = await createWasmModule(); - self.instance = new Instance(self.mod); - } catch (e) { } - - idl_array.add_objects({ - Memory: ['memory'], - Module: ['mod'], - Instance: ['instance'], - }); - idl_array.test(); -}, 'wasm-js-api interfaces.'); -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any-expected.txt new file mode 100644 index 0000000..d120c0a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any-expected.txt
@@ -0,0 +1,69 @@ +This is a testharness.js-based test. +Found 63 tests; 46 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS wasm-js-api interfaces. +FAIL WebAssembly namespace: operation validate(BufferSource) assert_true: property should be enumerable expected true got false +FAIL WebAssembly namespace: operation compile(BufferSource) assert_true: property should be enumerable expected true got false +FAIL WebAssembly namespace: operation instantiate(BufferSource, object) assert_true: property should be enumerable expected true got false +FAIL WebAssembly namespace: operation instantiate(Module, object) assert_true: property should be enumerable expected true got false +PASS Module interface: existence and properties of interface object +PASS Module interface object length +PASS Module interface object name +PASS Module interface: existence and properties of interface prototype object +PASS Module interface: existence and properties of interface prototype object's "constructor" property +PASS Module interface: existence and properties of interface prototype object's @@unscopables property +FAIL Module interface: operation exports(Module) assert_true: property should be enumerable expected true got false +FAIL Module interface: operation imports(Module) assert_true: property should be enumerable expected true got false +FAIL Module interface: operation customSections(Module, USVString) assert_true: property should be enumerable expected true got false +PASS Module must be primary interface of mod +PASS Stringification of mod +PASS Module interface: mod must inherit property "exports(Module)" with the proper type +PASS Module interface: calling exports(Module) on mod with too few arguments must throw TypeError +PASS Module interface: mod must inherit property "imports(Module)" with the proper type +PASS Module interface: calling imports(Module) on mod with too few arguments must throw TypeError +PASS Module interface: mod must inherit property "customSections(Module, USVString)" with the proper type +PASS Module interface: calling customSections(Module, USVString) on mod with too few arguments must throw TypeError +PASS Instance interface: existence and properties of interface object +PASS Instance interface object length +PASS Instance interface object name +PASS Instance interface: existence and properties of interface prototype object +PASS Instance interface: existence and properties of interface prototype object's "constructor" property +PASS Instance interface: existence and properties of interface prototype object's @@unscopables property +FAIL Instance interface: attribute exports assert_true: property should be enumerable expected true got false +PASS Instance must be primary interface of instance +PASS Stringification of instance +PASS Instance interface: instance must inherit property "exports" with the proper type +PASS Memory interface: existence and properties of interface object +PASS Memory interface object length +PASS Memory interface object name +PASS Memory interface: existence and properties of interface prototype object +PASS Memory interface: existence and properties of interface prototype object's "constructor" property +PASS Memory interface: existence and properties of interface prototype object's @@unscopables property +FAIL Memory interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false +FAIL Memory interface: attribute buffer assert_true: property should be enumerable expected true got false +PASS Memory must be primary interface of memory +PASS Stringification of memory +PASS Memory interface: memory must inherit property "grow(unsigned long)" with the proper type +FAIL Memory interface: calling grow(unsigned long) on memory with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function() { + fn.apply(obj, args); + }" did not throw +PASS Memory interface: memory must inherit property "buffer" with the proper type +PASS Table interface: existence and properties of interface object +PASS Table interface object length +PASS Table interface object name +PASS Table interface: existence and properties of interface prototype object +PASS Table interface: existence and properties of interface prototype object's "constructor" property +PASS Table interface: existence and properties of interface prototype object's @@unscopables property +FAIL Table interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false +FAIL Table interface: operation get(unsigned long) assert_true: property should be enumerable expected true got false +FAIL Table interface: operation set(unsigned long, Function) assert_true: property should be enumerable expected true got false +FAIL Table interface: attribute length assert_true: property should be enumerable expected true got false +PASS Global interface: existence and properties of interface object +PASS Global interface object length +PASS Global interface object name +PASS Global interface: existence and properties of interface prototype object +PASS Global interface: existence and properties of interface prototype object's "constructor" property +PASS Global interface: existence and properties of interface prototype object's @@unscopables property +FAIL Global interface: operation valueOf() assert_true: property should be enumerable expected true got false +FAIL Global interface: attribute value assert_true: property should be enumerable expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any.js new file mode 100644 index 0000000..25298d3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any.js
@@ -0,0 +1,40 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: script=../resources/load_wasm.js + +'use strict'; + +// https://webassembly.github.io/spec/js-api/ + +promise_test(async () => { + const srcs = ['wasm-js-api']; + const [wasm] = await Promise.all( + srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text()))); + + const idl_array = new IdlArray(); + idl_array.add_idls(wasm, { + // Note the prose requirements in the specification. + except: ['CompileError', 'LinkError', 'RuntimeError'] + }); + + // https://github.com/web-platform-tests/wpt/issues/12850 + idl_array.add_untested_idls('[Exposed=(Window,Worker)] interface ArrayBuffer {};'); + + // Ignored errors are surfaced in idlharness.js's test_object below. + try { + self.memory = new WebAssembly.Memory({initial: 1024}); + } catch (e) { } + + try { + self.mod = await createWasmModule(); + self.instance = new WebAssembly.Instance(self.mod); + } catch (e) { } + + idl_array.add_objects({ + Memory: ['memory'], + Module: ['mod'], + Instance: ['instance'], + }); + idl_array.test(); +}, 'wasm-js-api interfaces.'); +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any.worker-expected.txt new file mode 100644 index 0000000..d120c0a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/idlharness.any.worker-expected.txt
@@ -0,0 +1,69 @@ +This is a testharness.js-based test. +Found 63 tests; 46 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS wasm-js-api interfaces. +FAIL WebAssembly namespace: operation validate(BufferSource) assert_true: property should be enumerable expected true got false +FAIL WebAssembly namespace: operation compile(BufferSource) assert_true: property should be enumerable expected true got false +FAIL WebAssembly namespace: operation instantiate(BufferSource, object) assert_true: property should be enumerable expected true got false +FAIL WebAssembly namespace: operation instantiate(Module, object) assert_true: property should be enumerable expected true got false +PASS Module interface: existence and properties of interface object +PASS Module interface object length +PASS Module interface object name +PASS Module interface: existence and properties of interface prototype object +PASS Module interface: existence and properties of interface prototype object's "constructor" property +PASS Module interface: existence and properties of interface prototype object's @@unscopables property +FAIL Module interface: operation exports(Module) assert_true: property should be enumerable expected true got false +FAIL Module interface: operation imports(Module) assert_true: property should be enumerable expected true got false +FAIL Module interface: operation customSections(Module, USVString) assert_true: property should be enumerable expected true got false +PASS Module must be primary interface of mod +PASS Stringification of mod +PASS Module interface: mod must inherit property "exports(Module)" with the proper type +PASS Module interface: calling exports(Module) on mod with too few arguments must throw TypeError +PASS Module interface: mod must inherit property "imports(Module)" with the proper type +PASS Module interface: calling imports(Module) on mod with too few arguments must throw TypeError +PASS Module interface: mod must inherit property "customSections(Module, USVString)" with the proper type +PASS Module interface: calling customSections(Module, USVString) on mod with too few arguments must throw TypeError +PASS Instance interface: existence and properties of interface object +PASS Instance interface object length +PASS Instance interface object name +PASS Instance interface: existence and properties of interface prototype object +PASS Instance interface: existence and properties of interface prototype object's "constructor" property +PASS Instance interface: existence and properties of interface prototype object's @@unscopables property +FAIL Instance interface: attribute exports assert_true: property should be enumerable expected true got false +PASS Instance must be primary interface of instance +PASS Stringification of instance +PASS Instance interface: instance must inherit property "exports" with the proper type +PASS Memory interface: existence and properties of interface object +PASS Memory interface object length +PASS Memory interface object name +PASS Memory interface: existence and properties of interface prototype object +PASS Memory interface: existence and properties of interface prototype object's "constructor" property +PASS Memory interface: existence and properties of interface prototype object's @@unscopables property +FAIL Memory interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false +FAIL Memory interface: attribute buffer assert_true: property should be enumerable expected true got false +PASS Memory must be primary interface of memory +PASS Stringification of memory +PASS Memory interface: memory must inherit property "grow(unsigned long)" with the proper type +FAIL Memory interface: calling grow(unsigned long) on memory with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function() { + fn.apply(obj, args); + }" did not throw +PASS Memory interface: memory must inherit property "buffer" with the proper type +PASS Table interface: existence and properties of interface object +PASS Table interface object length +PASS Table interface object name +PASS Table interface: existence and properties of interface prototype object +PASS Table interface: existence and properties of interface prototype object's "constructor" property +PASS Table interface: existence and properties of interface prototype object's @@unscopables property +FAIL Table interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false +FAIL Table interface: operation get(unsigned long) assert_true: property should be enumerable expected true got false +FAIL Table interface: operation set(unsigned long, Function) assert_true: property should be enumerable expected true got false +FAIL Table interface: attribute length assert_true: property should be enumerable expected true got false +PASS Global interface: existence and properties of interface object +PASS Global interface object length +PASS Global interface object name +PASS Global interface: existence and properties of interface prototype object +PASS Global interface: existence and properties of interface prototype object's "constructor" property +PASS Global interface: existence and properties of interface prototype object's @@unscopables property +FAIL Global interface: operation valueOf() assert_true: property should be enumerable expected true got false +FAIL Global interface: attribute value assert_true: property should be enumerable expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/resources/load_wasm.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/resources/load_wasm.js index 5123246..8316dcfb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/wasm/resources/load_wasm.js +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/resources/load_wasm.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. function createWasmModule() { - return fetch('incrementer.wasm') + return fetch('/wasm/incrementer.wasm') .then(response => { if (!response.ok) throw new Error(response.statusText); return response.arrayBuffer();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-reuse.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-reuse.html new file mode 100644 index 0000000..dabe323 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-reuse.html
@@ -0,0 +1,36 @@ +<!doctype html> +<meta charset="utf-8"> +<title>AudioBuffer can be reused between AudioBufferSourceNodes</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +function render_audio_context() { + let sampleRate = 44100; + let context = new OfflineAudioContext( + 2, sampleRate * 0.1, sampleRate); + let buf = context.createBuffer(1, 0.1 * sampleRate, context.sampleRate); + let data = buf.getChannelData(0); + data[0] = 0.5; + data[1] = 0.25; + let b1 = context.createBufferSource(); + b1.buffer = buf; + b1.start(); + let b2 = context.createBufferSource(); + b2.buffer = buf; + b2.start(); + let merger = context.createChannelMerger(2); + b1.connect(merger, 0, 0); + b2.connect(merger, 0, 1); + merger.connect(context.destination); + return context.startRendering(); +} +promise_test(function() { + return render_audio_context() + .then(function(buffer) { + assert_equals(buffer.getChannelData(0)[0], 0.5); + assert_equals(buffer.getChannelData(1)[0], 0.5); + assert_equals(buffer.getChannelData(0)[1], 0.25); + assert_equals(buffer.getChannelData(1)[1], 0.25); + }); +}, "AudioBuffer can be reused between AudioBufferSourceNodes"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt index 2730fbb3..794763f8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -321,7 +321,9 @@ FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "getRemoteCertificates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onerror" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL RTCIceTransport interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function () { [native code] }" did not throw +FAIL RTCIceTransport interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function() { + new interface_object(); + }" did not throw PASS RTCIceTransport interface object length PASS RTCIceTransport interface object name PASS RTCIceTransport interface: existence and properties of interface prototype object
diff --git a/third_party/WebKit/LayoutTests/html/dialog/dialog-show-modal-inert-crash.html b/third_party/WebKit/LayoutTests/html/dialog/dialog-show-modal-inert-crash.html new file mode 100644 index 0000000..6e10a36 --- /dev/null +++ b/third_party/WebKit/LayoutTests/html/dialog/dialog-show-modal-inert-crash.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<iframe id="frame"></iframe> +<script> + async_test(function(t) { + onload = t.step_func(() => { + const host = document.createElement("div"); + frame.appendChild(host); + frame.contentDocument.body.innerHTML = "<dialog></dialog>"; + document.body.offsetTop; + const root = host.createShadowRoot(); + root.innerHTML = "<content>"; + const dialog = frame.contentDocument.querySelector("dialog"); + dialog.showModal(); + t.done(); + }); + }, "Dialog.showModal() called when we have a dirty shadow distribution should not crash."); +</script>
diff --git a/third_party/WebKit/LayoutTests/html/dialog/showmodal-shadow-sibling-frame-crash-expected.txt b/third_party/WebKit/LayoutTests/html/dialog/showmodal-shadow-sibling-frame-crash-expected.txt new file mode 100644 index 0000000..2b0564d --- /dev/null +++ b/third_party/WebKit/LayoutTests/html/dialog/showmodal-shadow-sibling-frame-crash-expected.txt
@@ -0,0 +1,4 @@ +CONSOLE WARNING: line 24: document.registerElement is deprecated and will be removed in M73, around March 2019. Please use window.customElements.define instead. See https://www.chromestatus.com/features/4642138092470272 for more details. +CONSOLE WARNING: line 16: Element.createShadowRoot is deprecated and will be removed in M73, around March 2019. Please use Element.attachShadow instead. See https://www.chromestatus.com/features/4507242028072960 for more details. +Test for crash crbug.com/804047 Show custom dialog element +
diff --git a/third_party/WebKit/LayoutTests/html/dialog/showmodal-shadow-sibling-frame-crash.html b/third_party/WebKit/LayoutTests/html/dialog/showmodal-shadow-sibling-frame-crash.html new file mode 100644 index 0000000..134634a --- /dev/null +++ b/third_party/WebKit/LayoutTests/html/dialog/showmodal-shadow-sibling-frame-crash.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> +<body> +Test for crash crbug.com/804047 <button>Show custom dialog element</button> + +<template id="dialog"> + <custom-dialog></custom-dialog> +</template> +<div></div> +<iframe></iframe> + +<script> +var customDialogProto = Object.create(HTMLElement.prototype); + +customDialogProto.createdCallback = function() { + const shadowRoot = this.createShadowRoot(); + shadowRoot.innerHTML = '<dialog></dialog>'; +}; + +customDialogProto.show = function() { + this.shadowRoot.querySelector('dialog').showModal(); +}; + +document.registerElement('custom-dialog', { prototype: customDialogProto }); + +document.body.querySelector('button').addEventListener('click', function() { + const template = document.querySelector('#dialog'); + const custom = document.importNode(template.content, true); + const dialog = custom.querySelector('custom-dialog'); + document.querySelector('div').appendChild(dialog); + dialog.show(); +}); + +if (window.testRunner) { + testRunner.dumpAsText(); + + let absoluteTop = 0; + let absoluteLeft = 0; + const element = document.body.querySelector('button'); + for (let parent = element; parent; parent = parent.offsetParent) { + absoluteLeft += parent.offsetLeft; + absoluteTop += parent.offsetTop; + } + + const x = absoluteLeft + element.offsetWidth / 2; + const y = absoluteTop + element.offsetHeight / 2; + eventSender.mouseMoveTo(x, y); + eventSender.mouseDown(); + eventSender.mouseUp(); +} +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/sxg-prefetch-resource-timing.html b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/sxg-prefetch-resource-timing.html new file mode 100644 index 0000000..c218c1b --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/sxg-prefetch-resource-timing.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<title>Resource Timing for prefetched SignedHTTPExchange</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="./resources/sxg-util.js"></script> +<body> +<script> +function addPrefetch(url) { + let link = document.createElement('link'); + link.rel = 'prefetch'; + link.href = url; + document.body.appendChild(link); +} +async function wait_for_performance_entries(url) { + let entries = performance.getEntriesByName(url); + if (entries.length > 0) { + return entries; + } + return new Promise((resolve) => { + new PerformanceObserver((list) => { + const entries = list.getEntriesByName(url); + if (entries.length > 0) { + resolve(entries); + } + }).observe({ entryTypes: ['resource'] }); + }); +} + +promise_test(async (t) => { + const url = 'http://127.0.0.1:8000/loading/sxg/resources/sxg-location.sxg'; + addPrefetch(url); + return wait_for_performance_entries(url).then((entries) => { + assert_equals(entries.length, 1, "Should have only one resource timing entry"); + const e = entries[0]; + assert_greater_than(e.duration, 0, "duration should be greater than 0"); + assert_greater_than(e.fetchStart, 0, "fetchStart should be greater than 0"); + assert_greater_than(e.responseEnd, e.fetchStart, + "responseEnd should be greater than fetchStart"); + }); +}, 'Resource Timing for prefetched SignedHTTPExchange'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/float/nopaint-after-layer-destruction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/block/float/nopaint-after-layer-destruction-expected.txt deleted file mode 100644 index 2d78c09..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/block/float/nopaint-after-layer-destruction-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {P} at (0,0) size 784x36 - LayoutText {#text} at (0,0) size 144x18 - text run at (0,0) width 144: "This is a pixel test for " - LayoutInline {I} at (0,0) size 774x36 - LayoutInline {A} at (0,0) size 353x18 [color=#0000EE] - LayoutText {#text} at (143,0) size 353x18 - text run at (143,0) width 353: "http://bugzilla.opendarwin.org/show_bug.cgi?id=4334" - LayoutText {#text} at (495,0) size 774x36 - text run at (495,0) width 5: " " - text run at (499,0) width 275: "REGRESSION: Flickering when css-hover" - text run at (0,18) width 277: "should change opacity on floating elements" - LayoutText {#text} at (276,18) size 5x18 - text run at (276,18) width 5: "." - LayoutBlockFlow {P} at (0,52) size 784x18 - LayoutText {#text} at (0,0) size 281x18 - text run at (0,0) width 281: "There should be a solid green square below." - LayoutBlockFlow {HR} at (0,86) size 784x2 [border: (1px inset #EEEEEE)] - LayoutBlockFlow (floating) {DIV} at (0,96) size 100x100 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/layout_ng/fast/block/float/nopaint-after-layer-destruction-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/layout_ng/fast/block/float/nopaint-after-layer-destruction-expected.png new file mode 100644 index 0000000..3d120b3b --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/layout_ng/fast/block/float/nopaint-after-layer-destruction-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt index 3f29529e..b53778f 100644 --- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -321,7 +321,9 @@ FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "getRemoteCertificates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onerror" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL RTCIceTransport interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function () { [native code] }" did not throw +FAIL RTCIceTransport interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function() { + new interface_object(); + }" did not throw PASS RTCIceTransport interface object length PASS RTCIceTransport interface object name PASS RTCIceTransport interface: existence and properties of interface prototype object
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index d7e0253..4724a9f 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -461,7 +461,6 @@ "web/web_local_frame_client.h", "web/web_meaningful_layout.h", "web/web_media_player_action.h", - "web/web_media_stream_registry.h", "web/web_memory_statistics.h", "web/web_menu_item_info.h", "web/web_meta_element.h",
diff --git a/third_party/blink/public/platform/modules/push_messaging/web_push_client.h b/third_party/blink/public/platform/modules/push_messaging/web_push_client.h index ccf5c05e7..539ee80 100644 --- a/third_party/blink/public/platform/modules/push_messaging/web_push_client.h +++ b/third_party/blink/public/platform/modules/push_messaging/web_push_client.h
@@ -12,16 +12,14 @@ namespace blink { -class WebServiceWorkerRegistration; struct WebPushSubscriptionOptions; class WebPushClient { public: virtual ~WebPushClient() = default; - // Ownership of the WebServiceWorkerRegistration is not transferred. // Ownership of the callbacks is transferred to the client. - virtual void Subscribe(WebServiceWorkerRegistration*, + virtual void Subscribe(int64_t service_worker_registration_id, const WebPushSubscriptionOptions&, bool user_gesture, std::unique_ptr<WebPushSubscriptionCallbacks>) = 0;
diff --git a/third_party/blink/public/platform/modules/push_messaging/web_push_provider.h b/third_party/blink/public/platform/modules/push_messaging/web_push_provider.h index 041402e..da3b8b46 100644 --- a/third_party/blink/public/platform/modules/push_messaging/web_push_provider.h +++ b/third_party/blink/public/platform/modules/push_messaging/web_push_provider.h
@@ -12,7 +12,6 @@ namespace blink { -class WebServiceWorkerRegistration; struct WebPushError; struct WebPushSubscriptionOptions; @@ -25,21 +24,18 @@ virtual ~WebPushProvider() = default; // Takes ownership of the WebPushSubscriptionCallbacks. - // Does not take ownership of the WebServiceWorkerRegistration. - virtual void Subscribe(WebServiceWorkerRegistration*, + virtual void Subscribe(int64_t service_worker_registration_id, const WebPushSubscriptionOptions&, bool user_gesture, std::unique_ptr<WebPushSubscriptionCallbacks>) = 0; // Takes ownership of the WebPushSubscriptionCallbacks. - // Does not take ownership of the WebServiceWorkerRegistration. virtual void GetSubscription( - WebServiceWorkerRegistration*, + int64_t service_worker_registration_id, std::unique_ptr<WebPushSubscriptionCallbacks>) = 0; // Takes ownership if the WebPushUnsubscribeCallbacks. - // Does not take ownership of the WebServiceWorkerRegistration. - virtual void Unsubscribe(WebServiceWorkerRegistration*, + virtual void Unsubscribe(int64_t service_worker_registration_id, std::unique_ptr<WebPushUnsubscribeCallbacks>) = 0; };
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index 2f57bdd1..71666c92 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -167,6 +167,12 @@ // You should not pass in a Platform object that is not fully instantiated. static void SetCurrentPlatformForTesting(Platform*); + // This sets up a minimally viable implementation of blink::Thread without + // changing the current Platform. This is essentially a workaround for the + // initialization order in ScopedUnittestsEnvironmentSetup, and nobody else + // should use this. + static void CreateMainThreadForTesting(); + // These are dirty workaround for tests requiring the main thread task runner // from a non-main thread. If your test needs base::ScopedTaskEnvironment // and a non-main thread may call MainThread()->GetTaskRunner(), call @@ -428,38 +434,34 @@ // Threads ------------------------------------------------------- - // blink::Thread creation is no longer customizable in Platform. - // CreateThread() always creates a new physical thread for Blink. - // Platform maintains the thread-local storage containing each blink::Thread - // object, so that CurrentThread() could return the correct thread object. - // - // TODO(yutak): These non-virtual functions should be moved to somewhere - // else, because they no longer require embedder's implementation. + // Most of threading functionality has moved to blink::Thread. The functions + // in Platform are deprecated; use the counterpart in blink::Thread as noted + // below. - // Creates a new thread. This may be called from a non-main thread (e.g. - // nested Web workers). + // DEPRECATED: Use Thread::CreateThread() instead. std::unique_ptr<Thread> CreateThread(const ThreadCreationParams&); - // Creates a WebAudio-specific thread with the elevated priority. Do NOT use - // for any other purpose. + // DEPRECATED: Use Thread::CreateWebAudioThread() instead. std::unique_ptr<Thread> CreateWebAudioThread(); - // Create and initialize the compositor thread. The thread is saved in - // Platform, and will be accessible through CompositorThread(). - void InitializeCompositorThread(); - - // Returns an interface to the current thread. + // DEPRECATED: Use Thread::Current() instead. Thread* CurrentThread(); - // Returns an interface to the main thread. + // DEPRECATED: Use Thread::MainThread() instead. Thread* MainThread(); - // Returns an interface to the compositor thread. This can be null if the - // renderer was created with threaded rendering disabled. + // DEPRECATED: Use Thread::CompositorThread() instead. Thread* CompositorThread(); + // The two compositor-related functions below are called by the embedder. + // TODO(yutak): Perhaps we should move these to somewhere else? + + // Create and initialize the compositor thread. After this function + // completes, you can access CompositorThreadTaskRunner(). + void CreateAndSetCompositorThread(); + // Returns the task runner of the compositor thread. This is available - // once InitializeCompositorThread() is called. + // once CreateAndSetCompositorThread() is called. scoped_refptr<base::SingleThreadTaskRunner> CompositorThreadTaskRunner(); // This is called after the compositor thread is created, so the embedder @@ -766,28 +768,9 @@ // runs during Chromium's build step). virtual bool IsTakingV8ContextSnapshot() { return false; } - protected: - Thread* main_thread_; - private: - static void InitializeCommon(Platform* platform); - - void WaitUntilThreadTLSUpdate(Thread*); - void UpdateThreadTLS(Thread* thread, base::WaitableEvent* event); - - // Platform owns the main thread in most cases. The pointer value is the same - // as main_thread_ if this variable is non-null. - // - // This variable is null if (and only if) ScopedTestingPlatformSupport<> - // overrides the old Platform. In this case, main_thread_ points to the old - // Platform's main thread. See testing_platform_support.h for this. - std::unique_ptr<Thread> owned_main_thread_; - - std::unique_ptr<Thread> compositor_thread_; - - // We can't use WTF stuff here. Ultimately these should go away (see comments - // near CreateThread()), though. - base::ThreadLocalStorage::Slot current_thread_slot_; + static void InitializeCommon(Platform* platform, + std::unique_ptr<Thread> main_thread); }; } // namespace blink
diff --git a/third_party/blink/public/web/web_media_stream_registry.h b/third_party/blink/public/web/web_media_stream_registry.h deleted file mode 100644 index d0b7565..0000000 --- a/third_party/blink/public/web/web_media_stream_registry.h +++ /dev/null
@@ -1,48 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_MEDIA_STREAM_REGISTRY_H_ -#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_MEDIA_STREAM_REGISTRY_H_ - -#include "third_party/blink/public/platform/web_string.h" - -namespace blink { - -class WebMediaStream; -class WebURL; - -class WebMediaStreamRegistry { - public: - BLINK_EXPORT static WebMediaStream LookupMediaStreamDescriptor(const WebURL&); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_MEDIA_STREAM_REGISTRY_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc index 789022b..5394a38 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h" +#include "third_party/blink/renderer/bindings/core/v8/binding_security.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/core/dom/document.h" @@ -73,7 +74,7 @@ return; { - v8::HandleScope scope(isolate); + v8::HandleScope handle_scope(isolate); // Calling |GetListenerObject()| here may cause compilation of the // uncompiled script body in eventHandler's value earlier than standard's @@ -92,7 +93,7 @@ if (!script_state_of_listener->ContextIsValid()) return; - ScriptState::Scope scope(script_state_of_listener); + ScriptState::Scope listener_script_state_scope(script_state_of_listener); // https://dom.spec.whatwg.org/#firing-events // Step 2. of firing events: Let event be the result of creating an event @@ -101,11 +102,28 @@ // |js_event|, a V8 wrapper object for |event|, must be created in the // relevant realm of the event target. The world must match the event // listener's world. - v8::Local<v8::Context> v8_context = + v8::Local<v8::Context> v8_context_of_event_target = ToV8Context(execution_context_of_event_target, GetWorld()); - if (v8_context.IsEmpty()) + if (v8_context_of_event_target.IsEmpty()) return; - v8::Local<v8::Value> js_event = ToV8(event, v8_context->Global(), isolate); + + if (v8_context_of_event_target != script_state_of_listener->GetContext()) { + // Catch exceptions thrown in the event listener if any and report them to + // DevTools console. + v8::TryCatch try_catch(isolate); + try_catch.SetVerbose(true); + + // Check if the current context, which is set to the listener's relevant + // context by creating |listener_script_state_scope|, has access to the + // event target's relevant context before creating |js_event|. SecurityError + // is thrown if it doesn't have access. + if (!BindingSecurity::ShouldAllowAccessToCreationContext( + v8_context_of_event_target, event->GetWrapperTypeInfo())) + return; + } + + v8::Local<v8::Value> js_event = + ToV8(event, v8_context_of_event_target->Global(), isolate); if (js_event.IsEmpty()) return; @@ -161,7 +179,7 @@ std::unique_ptr<SourceLocation> JSBasedEventListener::GetSourceLocation( EventTarget& target) { - v8::HandleScope(GetIsolate()); + v8::HandleScope handle_scope(GetIsolate()); v8::Local<v8::Value> effective_function = GetEffectiveFunction(target); if (effective_function->IsFunction()) return SourceLocation::FromFunction(effective_function.As<v8::Function>());
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc b/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc index 42b029d..16d8f73 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc
@@ -25,6 +25,16 @@ v8::Local<v8::Function> listener, const V8PrivateProperty::Symbol& property) { DCHECK(!HasCompiledHandler()); + + // https://html.spec.whatwg.org/multipage/webappapis.html#getting-the-current-value-of-the-event-handler + // Step 12: Set eventHandler's value to the result of creating a Web IDL + // EventHandler callback function object whose object reference is function + // and whose callback context is settings object. + // + // Push |script_state|'s context onto the backup incumbent settings object + // stack because appropriate incumbent realm does not always exist when + // content attribute gets lazily compiled. This context is the same one of the + // relevant realm of |listener| and its event target. v8::Context::BackupIncumbentScope backup_incumbent_scope( script_state->GetContext()); event_handler_ = V8EventHandlerNonNull::Create(listener);
diff --git a/third_party/blink/renderer/bindings/scripts/code_generator_v8.py b/third_party/blink/renderer/bindings/scripts/code_generator_v8.py index 455a76e..9d321f9 100644 --- a/third_party/blink/renderer/bindings/scripts/code_generator_v8.py +++ b/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
@@ -187,19 +187,19 @@ # Select appropriate Jinja template and contents function if interface.is_callback: header_template_filename = 'callback_interface.h.tmpl' - cpp_template_filename = 'callback_interface.cpp.tmpl' + cpp_template_filename = 'callback_interface.cc.tmpl' interface_context = v8_callback_interface.callback_interface_context elif interface.is_partial: interface_context = v8_interface.interface_context header_template_filename = 'partial_interface.h.tmpl' - cpp_template_filename = 'partial_interface.cpp.tmpl' + cpp_template_filename = 'partial_interface.cc.tmpl' interface_name += 'Partial' assert component == 'core' component = 'modules' include_paths = interface_info.get('dependencies_other_component_include_paths') else: header_template_filename = 'interface.h.tmpl' - cpp_template_filename = 'interface.cpp.tmpl' + cpp_template_filename = 'interface.cc.tmpl' interface_context = v8_interface.interface_context template_context = interface_context(interface, definitions.interfaces) @@ -233,7 +233,7 @@ # pylint: disable=unused-argument interfaces_info = self.info_provider.interfaces_info header_template = self.jinja_env.get_template('dictionary_v8.h.tmpl') - cpp_template = self.jinja_env.get_template('dictionary_v8.cpp.tmpl') + cpp_template = self.jinja_env.get_template('dictionary_v8.cc.tmpl') interface_info = interfaces_info[dictionary_name] template_context = v8_dictionary.dictionary_context( dictionary, interfaces_info) @@ -273,7 +273,7 @@ dictionary = definitions.dictionaries[definition_name] interface_info = interfaces_info[definition_name] header_template = self.jinja_env.get_template('dictionary_impl.h.tmpl') - cpp_template = self.jinja_env.get_template('dictionary_impl.cpp.tmpl') + cpp_template = self.jinja_env.get_template('dictionary_impl.cc.tmpl') template_context = v8_dictionary.dictionary_impl_context( dictionary, interfaces_info) include_paths = interface_info.get('dependencies_include_paths') @@ -313,7 +313,7 @@ includes.clear() union_type = union_type.resolve_typedefs(self.typedefs) header_template = self.jinja_env.get_template('union_container.h.tmpl') - cpp_template = self.jinja_env.get_template('union_container.cpp.tmpl') + cpp_template = self.jinja_env.get_template('union_container.cc.tmpl') template_context = v8_union.container_context(union_type, self.info_provider) template_context['header_includes'].append( self.info_provider.include_path_for_export) @@ -365,7 +365,7 @@ def generate_code_internal(self, callback_function, path): self.typedef_resolver.resolve(callback_function, callback_function.name) header_template = self.jinja_env.get_template('callback_function.h.tmpl') - cpp_template = self.jinja_env.get_template('callback_function.cpp.tmpl') + cpp_template = self.jinja_env.get_template('callback_function.cc.tmpl') template_context = v8_callback_function.callback_function_context( callback_function) if not is_testing_target(path):
diff --git a/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py b/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py index 5eaa524..c55a0fe 100644 --- a/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py +++ b/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py
@@ -29,7 +29,7 @@ 'third_party/blink/renderer/platform/bindings/v8_private_property.h', 'v8/include/v8.h']) -TEMPLATE_FILE = 'external_reference_table.cpp.tmpl' +TEMPLATE_FILE = 'external_reference_table.cc.tmpl' WHITE_LIST_INTERFACES = frozenset([ 'DOMMatrix', # crbug.com/733481
diff --git a/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl similarity index 98% rename from third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/attributes.cc.tmpl index f569e78a..e211518 100644 --- a/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
@@ -1,5 +1,5 @@ -{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %} -{% from 'methods.cpp.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %} +{% from 'utilities.cc.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %} +{% from 'methods.cc.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %} {##############################################################################} {% macro attribute_getter(attribute, world_suffix) %} @@ -514,7 +514,7 @@ {##############################################################################} {% macro build_attribute_or_accessor_configuration(attribute, config_type) %} -{% from 'utilities.cpp.tmpl' import property_location %} +{% from 'utilities.cc.tmpl' import property_location %} {% if attribute.constructor_type %} {% set getter_callback = '%s::%sConstructorGetterCallback' % (v8_class_or_partial, attribute.name) %} {% set setter_callback = 'nullptr' %}
diff --git a/third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl b/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl similarity index 100% rename from third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl
diff --git a/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl b/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl similarity index 98% rename from third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl index f68d464..2ac0b7b 100644 --- a/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl
@@ -34,7 +34,7 @@ #pragma clang diagnostic pop #endif -{% from 'constants.cpp.tmpl' import install_constants with context %} +{% from 'constants.cc.tmpl' import install_constants with context %} static void Install{{v8_class}}Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interface_template) { // Legacy callback interface must not have a prototype object. interface_template->RemovePrototype();
diff --git a/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl b/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl index 25f514b..97bf37f 100644 --- a/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl
@@ -1,4 +1,4 @@ -{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable %} +{% from 'utilities.cc.tmpl' import declare_enum_validation_variable %} {# Implements callback interface\'s "call a user object's operation", or callback function\'s "invoke" and/or "construct".
diff --git a/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl b/third_party/blink/renderer/bindings/templates/constants.cc.tmpl similarity index 96% rename from third_party/blink/renderer/bindings/templates/constants.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/constants.cc.tmpl index 1b8d27c..798329d7 100644 --- a/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/constants.cc.tmpl
@@ -1,4 +1,4 @@ -{% from 'methods.cpp.tmpl' import runtime_timer_scope_disabled_by_default %} +{% from 'methods.cc.tmpl' import runtime_timer_scope_disabled_by_default %} {##############################################################################} {% macro constant_getter_callback(constant) %}
diff --git a/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl b/third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl similarity index 92% rename from third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl index a08c3ad..546a970 100644 --- a/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl
@@ -1,4 +1,4 @@ -{% from 'dictionary_impl_common.cpp.tmpl' import dictionary_setter_impl with context %} +{% from 'dictionary_impl_common.cc.tmpl' import dictionary_setter_impl with context %} {% filter format_blink_cpp_source_code %} {% include 'copyright_block.txt' %}
diff --git a/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl b/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl index 8e485d3..8055c54 100644 --- a/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl +++ b/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
@@ -1,4 +1,4 @@ -{% from 'dictionary_impl_common.cpp.tmpl' import dictionary_setter_impl with context %} +{% from 'dictionary_impl_common.cc.tmpl' import dictionary_setter_impl with context %} {% filter format_blink_cpp_source_code %} {% include 'copyright_block.txt' %}
diff --git a/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl b/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cc.tmpl similarity index 100% rename from third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/dictionary_impl_common.cc.tmpl
diff --git a/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl b/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl similarity index 97% rename from third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl index 1573a02..42ef29d 100644 --- a/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
@@ -1,6 +1,6 @@ {% filter format_blink_cpp_source_code %} -{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable %} +{% from 'utilities.cc.tmpl' import declare_enum_validation_variable %} {% include 'copyright_block.txt' %} #include "{{this_include_header_path}}" @@ -22,7 +22,7 @@ } {% endif %} -{% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} +{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %} void {{v8_class}}::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8Value, {{cpp_class}}& impl, ExceptionState& exceptionState) { if (IsUndefinedOrNull(v8Value)) { {% if required_member_names %}
diff --git a/third_party/blink/renderer/bindings/templates/external_reference_table.cpp.tmpl b/third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl similarity index 100% rename from third_party/blink/renderer/bindings/templates/external_reference_table.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl
diff --git a/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl b/third_party/blink/renderer/bindings/templates/interface.cc.tmpl similarity index 98% rename from third_party/blink/renderer/bindings/templates/interface.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/interface.cc.tmpl index 1d7c57a4..02d1f47 100644 --- a/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
@@ -1,6 +1,6 @@ -{% extends 'interface_base.cpp.tmpl' %} +{% extends 'interface_base.cc.tmpl' %} -{% from 'methods.cpp.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %} +{% from 'methods.cc.tmpl' import runtime_timer_scope, runtime_timer_scope_disabled_by_default %} {##############################################################################} {% block indexed_property_getter %} @@ -70,7 +70,7 @@ {##############################################################################} {% block indexed_property_setter %} -{% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} +{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %} {% if indexed_property_setter and not indexed_property_setter.is_custom %} {% set setter = indexed_property_setter %} static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) { @@ -427,7 +427,7 @@ {##############################################################################} {% block named_property_setter %} -{% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} +{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %} {% if named_property_setter and not named_property_setter.is_custom %} {% set setter = named_property_setter %} static void namedPropertySetter(const AtomicString& name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) { @@ -691,7 +691,7 @@ {% raw %} // |methodName| must be same with {{method.name}} in // {{method.name}}OriginSafeMethodGetter{{world_suffix}} defined in - // methods.cpp.tmpl + // methods.cc.tmpl {% endraw %} V8PrivateProperty::GetSymbol(info.GetIsolate(), *methodName) .Set(v8::Local<v8::Object>::Cast(info.Holder()), v8Value); @@ -710,7 +710,7 @@ {##############################################################################} {% block named_constructor %} -{% from 'methods.cpp.tmpl' import generate_constructor with context %} +{% from 'methods.cc.tmpl' import generate_constructor with context %} {% if named_constructor %} {% set active_scriptwrappable_inheritance = 'kInheritFromActiveScriptWrappable' @@ -867,7 +867,7 @@ {##############################################################################} {% macro install_origin_safe_method(method, instance_template, prototype_template) %} -{% from 'utilities.cpp.tmpl' import property_location %} +{% from 'utilities.cc.tmpl' import property_location %} {# TODO(dcheng): Currently, bindings must create a function object for each realm as a hack to support the incumbent realm. Clean this up when Blink properly supports the incumbent realm. #}
diff --git a/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl b/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl similarity index 96% rename from third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl index f78737d..bb5fa16d 100644 --- a/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl
@@ -84,7 +84,7 @@ {##############################################################################} {# Attributes #} -{% from 'attributes.cpp.tmpl' import attribute_getter, +{% from 'attributes.cc.tmpl' import attribute_getter, attribute_setter, with context %} {% for attribute in attributes %} @@ -99,7 +99,7 @@ {% endfor %} {##############################################################################} {# Methods #} -{% from 'methods.cpp.tmpl' import generate_method, overload_resolution_method, +{% from 'methods.cc.tmpl' import generate_method, overload_resolution_method, origin_safe_method_getter, generate_constructor, runtime_determined_length_method, runtime_determined_maxarg_method with context %} @@ -180,13 +180,13 @@ } // namespace {{cpp_class_or_partial}}V8Internal {# Constants #} -{% from 'constants.cpp.tmpl' import constant_getter_callback with context %} +{% from 'constants.cc.tmpl' import constant_getter_callback with context %} {% for constant in constants | has_special_getter %} {{constant_getter_callback(constant)}} {% endfor %} {# Attributes #} -{% from 'attributes.cpp.tmpl' import constructor_getter_callback, +{% from 'attributes.cc.tmpl' import constructor_getter_callback, attribute_getter_callback, attribute_setter_callback with context %} {% for attribute in attributes %} {% for world_suffix in attribute.world_suffixes %} @@ -202,7 +202,7 @@ {% endfor %} {# Methods #} -{% from 'methods.cpp.tmpl' import origin_safe_method_getter_callback, +{% from 'methods.cc.tmpl' import origin_safe_method_getter_callback, method_callback with context %} {% for method in methods %} {% for world_suffix in method.world_suffixes %} @@ -350,7 +350,7 @@ {% block visit_dom_wrapper %}{% endblock %} {##############################################################################} {% block install_attributes %} -{% from 'attributes.cpp.tmpl' import attribute_configuration with context %} +{% from 'attributes.cc.tmpl' import attribute_configuration with context %} {% if data_attributes %} // Suppress warning: global constructors, because AttributeConfiguration is trivial // and does not depend on another global objects. @@ -371,7 +371,7 @@ {% endblock %} {##############################################################################} {% block install_accessors %} -{% from 'attributes.cpp.tmpl' import accessor_configuration with context %} +{% from 'attributes.cc.tmpl' import accessor_configuration with context %} {% if accessors %} static const V8DOMConfiguration::AccessorConfiguration {{v8_class}}Accessors[] = { {% for accessor in accessors %} @@ -383,7 +383,7 @@ {% endblock %} {##############################################################################} {% block install_methods %} -{% from 'methods.cpp.tmpl' import method_configuration with context %} +{% from 'methods.cc.tmpl' import method_configuration with context %} {% if methods | has_method_configuration(is_partial) %} static const V8DOMConfiguration::MethodConfiguration {{v8_class}}Methods[] = { {% for method in methods | has_method_configuration(is_partial) %} @@ -400,12 +400,12 @@ {##############################################################################} {% block install_dom_template %} {% if not is_array_buffer_or_view %} -{% from 'methods.cpp.tmpl' import install_custom_signature, +{% from 'methods.cc.tmpl' import install_custom_signature, method_configuration with context %} -{% from 'attributes.cpp.tmpl' import accessor_configuration, +{% from 'attributes.cc.tmpl' import accessor_configuration, attribute_configuration, with context %} -{% from 'constants.cpp.tmpl' import install_constants, +{% from 'constants.cc.tmpl' import install_constants, constant_configuration with context %} {% if has_partial_interface or is_partial %} void {{v8_class_or_partial}}::install{{v8_class}}Template( @@ -760,8 +760,8 @@ {##############################################################################} {% block install_runtime_enabled %} {% if needs_runtime_enabled_installer %} -{% from 'attributes.cpp.tmpl' import accessor_configuration, attribute_configuration with context %} -{% from 'methods.cpp.tmpl' import install_custom_signature with context %} +{% from 'attributes.cc.tmpl' import accessor_configuration, attribute_configuration with context %} +{% from 'methods.cc.tmpl' import install_custom_signature with context %} {% if not is_partial %} void {{v8_class}}::InstallRuntimeEnabledFeatures( v8::Isolate* isolate, @@ -851,11 +851,11 @@ {% endblock %} {##############################################################################} {% block origin_trials %} -{% from 'attributes.cpp.tmpl' import accessor_configuration, +{% from 'attributes.cc.tmpl' import accessor_configuration, attribute_configuration, with context %} -{% from 'constants.cpp.tmpl' import constant_configuration with context %} -{% from 'methods.cpp.tmpl' import method_configuration with context %} +{% from 'constants.cc.tmpl' import constant_configuration with context %} +{% from 'methods.cc.tmpl' import method_configuration with context %} {% for feature in optional_features %} void {{v8_class_or_partial}}::install{{feature.name}}(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface) { {% if feature.attributes or feature.methods %} @@ -929,9 +929,9 @@ {% block native_value_traits %}{% endblock %} {##############################################################################} {% block install_conditional_features %} -{% from 'attributes.cpp.tmpl' import install_conditional_attributes, +{% from 'attributes.cc.tmpl' import install_conditional_attributes, install_conditional_interface_objects with context %} -{% from 'methods.cpp.tmpl' import install_conditional_methods with context %} +{% from 'methods.cc.tmpl' import install_conditional_methods with context %} {% if install_conditional_features_func %} void {{v8_class_or_partial}}::InstallConditionalFeatures( v8::Local<v8::Context> context,
diff --git a/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl similarity index 98% rename from third_party/blink/renderer/bindings/templates/methods.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/methods.cc.tmpl index b0e5543..98e1038 100644 --- a/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
@@ -1,4 +1,4 @@ -{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %} +{% from 'utilities.cc.tmpl' import declare_enum_validation_variable, v8_value_to_local_cpp_value %} {##############################################################################} {% macro runtime_timer_scope(counter) %} @@ -546,7 +546,7 @@ {% raw %} // {{method.name}} must be same with |methodName| (=name) in - // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl. + // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl. {% endraw %} V8PrivateProperty::Symbol propertySymbol = V8PrivateProperty::GetSymbol(info.GetIsolate(), "{{method.name}}"); @@ -612,7 +612,7 @@ {##############################################################################} {% macro method_configuration(method) %} -{% from 'utilities.cpp.tmpl' import property_location %} +{% from 'utilities.cc.tmpl' import property_location %} {% set method_callback = '%s::%sMethodCallback' % (v8_class_or_partial, method.name) %} {% set method_callback_for_main_world =
diff --git a/third_party/blink/renderer/bindings/templates/partial_interface.cpp.tmpl b/third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl similarity index 95% rename from third_party/blink/renderer/bindings/templates/partial_interface.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl index e318f612..91087a0 100644 --- a/third_party/blink/renderer/bindings/templates/partial_interface.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl
@@ -1,4 +1,4 @@ -{% extends 'interface_base.cpp.tmpl' %} +{% extends 'interface_base.cc.tmpl' %} {##############################################################################} {% block partial_interface %}
diff --git a/third_party/blink/renderer/bindings/templates/templates.gni b/third_party/blink/renderer/bindings/templates/templates.gni index b6c270e..585a300 100644 --- a/third_party/blink/renderer/bindings/templates/templates.gni +++ b/third_party/blink/renderer/bindings/templates/templates.gni
@@ -5,29 +5,29 @@ # Paths should be absolute so this file can be imported from anywhere. code_generator_template_files = get_path_info([ - "attributes.cpp.tmpl", - "callback_function.cpp.tmpl", + "attributes.cc.tmpl", + "callback_function.cc.tmpl", "callback_function.h.tmpl", - "callback_interface.cpp.tmpl", + "callback_interface.cc.tmpl", "callback_interface.h.tmpl", "callback_invoke.cc.tmpl", - "constants.cpp.tmpl", + "constants.cc.tmpl", "copyright_block.txt", - "dictionary_impl.cpp.tmpl", + "dictionary_impl.cc.tmpl", "dictionary_impl.h.tmpl", - "dictionary_impl_common.cpp.tmpl", - "dictionary_v8.cpp.tmpl", + "dictionary_impl_common.cc.tmpl", + "dictionary_v8.cc.tmpl", "dictionary_v8.h.tmpl", - "external_reference_table.cpp.tmpl", - "interface.cpp.tmpl", + "external_reference_table.cc.tmpl", + "interface.cc.tmpl", "interface.h.tmpl", - "interface_base.cpp.tmpl", - "methods.cpp.tmpl", - "partial_interface.cpp.tmpl", + "interface_base.cc.tmpl", + "methods.cc.tmpl", + "partial_interface.cc.tmpl", "partial_interface.h.tmpl", - "union_container.cpp.tmpl", + "union_container.cc.tmpl", "union_container.h.tmpl", - "utilities.cpp.tmpl", + "utilities.cc.tmpl", "web_agent_api_interface.cc.tmpl", "web_agent_api_interface.h.tmpl", ],
diff --git a/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl b/third_party/blink/renderer/bindings/templates/union_container.cc.tmpl similarity index 97% rename from third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/union_container.cc.tmpl index 2b6b64c..884fd43 100644 --- a/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/union_container.cc.tmpl
@@ -1,5 +1,5 @@ -{% from 'utilities.cpp.tmpl' import declare_enum_validation_variable %} -{% from 'utilities.cpp.tmpl' import v8_value_to_local_cpp_value %} +{% from 'utilities.cc.tmpl' import declare_enum_validation_variable %} +{% from 'utilities.cc.tmpl' import v8_value_to_local_cpp_value %} {#############################################################################} {% macro assign_and_return_if_hasinstance(member) %} {% if member.is_array_buffer_or_view_type %}
diff --git a/third_party/blink/renderer/bindings/templates/utilities.cpp.tmpl b/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl similarity index 100% rename from third_party/blink/renderer/bindings/templates/utilities.cpp.tmpl rename to third_party/blink/renderer/bindings/templates/utilities.cc.tmpl
diff --git a/third_party/blink/renderer/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc index fc0077f..647dca48 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/array_buffer_or_array_buffer_view_or_dictionary.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/boolean_or_element_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/boolean_or_element_sequence.cc index 44b11d81..f710fd4a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/boolean_or_element_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/boolean_or_element_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc b/third_party/blink/renderer/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc index 3173af6..59c35a1a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/boolean_or_string_or_unrestricted_double.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/boolean_or_test_callback_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/boolean_or_test_callback_interface.cc index 74e4ae1..577f00b 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/boolean_or_test_callback_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/boolean_or_test_callback_interface.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/byte_string_or_node_list.cc b/third_party/blink/renderer/bindings/tests/results/core/byte_string_or_node_list.cc index 1ca3e9119..9a0724ad 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/byte_string_or_node_list.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/byte_string_or_node_list.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc b/third_party/blink/renderer/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc index 2827871..2e7d3367 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/byte_string_sequence_sequence_or_byte_string_byte_string_record.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/double_or_double_or_null_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/double_or_double_or_null_sequence.cc index 216c319..c44d6f1 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/double_or_double_or_null_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/double_or_double_or_null_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/double_or_double_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/double_or_double_sequence.cc index e0dc677..d1de8e7 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/double_or_double_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/double_or_double_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc index a528934..52f7b601 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/double_or_long_or_boolean_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/double_or_string.cc b/third_party/blink/renderer/bindings/tests/results/core/double_or_string.cc index 5ea464c..00fb975 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/double_or_string.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/double_or_string.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc index 2298371e..e8ee4fe 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/double_or_string_or_double_or_string_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc b/third_party/blink/renderer/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc index 5567c047..f9f251a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/element_sequence_or_byte_string_double_or_string_record.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/float_or_boolean.cc b/third_party/blink/renderer/bindings/tests/results/core/float_or_boolean.cc index 712688dd..72a0a33d 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/float_or_boolean.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/float_or_boolean.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/long_or_boolean.cc b/third_party/blink/renderer/bindings/tests/results/core/long_or_boolean.cc index 141dd8ba5..de48707 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/long_or_boolean.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/long_or_boolean.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/long_or_test_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/long_or_test_dictionary.cc index 54a355d..42ff4ebb 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/long_or_test_dictionary.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/long_or_test_dictionary.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/long_sequence_or_event.cc b/third_party/blink/renderer/bindings/tests/results/core/long_sequence_or_event.cc index 9621a9f..c1df376 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/long_sequence_or_event.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/long_sequence_or_event.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/nested_union_type.cc b/third_party/blink/renderer/bindings/tests/results/core/nested_union_type.cc index 69585f5..6dc0496 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/nested_union_type.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/nested_union_type.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/node_or_node_list.cc b/third_party/blink/renderer/bindings/tests/results/core/node_or_node_list.cc index 5357cbe7..8bc3505c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/node_or_node_list.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/node_or_node_list.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc b/third_party/blink/renderer/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc index 17cec5cd..6c09a1a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/string_or_array_buffer_or_array_buffer_view.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/string_or_double.cc b/third_party/blink/renderer/bindings/tests/results/core/string_or_double.cc index 444b84b..e4b9ebe6 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/string_or_double.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/string_or_double.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/string_or_string_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/string_or_string_sequence.cc index d26c42b..b9f839c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/string_or_string_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/string_or_string_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/test_dictionary.cc index bd498bc..eee33b3 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_dictionary.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_dictionary.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_dictionary_derived.cc b/third_party/blink/renderer/bindings/tests/results/core/test_dictionary_derived.cc index ec382a0d..a034934 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_dictionary_derived.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_dictionary_derived.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_double.cc b/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_double.cc index 19a721f..6114972 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_double.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_double.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_or_null_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_or_null_sequence.cc index 7ce2917f..7a4f425 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_or_null_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_or_null_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_sequence.cc b/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_sequence.cc index a96c8ca3..be1c3bc 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_sequence.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_enum_or_test_enum_sequence.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_interface_2_or_uint8_array.cc b/third_party/blink/renderer/bindings/tests/results/core/test_interface_2_or_uint8_array.cc index 0a44d2c..1f58f39 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_interface_2_or_uint8_array.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_interface_2_or_uint8_array.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_interface_event_init.cc b/third_party/blink/renderer/bindings/tests/results/core/test_interface_event_init.cc index c5927f7..bdf5287 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_interface_event_init.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_interface_event_init.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_long.cc b/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_long.cc index 72ddd7b..b4b39d1a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_long.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_long.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_test_interface_empty.cc b/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_test_interface_empty.cc index b4f738a..a5b9aee 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_test_interface_empty.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_interface_or_test_interface_empty.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/test_permissive_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/test_permissive_dictionary.cc index 339d400..29d75af 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/test_permissive_dictionary.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/test_permissive_dictionary.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_impl.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/unrestricted_double_or_string.cc b/third_party/blink/renderer/bindings/tests/results/core/unrestricted_double_or_string.cc index ac0d42a..ee89235 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/unrestricted_double_or_string.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/unrestricted_double_or_string.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc index 3c5a2d7..2ef955a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/unsigned_long_long_or_boolean_or_test_callback_interface.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc index 9c94e586..81378ef 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc index d44c397d..c44f741 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer.cc index ac29a395..2eb4e12 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer_view.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer_view.cc index 6ee1342..2be1008 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer_view.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_array_buffer_view.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_data_view.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_data_view.cc index 9be5a1e3..6d9d76d 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_data_view.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_data_view.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc index 194975f..f42b1a0 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc index 02fabbb..ebe09c58 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_svg_test_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_svg_test_interface.cc index ddc78e0..5a9aaa9 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_svg_test_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_svg_test_interface.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc index 68079506..859d0cc 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_functions.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_functions.cc index 915b9ea..6f43037 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_functions.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_functions.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc index e078d5d..9dcb6a4 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc index f686d4b82..4fbad7e 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc index d605d0a..6394187d 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary_derived.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary_derived.cc index c2ad6910..2adc1be 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary_derived.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary_derived.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc index 28d9d4e..62d09050 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_global.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_global.cc index b8d720e..dfa883f 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_global.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_global.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_primary_global.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_primary_global.cc index 8ee0752..708b062 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_primary_global.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_integer_indexed_primary_global.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc index fe533d8d..ea83e55 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc index 9f720f0..d06ad87c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_2.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_3.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_3.cc index a8f61da..5a15cce 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_3.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_3.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_check_security.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_check_security.cc index ecaa590..bd5a7fbd 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_check_security.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_check_security.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY! @@ -201,7 +201,7 @@ } // {{method.name}} must be same with |methodName| (=name) in - // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl. + // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl. V8PrivateProperty::Symbol propertySymbol = V8PrivateProperty::GetSymbol(info.GetIsolate(), "doNotCheckSecurityVoidMethod"); v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder()); @@ -233,7 +233,7 @@ } // {{method.name}} must be same with |methodName| (=name) in - // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl. + // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl. V8PrivateProperty::Symbol propertySymbol = V8PrivateProperty::GetSymbol(info.GetIsolate(), "doNotCheckSecurityPerWorldBindingsVoidMethod"); v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder()); @@ -265,7 +265,7 @@ } // {{method.name}} must be same with |methodName| (=name) in - // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl. + // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl. V8PrivateProperty::Symbol propertySymbol = V8PrivateProperty::GetSymbol(info.GetIsolate(), "doNotCheckSecurityPerWorldBindingsVoidMethod"); v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder()); @@ -297,7 +297,7 @@ } // {{method.name}} must be same with |methodName| (=name) in - // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl. + // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl. V8PrivateProperty::Symbol propertySymbol = V8PrivateProperty::GetSymbol(info.GetIsolate(), "doNotCheckSecurityUnforgeableVoidMethod"); v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder()); @@ -424,7 +424,7 @@ } // {{method.name}} must be same with |methodName| (=name) in - // {{cpp_class}}OriginSafeMethodSetter defined in interface.cpp.tmpl. + // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl. V8PrivateProperty::Symbol propertySymbol = V8PrivateProperty::GetSymbol(info.GetIsolate(), "doNotCheckSecurityVoidOverloadMethod"); v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder()); @@ -466,7 +466,7 @@ // |methodName| must be same with {{method.name}} in // {{method.name}}OriginSafeMethodGetter{{world_suffix}} defined in - // methods.cpp.tmpl + // methods.cc.tmpl V8PrivateProperty::GetSymbol(info.GetIsolate(), *methodName) .Set(v8::Local<v8::Object>::Cast(info.Holder()), v8Value); }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_conditional_secure_context.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_conditional_secure_context.cc index dfe293a..03f27263 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_conditional_secure_context.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_conditional_secure_context.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc index 1250cf8..e2007e9 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_2.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_2.cc index 04b79a2..beaba95c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_2.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_2.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_3.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_3.cc index 0e30e15..98f3a9a2 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_3.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_3.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_4.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_4.cc index 1340fb7b..22bb602 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_4.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor_4.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_custom_constructor.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_custom_constructor.cc index b014630..82b9b143 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_custom_constructor.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_custom_constructor.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc index 2903f9c..1dec31c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_empty.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_empty.cc index 51e9c8f..85fb95a9 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_empty.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_empty.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init.cc index f1a9a10..34df4fc 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init_constructor.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init_constructor.cc index d99e4b0..47c9731 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init_constructor.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_init_constructor.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_target.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_target.cc index 80d4390..c1c536ff 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_target.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_event_target.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor.cc index f966d7b7..ab22b84 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor_2.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor_2.cc index 998dd91..0184da4 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor_2.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_named_constructor_2.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_node.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_node.cc index 37b2d68..35a89e8c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_node.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_node.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_origin_trial_enabled.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_origin_trial_enabled.cc index 63cb40e..03d37bc3 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_origin_trial_enabled.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_origin_trial_enabled.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_secure_context.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_secure_context.cc index 0f9910b..3d6b1eaf 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_secure_context.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_secure_context.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc index eb3b1c43..d2aa85e 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_node.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_node.cc index 27388218..89b20df 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_node.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_node.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc index 548edfe..fce89aa 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_permissive_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_permissive_dictionary.cc index 508bcc8..d41bebf 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_permissive_dictionary.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_permissive_dictionary.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl +// third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations.cc index 916de0ff..36216416 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations_not_enumerable.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations_not_enumerable.cc index ea7e8d1a..9275f5f 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations_not_enumerable.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_special_operations_not_enumerable.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_typedefs.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_typedefs.cc index d5a59bd..d3b2636 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_typedefs.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_typedefs.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_variadic_constructor_arguments.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_variadic_constructor_arguments.cc index 27f875a..123d80c 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_variadic_constructor_arguments.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_variadic_constructor_arguments.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc index 7868a24..3f745af0 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc index b6d59ba..ae23a87 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_uint8_clamped_array.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_uint8_clamped_array.cc index a9cf170..f838ab1 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_uint8_clamped_array.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_uint8_clamped_array.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc index 4604b860..8e9b8564 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc index f11cbda..d6ea6737 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc index 42e1729..eae3aba1 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc index 3e66d4f..e13d389 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc index 2b970bf..3e25936 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc index 9952e59..8d05ea4 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/core/xml_http_request_or_string.cc b/third_party/blink/renderer/bindings/tests/results/core/xml_http_request_or_string.cc index 914717ff..82d67c8 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/xml_http_request_or_string.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/xml_http_request_or_string.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/boolean_or_string.cc b/third_party/blink/renderer/bindings/tests/results/modules/boolean_or_string.cc index a4b9035..595e5f1 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/boolean_or_string.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/boolean_or_string.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl +// third_party/blink/renderer/bindings/templates/union_container.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_inherited_legacy_unenumerable_named_properties.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_inherited_legacy_unenumerable_named_properties.cc index 0ce7006c..9bb6443 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_inherited_legacy_unenumerable_named_properties.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_inherited_legacy_unenumerable_named_properties.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_2_partial.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_2_partial.cc index c11af8c..5d4d625d 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_2_partial.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_2_partial.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/partial_interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_5.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_5.cc index 4c80b44..d7660ff 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_5.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_5.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_partial.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_partial.cc index 239a538e..8492843 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_partial.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_interface_partial.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/partial_interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/partial_interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_not_enumerable_named_getter.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_not_enumerable_named_getter.cc index 58fe85e8..e37234d 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_not_enumerable_named_getter.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_not_enumerable_named_getter.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_sub_object.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_sub_object.cc index 95e53da..54e12d7 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_test_sub_object.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_test_sub_object.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +// third_party/blink/renderer/bindings/templates/interface.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc index 64078dd..f0e35e9 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. // This file has been auto-generated from the Jinja2 template -// third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl +// third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl // by the script code_generator_v8.py. // DO NOT MODIFY!
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.h b/third_party/blink/renderer/core/css/css_primitive_value.h index a4b4f3a3..a00ce66f 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value.h +++ b/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -297,7 +297,7 @@ template <typename T> operator T*(); // compile-time guard - // Code generated by CSSPrimitiveValueUnitTrie.cpp.tmpl + // Code generated by css_primitive_value_unit_trie.cc.tmpl static UnitType StringToUnitType(const LChar*, unsigned length); static UnitType StringToUnitType(const UChar*, unsigned length);
diff --git a/third_party/blink/renderer/core/css/css_syntax_descriptor.h b/third_party/blink/renderer/core/css/css_syntax_descriptor.h index ec88ced..7b3642a 100644 --- a/third_party/blink/renderer/core/css/css_syntax_descriptor.h +++ b/third_party/blink/renderer/core/css/css_syntax_descriptor.h
@@ -45,6 +45,10 @@ } bool IsRepeatable() const { return repeat_ != CSSSyntaxRepeat::kNone; } + char Separator() const { + DCHECK(IsRepeatable()); + return repeat_ == CSSSyntaxRepeat::kSpaceSeparated ? ' ' : ','; + } bool CanTake(const CSSStyleValue&) const;
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.cc b/third_party/blink/renderer/core/css/cssom/style_property_map.cc index adc08f0..111f9fb 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
@@ -22,6 +22,21 @@ namespace { +bool IsListValuedProperty(const CSSProperty& property, + const PropertyRegistration* registration) { + if (property.IsRepeated()) + return true; + // TODO(andruud): The concept of "list-valued properties" doesn't fully work + // in all cases. See https://github.com/w3c/css-houdini-drafts/issues/823 + // For now we only consider a custom property list-valued if it has a single + // syntax component that is repeatable (e.g. <length>+). + if (property.IDEquals(CSSPropertyVariable) && registration) { + const auto& components = registration->Syntax().Components(); + return components.size() == 1 && components[0].IsRepeatable(); + } + return false; +} + CSSValueList* CssValueListForPropertyID(CSSPropertyID property_id) { DCHECK(CSSProperty::Get(property_id).IsRepeated()); char separator = CSSProperty::Get(property_id).RepetitionSeparator(); @@ -38,6 +53,44 @@ } } +const CSSVariableReferenceValue* CreateVariableReferenceValue( + const String& value, + const CSSParserContext& context) { + CSSTokenizer tokenizer(value); + const auto tokens = tokenizer.TokenizeToEOF(); + CSSParserTokenRange range(tokens); + scoped_refptr<CSSVariableData> variable_data = CSSVariableData::Create( + range, false, false, context.BaseURL(), context.Charset()); + return CSSVariableReferenceValue::Create(variable_data, context); +} + +const CSSVariableReferenceValue* CreateVariableReferenceValue( + const CSSProperty& property, + const AtomicString& custom_property_name, + const PropertyRegistration& registration, + const CSSStyleValueVector& values, + const CSSParserContext& context) { + DCHECK(IsListValuedProperty(property, ®istration)); + DCHECK_EQ(registration.Syntax().Components().size(), 1U); + + char separator = registration.Syntax().Components()[0].Separator(); + + StringBuilder builder; + + for (const auto& value : values) { + if (!CSSOMTypes::PropertyCanTake(property.PropertyID(), + custom_property_name, ®istration, + *value)) { + return nullptr; + } + if (!builder.IsEmpty()) + builder.Append(separator); + builder.Append(value->toString()); + } + + return CreateVariableReferenceValue(builder.ToString(), context); +} + const CSSValue* StyleValueToCSSValue( const CSSProperty& property, const AtomicString& custom_property_name, @@ -69,13 +122,8 @@ case CSSPropertyVariable: if (registration && style_value.GetType() != CSSStyleValue::kUnparsedType) { - CSSTokenizer tokenizer(style_value.toString()); - const auto tokens = tokenizer.TokenizeToEOF(); - CSSParserTokenRange range(tokens); CSSParserContext* context = CSSParserContext::Create(execution_context); - scoped_refptr<CSSVariableData> variable_data = CSSVariableData::Create( - range, false, false, context->BaseURL(), context->Charset()); - return CSSVariableReferenceValue::Create(variable_data, *context); + return CreateVariableReferenceValue(style_value.toString(), *context); } break; case CSSPropertyBorderBottomLeftRadius: @@ -207,7 +255,7 @@ const PropertyRegistration* registration, const CSSStyleValueOrString& value, const ExecutionContext& execution_context) { - DCHECK(!property.IsRepeated()); + DCHECK(!IsListValuedProperty(property, registration)); DCHECK_EQ(property.IDEquals(CSSPropertyVariable), !custom_property_name.IsNull()); @@ -233,9 +281,10 @@ const CSSValue* CoerceStyleValuesOrStrings( const CSSProperty& property, const AtomicString& custom_property_name, + const PropertyRegistration* registration, const HeapVector<CSSStyleValueOrString>& values, const ExecutionContext& execution_context) { - DCHECK(property.IsRepeated()); + DCHECK(IsListValuedProperty(property, registration)); DCHECK_EQ(property.IDEquals(CSSPropertyVariable), !custom_property_name.IsNull()); if (values.IsEmpty()) @@ -243,11 +292,18 @@ CSSStyleValueVector style_values = StyleValueFactory::CoerceStyleValuesOrStrings( - property, custom_property_name, nullptr, values, execution_context); + property, custom_property_name, registration, values, + execution_context); if (style_values.IsEmpty()) return nullptr; + if (property.IDEquals(CSSPropertyVariable) && registration) { + CSSParserContext* context = CSSParserContext::Create(execution_context); + return CreateVariableReferenceValue(property, custom_property_name, + *registration, style_values, *context); + } + CSSValueList* result = CssValueListForPropertyID(property.PropertyID()); for (const auto& style_value : style_values) { const CSSValue* css_value = @@ -317,9 +373,10 @@ } const CSSValue* result = nullptr; - if (property.IsRepeated()) { - result = CoerceStyleValuesOrStrings(property, custom_property_name, values, - *execution_context); + if (IsListValuedProperty(property, registration)) { + result = + CoerceStyleValuesOrStrings(property, custom_property_name, registration, + values, *execution_context); } else if (values.size() == 1U) { result = CoerceStyleValueOrString(property, custom_property_name, registration, @@ -351,13 +408,55 @@ return; } + const CSSProperty& property = CSSProperty::Get(property_id); + if (property_id == CSSPropertyVariable) { + AtomicString custom_property_name(property_name); + + const PropertyRegistration* registration = + PropertyRegistration::From(execution_context, custom_property_name); + + if (registration && IsListValuedProperty(property, registration)) { + CSSStyleValueVector style_values; + + // Add existing CSSStyleValues: + if (const CSSValue* css_value = + GetCustomProperty(*execution_context, custom_property_name)) { + DCHECK(css_value->IsValueList()); + style_values = StyleValueFactory::CssValueToStyleValueVector( + property_id, custom_property_name, *css_value); + } + + // Append incoming CSSStyleValues: + CSSStyleValueVector incoming_style_values = + StyleValueFactory::CoerceStyleValuesOrStrings( + property, custom_property_name, registration, values, + *execution_context); + + const CSSValue* result = nullptr; + + if (!incoming_style_values.IsEmpty()) { + style_values.AppendVector(incoming_style_values); + CSSParserContext* context = + CSSParserContext::Create(*execution_context); + result = + CreateVariableReferenceValue(property, custom_property_name, + *registration, style_values, *context); + } + + if (!result) { + exception_state.ThrowTypeError("Invalid type for property"); + return; + } + + SetCustomProperty(custom_property_name, *result); + return; + } exception_state.ThrowTypeError( "Appending to custom properties is not supported"); return; } - const CSSProperty& property = CSSProperty::Get(property_id); if (!property.IsRepeated()) { exception_state.ThrowTypeError("Property does not support multiple values"); return; @@ -371,10 +470,8 @@ current_value = CssValueListForPropertyID(property_id); } - // TODO(andruud): Don't pass g_null_atom as custom property name - // once appending to custom properties is supported. const CSSValue* result = CoerceStyleValuesOrStrings( - property, g_null_atom, values, *execution_context); + property, g_null_atom, nullptr, values, *execution_context); if (!result || !result->IsValueList()) { exception_state.ThrowTypeError("Invalid type for property"); return;
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc index 2a8d480..fa822e5 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
@@ -133,6 +133,18 @@ return !getAll(execution_context, property_name, exception_state).IsEmpty(); } +const CSSValue* StylePropertyMapReadOnly::GetCustomProperty( + const ExecutionContext& execution_context, + const AtomicString& property_name) { + const CSSValue* value = GetCustomProperty(property_name); + + const auto* document = DynamicTo<Document>(execution_context); + if (!document) + return value; + + return PropertyRegistry::ParseIfRegistered(*document, property_name, value); +} + StylePropertyMapReadOnly::IterationSource* StylePropertyMapReadOnly::StartIteration(ScriptState* script_state, ExceptionState&) { @@ -176,16 +188,4 @@ serialization); } -const CSSValue* StylePropertyMapReadOnly::GetCustomProperty( - const ExecutionContext& execution_context, - const AtomicString& property_name) { - const CSSValue* value = GetCustomProperty(property_name); - - const auto* document = DynamicTo<Document>(execution_context); - if (!document) - return value; - - return PropertyRegistry::ParseIfRegistered(*document, property_name, value); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h index 49415543..acf6c42 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h
@@ -50,12 +50,13 @@ virtual String SerializationForShorthand(const CSSProperty&) = 0; + const CSSValue* GetCustomProperty(const ExecutionContext&, + const AtomicString&); + private: IterationSource* StartIteration(ScriptState*, ExceptionState&) override; CSSStyleValue* GetShorthandProperty(const CSSProperty&); - const CSSValue* GetCustomProperty(const ExecutionContext&, - const AtomicString&); private: DISALLOW_COPY_AND_ASSIGN(StylePropertyMapReadOnly);
diff --git a/third_party/blink/renderer/core/dom/element_test.cc b/third_party/blink/renderer/core/dom/element_test.cc index 74d0347..07b9e767 100644 --- a/third_party/blink/renderer/core/dom/element_test.cc +++ b/third_party/blink/renderer/core/dom/element_test.cc
@@ -394,8 +394,8 @@ TEST_F(ElementTest, PartmapAttribute) { Document& document = GetDocument(); SetBodyContent(R"HTML( - <span id='has_one_mapping' partmap='partname1 partname2'></span> - <span id='has_two_mappings' partmap='partname1 partname2, partname3 partname4'></span> + <span id='has_one_mapping' partmap='partname1: partname2'></span> + <span id='has_two_mappings' partmap='partname1: partname2, partname3: partname4'></span> <span id='has_no_mapping'></span> )HTML"); @@ -432,7 +432,7 @@ EXPECT_FALSE(has_no_mapping->PartNamesMap()); // Now update the attribute value and make sure it's reflected. - has_no_mapping->setAttribute("partmap", "partname1 partname2"); + has_no_mapping->setAttribute("partmap", "partname1: partname2"); const NamesMap* part_names_map = has_no_mapping->PartNamesMap(); ASSERT_TRUE(part_names_map); ASSERT_EQ(1UL, part_names_map->size());
diff --git a/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/third_party/blink/renderer/core/dom/idle_deadline_test.cc index aebde6e9..9e5073b8 100644 --- a/third_party/blink/renderer/core/dom/idle_deadline_test.cc +++ b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -8,7 +8,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h" +#include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h" #include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" #include "third_party/blink/renderer/platform/wtf/time.h" @@ -74,7 +74,7 @@ WTF::ScopedMockClock clock_; }; -TEST_F(IdleDeadlineTest, deadlineInFuture) { +TEST_F(IdleDeadlineTest, DeadlineInFuture) { IdleDeadline* deadline = IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25), IdleDeadline::CallbackType::kCalledWhenIdle); @@ -82,18 +82,16 @@ EXPECT_FLOAT_EQ(250.0, deadline->timeRemaining()); } -TEST_F(IdleDeadlineTest, deadlineInPast) { +TEST_F(IdleDeadlineTest, DeadlineInPast) { IdleDeadline* deadline = IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(0.75), IdleDeadline::CallbackType::kCalledWhenIdle); EXPECT_FLOAT_EQ(0, deadline->timeRemaining()); } -TEST_F(IdleDeadlineTest, yieldForHighPriorityWork) { +TEST_F(IdleDeadlineTest, YieldForHighPriorityWork) { MockIdleDeadlineScheduler scheduler; - ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler, - ThreadScheduler*> - platform(&scheduler); + ScopedSchedulerOverrider scheduler_overrider(&scheduler); IdleDeadline* deadline = IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25),
diff --git a/third_party/blink/renderer/core/dom/names_map.cc b/third_party/blink/renderer/core/dom/names_map.cc index 8acb1e5..ad7dbc3 100644 --- a/third_party/blink/renderer/core/dom/names_map.cc +++ b/third_party/blink/renderer/core/dom/names_map.cc
@@ -45,15 +45,34 @@ // second and => is not used to separate key and value. It also allows an ident // token on its own as a short-hand for forwarding with the same name. -// The states that can occur while parsing the part map. {...} denotes the new -// states that can be reached from this state. +// The states that can occur while parsing the part map and their transitions. +// A "+" indicates that this transition should consume the current character. +// A "*" indicates that this is invalid input, usually the decision here is +// to just do our best and recover gracefully. enum State { - kPreKey, // Searching for the start of a key. {kPreKey, kKey} - kKey, // Searching for the end of a key. {kKey, kPreValue} - kPreValue, // Searching for the start of a value. {kPreValue, kPreKey, - // kValue} - kValue, // Searching for the end of a value. {kValue, kPreKey, kPostValue} - kPostValue, // Searching for the comma after the value. {kPostValue, kPreKey} + kPreKey, // Searching for the start of a key: + // space, comma, colon* -> kPreKey+ + // else -> kKey + kKey, // Searching for the end of a key: + // comma -> kPreKey+ + // colon -> kPreValue+ + // space -> kPostKey+ + // else -> kKey+ + kPostKey, // Searching for a delimiter: + // comma -> kPreKey+ + // colon -> kPreValue+ + // space, else* -> kPostKey+ + kPreValue, // Searching for the start of a value: + // comma -> kPreKey+ + // colon*, space -> kPreValue+ + // else -> kValue+ + kValue, // Searching for the end of a value: + // comma -> kPreKey+ + // colon*, space -> kPostValue+ + // else -> kValue+ + kPostValue, // Searching for the comma after the value: + // comma -> kPreKey+ + // colon*, else -> kPostValue+ }; template <typename CharacterType> @@ -69,24 +88,55 @@ State state = kPreKey; AtomicString key; while (cur < length) { + // Almost all cases break, ensuring that some input is consumed and we avoid + // an infinite loop. For the few transitions which should happen without + // consuming input we fall through into the new state's case. This makes it + // easy to see the cases which don't consume input and check that they lead + // to a case which does. + // + // The only state which should set a value for key is kKey, as we leave the + // state. switch (state) { case kPreKey: - // Skip any number of spaces and commas. When we find something else, it - // is the start of a key. - if (!IsHTMLSpaceOrComma<CharacterType>(characters[cur])) { - start = cur; - state = kKey; - } - break; - case kKey: - // At a space or comma, we have found the end of the key. - if (IsHTMLSpaceOrComma<CharacterType>(characters[cur])) { - key = AtomicString(characters + start, cur - start); - state = kPreValue; - } else { + // Skip any number of spaces, commas and colons. When we find something + // else, it is the start of a key. + if ((IsHTMLSpaceOrComma<CharacterType>(characters[cur]) || + IsColon<CharacterType>(characters[cur]))) { break; } + start = cur; + state = kKey; FALLTHROUGH; + case kKey: + // At a comma this was a key without a value, the implicit value is the + // same as the key. + if (IsComma<CharacterType>(characters[cur])) { + key = AtomicString(characters + start, cur - start); + Add(key, key); + state = kPreKey; + // At a colon, we have found the end of the key and we expect a value. + } else if (IsColon<CharacterType>(characters[cur])) { + key = AtomicString(characters + start, cur - start); + state = kPreValue; + // At a space, we have found the end of the key. + } else if (IsHTMLSpace<CharacterType>(characters[cur])) { + key = AtomicString(characters + start, cur - start); + state = kPostKey; + } + break; + case kPostKey: + // At a comma this was a key without a value, the implicit value is the + // same as the key. + if (IsComma<CharacterType>(characters[cur])) { + Add(key, key); + state = kPreKey; + // At a colon this was a key with a value, we expect a value. + } else if (IsColon<CharacterType>(characters[cur])) { + state = kPreValue; + } + // Spaces should be consumed. We consume other characters too + // although the input is invalid + break; case kPreValue: // At a comma this was a key without a value, the implicit value is the // same as the key. @@ -95,20 +145,26 @@ state = kPreKey; // If we reach a non-space character, we have found the start of the // value. - } else if (IsNotHTMLSpace<CharacterType>(characters[cur])) { + } else if (IsColon<CharacterType>(characters[cur]) || + IsHTMLSpace<CharacterType>(characters[cur])) { + break; + } else { start = cur; state = kValue; } break; case kValue: - // At a comma or space, we have found the end of the value. - if (IsHTMLSpaceOrComma<CharacterType>(characters[cur])) { + // At a comma, we have found the end of the value and expect + // the next key. + if (IsComma<CharacterType>(characters[cur])) { Add(key, AtomicString(characters + start, cur - start)); - if (IsComma<CharacterType>(characters[cur])) { - state = kPreKey; - } else { - state = kPostValue; - } + state = kPreKey; + // At a space or colon, we have found the end of the value, + // although a colon is invalid here. + } else if (IsHTMLSpace<CharacterType>(characters[cur]) || + IsColon<CharacterType>(characters[cur])) { + Add(key, AtomicString(characters + start, cur - start)); + state = kPostValue; } break; case kPostValue: @@ -130,6 +186,7 @@ // The string ends with a key. key = AtomicString(characters + start, cur - start); FALLTHROUGH; + case kPostKey: case kPreValue: // The string ends after a key but with nothing else useful. Add(key, key);
diff --git a/third_party/blink/renderer/core/dom/names_map_test.cc b/third_party/blink/renderer/core/dom/names_map_test.cc index db30cc8..995fade 100644 --- a/third_party/blink/renderer/core/dom/names_map_test.cc +++ b/third_party/blink/renderer/core/dom/names_map_test.cc
@@ -29,26 +29,38 @@ Vector<std::pair<String, ExpectedMap>> test_cases({ // Various valid values. {"foo", {{"foo", "foo"}}}, - {"foo bar", {{"foo", "bar"}}}, - {"foo bar, foo buz", {{"foo", "bar buz"}}}, - {"foo bar, buz", {{"foo", "bar"}, {"buz", "buz"}}}, - {"foo bar, buz bar", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo, buz bar", {{"foo", "foo"}, {"buz", "bar"}}}, + {"foo: bar", {{"foo", "bar"}}}, + {"foo : bar", {{"foo", "bar"}}}, + {"foo: bar, foo: buz", {{"foo", "bar buz"}}}, + {"foo: bar, buz", {{"foo", "bar"}, {"buz", "buz"}}}, + {"foo: bar, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo, buz: bar", {{"foo", "foo"}, {"buz", "bar"}}}, // This is an error but qux should be ignored. - {"foo bar qux, buz bar", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo bar, buz bar qux", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar qux, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar qux", {{"foo", "bar"}, {"buz", "bar"}}}, - // This is an error but the extra comma should be ignored. - {",foo bar, buz bar", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo bar,, buz bar", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo bar, buz bar,", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo bar, buz bar,,", {{"foo", "bar"}, {"buz", "bar"}}}, + // This is an error but the extra commas and colons should be ignored. + {"foo:", {{"foo", "foo"}}}, + {"foo:,", {{"foo", "foo"}}}, + {"foo :", {{"foo", "foo"}}}, + {"foo :,", {{"foo", "foo"}}}, + {"foo: bar, buz:", {{"foo", "bar"}, {"buz", "buz"}}}, + {"foo: bar, buz :", {{"foo", "bar"}, {"buz", "buz"}}}, + {",foo: bar, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar,, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar,", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar,,", {{"foo", "bar"}, {"buz", "bar"}}}, + {":foo: bar, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar:, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: :bar, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar:", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar::", {{"foo", "bar"}, {"buz", "bar"}}}, // Spaces in odd places. - {" foo bar, buz bar", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo bar, buz bar", {{"foo", "bar"}, {"buz", "bar"}}}, - {"foo bar, buz bar ", {{"foo", "bar"}, {"buz", "bar"}}}, + {" foo: bar, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar", {{"foo", "bar"}, {"buz", "bar"}}}, + {"foo: bar, buz: bar ", {{"foo", "bar"}, {"buz", "bar"}}}, }); NamesMap map;
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc index 3da0c695..52bb88766 100644 --- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc +++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -6,12 +6,11 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h" #include "third_party/blink/renderer/core/dom/idle_request_options.h" #include "third_party/blink/renderer/core/testing/null_execution_context.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h" +#include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h" #include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -94,9 +93,7 @@ TEST_F(ScriptedIdleTaskControllerTest, RunCallback) { MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::DONT_YIELD); - ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler, - ThreadScheduler*> - platform(&scheduler); + ScopedSchedulerOverrider scheduler_overrider(&scheduler); NullExecutionContext execution_context; ScriptedIdleTaskController* controller = @@ -117,9 +114,7 @@ TEST_F(ScriptedIdleTaskControllerTest, DontRunCallbackWhenAskedToYield) { MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::YIELD); - ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler, - ThreadScheduler*> - platform(&scheduler); + ScopedSchedulerOverrider scheduler_overrider(&scheduler); NullExecutionContext execution_context; ScriptedIdleTaskController* controller =
diff --git a/third_party/blink/renderer/core/exported/web_node.cc b/third_party/blink/renderer/core/exported/web_node.cc index 06ba400..55843e70 100644 --- a/third_party/blink/renderer/core/exported/web_node.cc +++ b/third_party/blink/renderer/core/exported/web_node.cc
@@ -133,6 +133,8 @@ bool WebNode::IsFocusable() const { if (!private_->IsElementNode()) return false; + if (!private_->GetDocument().IsRenderingReady()) + return false; private_->GetDocument().UpdateStyleAndLayoutTreeForNode(private_.Get()); return ToElement(private_.Get())->IsFocusable(); }
diff --git a/third_party/blink/renderer/core/exported/web_node_test.cc b/third_party/blink/renderer/core/exported/web_node_test.cc index bb1d34dc..d16be0d 100644 --- a/third_party/blink/renderer/core/exported/web_node_test.cc +++ b/third_party/blink/renderer/core/exported/web_node_test.cc
@@ -67,7 +67,8 @@ LoadURL("https://example.com/test.html"); WebView().Resize(WebSize(800, 600)); - main_resource.Complete(R"HTML( + main_resource.Start(); + main_resource.Write(R"HTML( <!DOCTYPE html> <link rel=stylesheet href=style.css> <input id=focusable> @@ -79,7 +80,9 @@ WebNode input_node(GetDocument().getElementById("focusable")); EXPECT_FALSE(input_node.IsFocusable()); + EXPECT_FALSE(GetDocument().HasNodesWithPlaceholderStyle()); + main_resource.Finish(); css_resource.Complete("dummy {}"); EXPECT_TRUE(input_node.IsFocusable()); }
diff --git a/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc b/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc index 75ede52..44f49c5 100644 --- a/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc +++ b/third_party/blink/renderer/core/frame/device_single_window_event_controller.cc
@@ -96,7 +96,8 @@ const Document& document = GetDocument(); return std::all_of(features.begin(), features.end(), [&document](mojom::FeaturePolicyFeature feature) { - return document.IsFeatureEnabled(feature); + return document.IsFeatureEnabled( + feature, ReportOptions::kReportOnFailure); }); }
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc index e3143d8..ce6a094 100644 --- a/third_party/blink/renderer/core/html/html_dialog_element.cc +++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -81,10 +81,13 @@ dialog->GetDocument().ClearFocusedElement(); } -static void InertSubtreesChanged(Document& document) { +static void InertSubtreesChanged(Document& document, + HTMLDialogElement& dialog_element) { + // SetIsInert recurses through subframes to propagate the inert bit and that + // needs an up-to-date dialog flat tree distribution: see crbug.com/789094 & + // crbug.com/804047 crash reports. if (document.GetFrame()) { - // SetIsInert recurses through subframes to propagate the inert bit as - // needed. + dialog_element.UpdateDistributionForFlatTreeTraversal(); document.GetFrame()->SetIsInert(document.LocalOwner() && document.LocalOwner()->IsInert()); } @@ -116,7 +119,7 @@ HTMLDialogElement* active_modal_dialog = GetDocument().ActiveModalDialog(); GetDocument().RemoveFromTopLayer(this); if (active_modal_dialog == this) - InertSubtreesChanged(GetDocument()); + InertSubtreesChanged(GetDocument(), *this); if (!return_value.IsNull()) return_value_ = return_value; @@ -172,19 +175,20 @@ GetDocument().AddToTopLayer(this); SetBooleanAttribute(openAttr, true); + ForceLayoutForCentering(); + // Throw away the AX cache first, so the subsequent steps don't have a chance // of queuing up AX events on objects that would be invalidated when the cache // is thrown away. - InertSubtreesChanged(GetDocument()); + InertSubtreesChanged(GetDocument(), *this); - ForceLayoutForCentering(); SetFocusForDialog(this); } void HTMLDialogElement::RemovedFrom(ContainerNode& insertion_point) { HTMLElement::RemovedFrom(insertion_point); SetNotCentered(); - InertSubtreesChanged(GetDocument()); + InertSubtreesChanged(GetDocument(), *this); } void HTMLDialogElement::SetCentered(LayoutUnit centered_position) {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 3ad04be..bee87b974 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -410,23 +410,12 @@ return result; } -URLRegistry* HTMLMediaElement::media_stream_registry_ = nullptr; - const HashSet<AtomicString>& HTMLMediaElement::GetCheckedAttributeNames() const { DEFINE_STATIC_LOCAL(HashSet<AtomicString>, attribute_set, ({"src"})); return attribute_set; } -void HTMLMediaElement::SetMediaStreamRegistry(URLRegistry* registry) { - DCHECK(!media_stream_registry_); - media_stream_registry_ = registry; -} - -bool HTMLMediaElement::IsMediaStreamURL(const String& url) { - return media_stream_registry_ ? media_stream_registry_->Contains(url) : false; -} - bool HTMLMediaElement::IsHLSURL(const KURL& url) { // Keep the same logic as in media_codec_util.h. if (url.IsNull() || url.IsEmpty()) @@ -1410,8 +1399,7 @@ if (media_source_) return WebMediaPlayer::kLoadTypeMediaSource; - if (src_object_ || - (!current_src_.IsNull() && IsMediaStreamURL(current_src_.GetString()))) + if (src_object_) return WebMediaPlayer::kLoadTypeMediaStream; return WebMediaPlayer::kLoadTypeURL; @@ -1990,7 +1978,7 @@ return false; // MediaStream can't be downloaded. - if (IsMediaStreamURL(current_src_.GetString())) + if (GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) return false; // MediaSource can't be downloaded.
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index f2d50264..7e060cf 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -76,7 +76,6 @@ class TextTrackContainer; class TextTrackList; class TimeRanges; -class URLRegistry; class VideoTrack; class VideoTrackList; class WebAudioSourceProvider; @@ -101,8 +100,6 @@ enum class RecordMetricsBehavior { kDoNotRecord, kDoRecord }; - static void SetMediaStreamRegistry(URLRegistry*); - static bool IsMediaStreamURL(const String& url); static bool IsHLSURL(const KURL&); // If HTMLMediaElement is using MediaTracks (either placeholder or provided @@ -753,8 +750,6 @@ Member<HTMLMediaElementControlsList> controls_list_; Member<ElementVisibilityObserver> lazy_load_visibility_observer_; - - static URLRegistry* media_stream_registry_; }; inline bool IsHTMLMediaElement(const HTMLElement& element) {
diff --git a/third_party/blink/renderer/core/html/parser/html_parser_idioms.h b/third_party/blink/renderer/core/html/parser/html_parser_idioms.h index ac928bb..1048d15 100644 --- a/third_party/blink/renderer/core/html/parser/html_parser_idioms.h +++ b/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
@@ -103,6 +103,11 @@ } template <typename CharType> +inline bool IsColon(CharType character) { + return character == ':'; +} + +template <typename CharType> inline bool IsHTMLSpaceOrComma(CharType character) { return IsComma(character) || IsHTMLSpace(character); }
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc index 022104ce..dd222f4 100644 --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
@@ -6,7 +6,6 @@ #include <utility> #include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h" @@ -54,9 +53,9 @@ bool match_all, mojom::blink::BackgroundFetchService::MatchRequestsCallback callback) { GetService()->MatchRequests( - GetSupplementable()->WebRegistration()->RegistrationId(), developer_id, - unique_id, std::move(request_to_match), std::move(cache_query_params), - match_all, std::move(callback)); + GetSupplementable()->RegistrationId(), developer_id, unique_id, + std::move(request_to_match), std::move(cache_query_params), match_all, + std::move(callback)); } void BackgroundFetchBridge::Fetch( @@ -67,8 +66,8 @@ mojom::blink::BackgroundFetchUkmDataPtr ukm_data, RegistrationCallback callback) { GetService()->Fetch( - GetSupplementable()->WebRegistration()->RegistrationId(), developer_id, - std::move(requests), std::move(options), icon, std::move(ukm_data), + GetSupplementable()->RegistrationId(), developer_id, std::move(requests), + std::move(options), icon, std::move(ukm_data), WTF::Bind(&BackgroundFetchBridge::DidGetRegistration, WrapPersistent(this), WTF::Passed(std::move(callback)))); } @@ -76,8 +75,8 @@ void BackgroundFetchBridge::Abort(const String& developer_id, const String& unique_id, AbortCallback callback) { - GetService()->Abort(GetSupplementable()->WebRegistration()->RegistrationId(), - developer_id, unique_id, std::move(callback)); + GetService()->Abort(GetSupplementable()->RegistrationId(), developer_id, + unique_id, std::move(callback)); } void BackgroundFetchBridge::UpdateUI(const String& developer_id, @@ -91,15 +90,14 @@ return; } - GetService()->UpdateUI( - GetSupplementable()->WebRegistration()->RegistrationId(), developer_id, - unique_id, title, icon, std::move(callback)); + GetService()->UpdateUI(GetSupplementable()->RegistrationId(), developer_id, + unique_id, title, icon, std::move(callback)); } void BackgroundFetchBridge::GetRegistration(const String& developer_id, RegistrationCallback callback) { GetService()->GetRegistration( - GetSupplementable()->WebRegistration()->RegistrationId(), developer_id, + GetSupplementable()->RegistrationId(), developer_id, WTF::Bind(&BackgroundFetchBridge::DidGetRegistration, WrapPersistent(this), WTF::Passed(std::move(callback)))); } @@ -121,9 +119,8 @@ } void BackgroundFetchBridge::GetDeveloperIds(GetDeveloperIdsCallback callback) { - GetService()->GetDeveloperIds( - GetSupplementable()->WebRegistration()->RegistrationId(), - std::move(callback)); + GetService()->GetDeveloperIds(GetSupplementable()->RegistrationId(), + std::move(callback)); } void BackgroundFetchBridge::AddRegistrationObserver(
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.cc b/third_party/blink/renderer/modules/background_sync/sync_manager.cc index 18ce043..47de737d 100644 --- a/third_party/blink/renderer/modules/background_sync/sync_manager.cc +++ b/third_party/blink/renderer/modules/background_sync/sync_manager.cc
@@ -44,8 +44,7 @@ blink::mojom::BackgroundSyncNetworkState::ONLINE; GetBackgroundSyncServicePtr()->Register( - std::move(sync_registration), - registration_->WebRegistration()->RegistrationId(), + std::move(sync_registration), registration_->RegistrationId(), WTF::Bind(SyncManager::RegisterCallback, WrapPersistent(resolver))); return promise; @@ -56,7 +55,7 @@ ScriptPromise promise = resolver->Promise(); GetBackgroundSyncServicePtr()->GetRegistrations( - registration_->WebRegistration()->RegistrationId(), + registration_->RegistrationId(), WTF::Bind(&SyncManager::GetRegistrationsCallback, WrapPersistent(resolver)));
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_store.cc b/third_party/blink/renderer/modules/cookie_store/cookie_store.cc index d3a45bab..0248f4b9 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_store.cc +++ b/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
@@ -348,7 +348,7 @@ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); int64_t service_worker_registration_id = - scope->registration()->WebRegistration()->RegistrationId(); + scope->registration()->RegistrationId(); subscription_backend_->AppendSubscriptions( service_worker_registration_id, std::move(backend_subscriptions), WTF::Bind(&CookieStore::OnSubscribeToCookieChangesResult, @@ -374,7 +374,7 @@ ServiceWorkerGlobalScope* scope = ToServiceWorkerGlobalScope(GetExecutionContext()); int64_t service_worker_registration_id = - scope->registration()->WebRegistration()->RegistrationId(); + scope->registration()->RegistrationId(); subscription_backend_->GetSubscriptions( service_worker_registration_id, WTF::Bind(&CookieStore::OnGetCookieChangeSubscriptionResult,
diff --git a/third_party/blink/renderer/modules/exported/BUILD.gn b/third_party/blink/renderer/modules/exported/BUILD.gn index e3030b0..f79e1d1 100644 --- a/third_party/blink/renderer/modules/exported/BUILD.gn +++ b/third_party/blink/renderer/modules/exported/BUILD.gn
@@ -16,7 +16,6 @@ "web_idb_key.cc", "web_idb_key_range.cc", "web_idb_value.cc", - "web_media_stream_registry.cc", "web_storage_event_dispatcher_impl.cc", "web_user_media_request.cc", ]
diff --git a/third_party/blink/renderer/modules/exported/web_media_stream_registry.cc b/third_party/blink/renderer/modules/exported/web_media_stream_registry.cc deleted file mode 100644 index d463018..0000000 --- a/third_party/blink/renderer/modules/exported/web_media_stream_registry.cc +++ /dev/null
@@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/public/web/web_media_stream_registry.h" - -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_url.h" -#include "third_party/blink/renderer/modules/mediastream/media_stream_registry.h" -#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h" -#include "third_party/blink/renderer/platform/weborigin/kurl.h" - -namespace blink { - -WebMediaStream WebMediaStreamRegistry::LookupMediaStreamDescriptor( - const WebURL& url) { - return WebMediaStream( - MediaStreamRegistry::Registry().LookupMediaStreamDescriptor( - KURL(url).GetString())); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc index aa454a8..b69ad79 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
@@ -76,8 +76,7 @@ // state. This allows potential recovery for transient network and decoder // resource issues. const String& url = MediaElement().currentSrc().GetString(); - if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) && - !HTMLMediaSource::Lookup(url)) { + if (MediaElement().error() && !HTMLMediaSource::Lookup(url)) { MediaElement().load(); }
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc index e358f000..81bb8d7 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc
@@ -62,8 +62,7 @@ // state. This allows potential recovery for transient network and decoder // resource issues. const String& url = MediaElement().currentSrc().GetString(); - if (MediaElement().error() && !HTMLMediaElement::IsMediaStreamURL(url) && - !HTMLMediaSource::Lookup(url)) + if (MediaElement().error() && !HTMLMediaSource::Lookup(url)) MediaElement().load(); MediaElement().TogglePlayState();
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc index c396e06..fb74690 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -15,7 +15,6 @@ #include "third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h" #include "third_party/blink/renderer/modules/encryptedmedia/media_keys.h" #include "third_party/blink/renderer/modules/mediastream/media_stream.h" -#include "third_party/blink/renderer/modules/mediastream/media_stream_registry.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_center.h" namespace blink { @@ -78,11 +77,7 @@ track->stopTrack(context); media_stream_->RemoveTrackByComponentAndFireEvents(track->Component()); } - MediaStreamDescriptor* const descriptor = - media_element_->currentSrc().IsEmpty() - ? media_element_->GetSrcObject() - : MediaStreamRegistry::Registry().LookupMediaStreamDescriptor( - media_element_->currentSrc().GetString()); + MediaStreamDescriptor* const descriptor = media_element_->GetSrcObject(); DCHECK(descriptor); for (unsigned i = 0; i < descriptor->NumberOfAudioComponents(); i++) { media_stream_->AddTrackByComponentAndFireEvents( @@ -182,11 +177,7 @@ // If |element| is actually playing a MediaStream, just clone it. if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) { - MediaStreamDescriptor* const descriptor = - element.currentSrc().IsEmpty() - ? element.GetSrcObject() - : MediaStreamRegistry::Registry().LookupMediaStreamDescriptor( - element.currentSrc().GetString()); + MediaStreamDescriptor* const descriptor = element.GetSrcObject(); DCHECK(descriptor); return MediaStream::Create(context, descriptor); }
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn index e77eb497..fb4d8b6 100644 --- a/third_party/blink/renderer/modules/mediastream/BUILD.gn +++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -23,8 +23,6 @@ "media_stream.h", "media_stream_event.cc", "media_stream_event.h", - "media_stream_registry.cc", - "media_stream_registry.h", "media_stream_track.cc", "media_stream_track.h", "media_stream_track_content_hint.h",
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.cc b/third_party/blink/renderer/modules/mediastream/media_stream.cc index feef966d..f435bb5 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream.cc
@@ -28,7 +28,6 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/frame/deprecation.h" -#include "third_party/blink/renderer/modules/mediastream/media_stream_registry.h" #include "third_party/blink/renderer/modules/mediastream/media_stream_track_event.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" @@ -494,10 +493,6 @@ events.clear(); } -URLRegistry& MediaStream::Registry() const { - return MediaStreamRegistry::Registry(); -} - void MediaStream::Trace(blink::Visitor* visitor) { visitor->Trace(audio_tracks_); visitor->Trace(video_tracks_);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.h b/third_party/blink/renderer/modules/mediastream/media_stream.h index 8b815ef7..7f119d1 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream.h
@@ -26,7 +26,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_H_ -#include "third_party/blink/renderer/core/fileapi/url_registry.h" #include "third_party/blink/renderer/modules/event_target_modules.h" #include "third_party/blink/renderer/modules/mediastream/media_stream_track.h" #include "third_party/blink/renderer/modules/modules_export.h" @@ -53,7 +52,6 @@ class MODULES_EXPORT MediaStream final : public EventTargetWithInlineData, public ContextClient, - public URLRegistrable, public MediaStreamDescriptorClient { USING_GARBAGE_COLLECTED_MIXIN(MediaStream); DEFINE_WRAPPERTYPEINFO(); @@ -127,9 +125,6 @@ return ContextClient::GetExecutionContext(); } - // URLRegistrable - URLRegistry& Registry() const override; - void Trace(blink::Visitor*) override; protected:
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_registry.cc b/third_party/blink/renderer/modules/mediastream/media_stream_registry.cc deleted file mode 100644 index db5b71d3..0000000 --- a/third_party/blink/renderer/modules/mediastream/media_stream_registry.cc +++ /dev/null
@@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/modules/mediastream/media_stream_registry.h" - -#include "third_party/blink/renderer/core/html/media/html_media_element.h" -#include "third_party/blink/renderer/modules/mediastream/media_stream.h" -#include "third_party/blink/renderer/platform/weborigin/kurl.h" - -namespace blink { - -MediaStreamRegistry& MediaStreamRegistry::Registry() { - // Since WebWorkers cannot obtain MediaStream objects, we should be on the - // main thread. - DCHECK(IsMainThread()); - DEFINE_STATIC_LOCAL(MediaStreamRegistry, instance, ()); - return instance; -} - -void MediaStreamRegistry::RegisterURL(SecurityOrigin*, - const KURL& url, - URLRegistrable* stream) { - DCHECK(&stream->Registry() == this); - DCHECK(IsMainThread()); - stream_descriptors_->Set(url.GetString(), - static_cast<MediaStream*>(stream)->Descriptor()); -} - -void MediaStreamRegistry::UnregisterURL(const KURL& url) { - DCHECK(IsMainThread()); - stream_descriptors_->erase(url.GetString()); -} - -bool MediaStreamRegistry::Contains(const String& url) { - DCHECK(IsMainThread()); - return stream_descriptors_->Contains(url); -} - -MediaStreamDescriptor* MediaStreamRegistry::LookupMediaStreamDescriptor( - const String& url) { - DCHECK(IsMainThread()); - return stream_descriptors_->at(url); -} - -MediaStreamRegistry::MediaStreamRegistry() - : stream_descriptors_( - new HeapHashMap<String, Member<MediaStreamDescriptor>>) { - HTMLMediaElement::SetMediaStreamRegistry(this); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_registry.h b/third_party/blink/renderer/modules/mediastream/media_stream_registry.h deleted file mode 100644 index 8f34641d..0000000 --- a/third_party/blink/renderer/modules/mediastream/media_stream_registry.h +++ /dev/null
@@ -1,60 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_REGISTRY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_REGISTRY_H_ - -#include "third_party/blink/renderer/core/fileapi/url_registry.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" -#include "third_party/blink/renderer/platform/wtf/text/string_hash.h" - -namespace blink { - -class KURL; -class MediaStreamDescriptor; - -class MODULES_EXPORT MediaStreamRegistry final : public URLRegistry { - public: - // Returns a single instance of MediaStreamRegistry. - static MediaStreamRegistry& Registry(); - - // Registers a blob URL referring to the specified stream data. - void RegisterURL(SecurityOrigin*, const KURL&, URLRegistrable*) override; - void UnregisterURL(const KURL&) override; - bool Contains(const String&) override; - - MediaStreamDescriptor* LookupMediaStreamDescriptor(const String& url); - - private: - MediaStreamRegistry(); - Persistent<HeapHashMap<String, Member<MediaStreamDescriptor>>> - stream_descriptors_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_REGISTRY_H_
diff --git a/third_party/blink/renderer/modules/notifications/notification_manager.cc b/third_party/blink/renderer/modules/notifications/notification_manager.cc index 36bc76a3..d4d6d33 100644 --- a/third_party/blink/renderer/modules/notifications/notification_manager.cc +++ b/third_party/blink/renderer/modules/notifications/notification_manager.cc
@@ -129,7 +129,7 @@ } void NotificationManager::DisplayPersistentNotification( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, mojom::blink::NotificationDataPtr notification_data, mojom::blink::NotificationResourcesPtr notification_resources, ScriptPromiseResolver* resolver) { @@ -165,8 +165,8 @@ } GetNotificationService()->DisplayPersistentNotification( - service_worker_registration->RegistrationId(), - std::move(notification_data), std::move(notification_resources), + service_worker_registration_id, std::move(notification_data), + std::move(notification_resources), WTF::Bind(&NotificationManager::DidDisplayPersistentNotification, WrapPersistent(this), WrapPersistent(resolver))); } @@ -193,11 +193,11 @@ } void NotificationManager::GetNotifications( - WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, const WebString& filter_tag, ScriptPromiseResolver* resolver) { GetNotificationService()->GetNotifications( - service_worker_registration->RegistrationId(), filter_tag, + service_worker_registration_id, filter_tag, WTF::Bind(&NotificationManager::DidGetNotifications, WrapPersistent(this), WrapPersistent(resolver))); }
diff --git a/third_party/blink/renderer/modules/notifications/notification_manager.h b/third_party/blink/renderer/modules/notifications/notification_manager.h index 98871553..7a8148d 100644 --- a/third_party/blink/renderer/modules/notifications/notification_manager.h +++ b/third_party/blink/renderer/modules/notifications/notification_manager.h
@@ -18,7 +18,6 @@ class ScriptPromise; class ScriptPromiseResolver; class ScriptState; -class WebServiceWorkerRegistration; // The notification manager, unique to the execution context, is responsible for // connecting and communicating with the Mojo notification service. @@ -61,7 +60,7 @@ // Shows a notification from a service worker. void DisplayPersistentNotification( - blink::WebServiceWorkerRegistration* service_worker_registration, + int64_t service_worker_registration_id, mojom::blink::NotificationDataPtr notification_data, mojom::blink::NotificationResourcesPtr notification_resources, ScriptPromiseResolver* resolver); @@ -72,10 +71,9 @@ // Asynchronously gets the persistent notifications belonging to the Service // Worker Registration. If |filter_tag| is not an empty string, only the // notification with the given tag will be considered. - void GetNotifications( - WebServiceWorkerRegistration* service_worker_registration, - const WebString& filter_tag, - ScriptPromiseResolver* resolver); + void GetNotifications(int64_t service_worker_registration_id, + const WebString& filter_tag, + ScriptPromiseResolver* resolver); void Trace(blink::Visitor* visitor) override;
diff --git a/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc b/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc index 72dba71..33d08e5c 100644 --- a/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc +++ b/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc
@@ -87,7 +87,7 @@ ExecutionContext* execution_context = ExecutionContext::From(script_state); NotificationManager::From(execution_context) - ->GetNotifications(registration.WebRegistration(), options.tag(), + ->GetNotifications(registration.RegistrationId(), options.tag(), WrapPersistent(resolver)); return promise; } @@ -144,7 +144,7 @@ DCHECK(loaders_.Contains(loader)); NotificationManager::From(GetExecutionContext()) - ->DisplayPersistentNotification(registration_->WebRegistration(), + ->DisplayPersistentNotification(registration_->RegistrationId(), std::move(data), loader->GetResources(), WrapPersistent(resolver)); loaders_.erase(loader);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc index fe216c25..e1895c44 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
@@ -237,7 +237,7 @@ return nullptr; } -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateIncomingDynamicStream( +P2PQuicStreamImpl* P2PQuicTransportImpl::CreateIncomingStream( quic::QuicStreamId id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); P2PQuicStreamImpl* stream = CreateStreamInternal(id);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h index 609f223c..60c85ef 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h
@@ -104,7 +104,7 @@ // Creates a new stream initiated from the remote side. The caller does not // own the stream, so the stream is activated and ownership is moved to the // quic::QuicSession. - P2PQuicStreamImpl* CreateIncomingDynamicStream( + P2PQuicStreamImpl* CreateIncomingStream( quic::QuicStreamId id) override; // Creates a new outgoing stream. The caller does not own the
diff --git a/third_party/blink/renderer/modules/push_messaging/push_manager.cc b/third_party/blink/renderer/modules/push_messaging/push_manager.cc index a4760fb..44fb9ac5 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_manager.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_manager.cc
@@ -79,13 +79,13 @@ DOMException::Create(DOMExceptionCode::kInvalidStateError, "Document is detached from window.")); PushController::ClientFrom(frame).Subscribe( - registration_->WebRegistration(), web_options, + registration_->RegistrationId(), web_options, LocalFrame::HasTransientUserActivation(frame, true /* check_if_main_thread */), std::make_unique<PushSubscriptionCallbacks>(resolver, registration_)); } else { PushProvider()->Subscribe( - registration_->WebRegistration(), web_options, + registration_->RegistrationId(), web_options, LocalFrame::HasTransientUserActivation(nullptr, true /* check_if_main_thread */), std::make_unique<PushSubscriptionCallbacks>(resolver, registration_)); @@ -99,7 +99,7 @@ ScriptPromise promise = resolver->Promise(); PushProvider()->GetSubscription( - registration_->WebRegistration(), + registration_->RegistrationId(), std::make_unique<PushSubscriptionCallbacks>(resolver, registration_)); return promise; }
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription.cc b/third_party/blink/renderer/modules/push_messaging/push_subscription.cc index 2e2032d..625124a 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_subscription.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
@@ -98,7 +98,7 @@ DCHECK(web_push_provider); web_push_provider->Unsubscribe( - service_worker_registration_->WebRegistration(), + service_worker_registration_->RegistrationId(), std::make_unique<CallbackPromiseAdapter<bool, PushError>>(resolver)); return promise; }
diff --git a/third_party/blink/renderer/modules/sensor/sensor.cc b/third_party/blink/renderer/modules/sensor/sensor.cc index 36fc023..a3680cf 100644 --- a/third_party/blink/renderer/modules/sensor/sensor.cc +++ b/third_party/blink/renderer/modules/sensor/sensor.cc
@@ -26,7 +26,8 @@ const Vector<mojom::FeaturePolicyFeature>& features) { return std::all_of(features.begin(), features.end(), [document](mojom::FeaturePolicyFeature feature) { - return document->IsFeatureEnabled(feature); + return document->IsFeatureEnabled( + feature, ReportOptions::kReportOnFailure); }); }
diff --git a/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc b/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc index e64157b..21078ebab 100644 --- a/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc +++ b/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc
@@ -36,7 +36,7 @@ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); - registration_->WebRegistration()->SetNavigationPreloadHeader( + registration_->SetNavigationPreloadHeader( value, std::make_unique<SetNavigationPreloadHeaderCallbacks>(resolver)); return promise; } @@ -44,7 +44,7 @@ ScriptPromise NavigationPreloadManager::getState(ScriptState* script_state) { ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); - registration_->WebRegistration()->GetNavigationPreloadState( + registration_->GetNavigationPreloadState( std::make_unique<GetNavigationPreloadStateCallbacks>(resolver)); return promise; } @@ -57,7 +57,7 @@ ScriptState* script_state) { ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise promise = resolver->Promise(); - registration_->WebRegistration()->EnableNavigationPreload( + registration_->EnableNavigationPreload( enable, std::make_unique<EnableNavigationPreloadCallbacks>(resolver)); return promise; }
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc b/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc index bb51581..06ff633b 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc
@@ -79,6 +79,10 @@ return navigation_preload_; } +int64_t ServiceWorkerRegistration::RegistrationId() const { + return handle_->Registration()->RegistrationId(); +} + String ServiceWorkerRegistration::scope() const { return handle_->Registration()->Scope().GetString(); } @@ -96,6 +100,31 @@ return ""; } +void ServiceWorkerRegistration::EnableNavigationPreload( + bool enable, + std::unique_ptr< + WebServiceWorkerRegistration::WebEnableNavigationPreloadCallbacks> + callbacks) { + handle_->Registration()->EnableNavigationPreload(enable, + std::move(callbacks)); +} + +void ServiceWorkerRegistration::GetNavigationPreloadState( + std::unique_ptr< + WebServiceWorkerRegistration::WebGetNavigationPreloadStateCallbacks> + callbacks) { + handle_->Registration()->GetNavigationPreloadState(std::move(callbacks)); +} + +void ServiceWorkerRegistration::SetNavigationPreloadHeader( + const WebString& value, + std::unique_ptr< + WebServiceWorkerRegistration::WebSetNavigationPreloadHeaderCallbacks> + callbacks) { + handle_->Registration()->SetNavigationPreloadHeader(value, + std::move(callbacks)); +} + ScriptPromise ServiceWorkerRegistration::update(ScriptState* script_state) { if (!GetExecutionContext()) { return ScriptPromise::RejectWithDOMException(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_registration.h b/third_party/blink/renderer/modules/service_worker/service_worker_registration.h index 70d5bbfe..d472cb53 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_registration.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_registration.h
@@ -73,9 +73,19 @@ String scope() const; String updateViaCache() const; - WebServiceWorkerRegistration* WebRegistration() { - return handle_->Registration(); - } + int64_t RegistrationId() const; + + void EnableNavigationPreload( + bool enable, + std::unique_ptr< + WebServiceWorkerRegistration::WebEnableNavigationPreloadCallbacks>); + void GetNavigationPreloadState( + std::unique_ptr< + WebServiceWorkerRegistration::WebGetNavigationPreloadStateCallbacks>); + void SetNavigationPreloadHeader( + const WebString& value, + std::unique_ptr<WebServiceWorkerRegistration:: + WebSetNavigationPreloadHeaderCallbacks>); ScriptPromise update(ScriptState*); ScriptPromise unregister(ScriptState*);
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 1f0518e9cc..1e4de767 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1574,15 +1574,17 @@ "testing/picture_matchers.h", "testing/scoped_fake_plugin_registry.cc", "testing/scoped_fake_plugin_registry.h", + "testing/scoped_main_thread_overrider.cc", + "testing/scoped_main_thread_overrider.h", "testing/scoped_mocked_url.cc", "testing/scoped_mocked_url.h", + "testing/scoped_scheduler_overrider.cc", + "testing/scoped_scheduler_overrider.h", "testing/stub_graphics_layer_client.h", "testing/test_paint_artifact.cc", "testing/test_paint_artifact.h", "testing/testing_platform_support.cc", "testing/testing_platform_support.h", - "testing/testing_platform_support_with_custom_scheduler.cc", - "testing/testing_platform_support_with_custom_scheduler.h", "testing/testing_platform_support_with_mock_scheduler.cc", "testing/testing_platform_support_with_mock_scheduler.h", "testing/testing_platform_support_with_web_rtc.cc",
diff --git a/third_party/blink/renderer/platform/exported/platform.cc b/third_party/blink/renderer/platform/exported/platform.cc index 13a3cf4..1ee5e5dd 100644 --- a/third_party/blink/renderer/platform/exported/platform.cc +++ b/third_party/blink/renderer/platform/exported/platform.cc
@@ -33,7 +33,6 @@ #include <memory> #include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" @@ -113,7 +112,7 @@ CrossThreadBind(function, CrossThreadUnretained(context))); } -Platform::Platform() : main_thread_(nullptr) { +Platform::Platform() { WTF::Partitions::Initialize(MaxObservedSizeFunction); } @@ -170,27 +169,22 @@ DCHECK(!g_platform); DCHECK(platform); g_platform = platform; - g_platform->owned_main_thread_ = main_thread_scheduler->CreateMainThread(); - g_platform->main_thread_ = g_platform->owned_main_thread_.get(); - DCHECK(!g_platform->current_thread_slot_.Get()); - g_platform->current_thread_slot_.Set(g_platform->main_thread_); - InitializeCommon(platform); + InitializeCommon(platform, main_thread_scheduler->CreateMainThread()); } void Platform::CreateMainThreadAndInitialize(Platform* platform) { DCHECK(!g_platform); DCHECK(platform); g_platform = platform; - g_platform->owned_main_thread_ = std::make_unique<SimpleMainThread>(); - g_platform->main_thread_ = g_platform->owned_main_thread_.get(); - DCHECK(!g_platform->current_thread_slot_.Get()); - g_platform->current_thread_slot_.Set(g_platform->main_thread_); - InitializeCommon(platform); + InitializeCommon(platform, std::make_unique<SimpleMainThread>()); } -void Platform::InitializeCommon(Platform* platform) { +void Platform::InitializeCommon(Platform* platform, + std::unique_ptr<Thread> main_thread) { WTF::Initialize(CallOnMainThreadFunction); + Thread::SetMainThread(std::move(main_thread)); + ProcessHeap::Init(); MemoryCoordinator::Initialize(); if (base::ThreadTaskRunnerHandle::IsSet()) { @@ -208,63 +202,45 @@ FontFamilyNames::init(); InitializePlatformLanguage(); - // TODO(ssid): remove this check after fixing crbug.com/486782. - if (g_platform->main_thread_) { - DCHECK(!g_gc_task_runner); - g_gc_task_runner = new GCTaskRunner(g_platform->main_thread_); - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - PartitionAllocMemoryDumpProvider::Instance(), "PartitionAlloc", - base::ThreadTaskRunnerHandle::Get()); - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - FontCacheMemoryDumpProvider::Instance(), "FontCaches", - base::ThreadTaskRunnerHandle::Get()); - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - MemoryCacheDumpProvider::Instance(), "MemoryCache", - base::ThreadTaskRunnerHandle::Get()); - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - InstanceCountersMemoryDumpProvider::Instance(), "BlinkObjectCounters", - base::ThreadTaskRunnerHandle::Get()); - } + DCHECK(!g_gc_task_runner); + g_gc_task_runner = new GCTaskRunner(Thread::MainThread()); + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + PartitionAllocMemoryDumpProvider::Instance(), "PartitionAlloc", + base::ThreadTaskRunnerHandle::Get()); + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + FontCacheMemoryDumpProvider::Instance(), "FontCaches", + base::ThreadTaskRunnerHandle::Get()); + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + MemoryCacheDumpProvider::Instance(), "MemoryCache", + base::ThreadTaskRunnerHandle::Get()); + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + InstanceCountersMemoryDumpProvider::Instance(), "BlinkObjectCounters", + base::ThreadTaskRunnerHandle::Get()); RendererResourceCoordinator::Initialize(); } void Platform::SetCurrentPlatformForTesting(Platform* platform) { DCHECK(platform); - - // The overriding platform does not necessarily own the main thread - // (owned_main_thread_ may be null), but must have a pointer to a valid - // main thread object (which may be from the overridden platform). - // - // If the new platform's main_thread_ is null, that means we need to - // create a new main thread for it. This happens only in - // ScopedUnittestsEnvironmentSetup's constructor, which bypasses - // Platform::Initialize(). - if (!platform->main_thread_) { - platform->owned_main_thread_ = std::make_unique<SimpleMainThread>(); - platform->main_thread_ = platform->owned_main_thread_.get(); - } - - // Set only the main thread to TLS for the new platform. This is OK for the - // testing purposes. The TLS slot may already be set when - // ScopedTestingPlatformSupport tries to revert to the old platform. - if (!platform->current_thread_slot_.Get()) - platform->current_thread_slot_.Set(platform->main_thread_); - g_platform = platform; } +void Platform::CreateMainThreadForTesting() { + DCHECK(!Thread::MainThread()); + Thread::SetMainThread(std::make_unique<SimpleMainThread>()); +} + void Platform::SetMainThreadTaskRunnerForTesting() { DCHECK(WTF::IsMainThread()); - DCHECK(g_platform->main_thread_->IsSimpleMainThread()); - static_cast<SimpleMainThread*>(g_platform->main_thread_) + DCHECK(Thread::MainThread()->IsSimpleMainThread()); + static_cast<SimpleMainThread*>(Thread::MainThread()) ->SetMainThreadTaskRunnerForTesting(base::ThreadTaskRunnerHandle::Get()); } void Platform::UnsetMainThreadTaskRunnerForTesting() { DCHECK(WTF::IsMainThread()); - DCHECK(g_platform->main_thread_->IsSimpleMainThread()); - static_cast<SimpleMainThread*>(g_platform->main_thread_) + DCHECK(Thread::MainThread()->IsSimpleMainThread()); + static_cast<SimpleMainThread*>(Thread::MainThread()) ->SetMainThreadTaskRunnerForTesting(nullptr); } @@ -273,11 +249,11 @@ } Thread* Platform::MainThread() { - return main_thread_; + return Thread::MainThread(); } Thread* Platform::CurrentThread() { - return static_cast<Thread*>(current_thread_slot_.Get()); + return Thread::Current(); } service_manager::Connector* Platform::GetConnector() { @@ -305,57 +281,19 @@ std::unique_ptr<Thread> Platform::CreateThread( const ThreadCreationParams& params) { - std::unique_ptr<scheduler::WebThreadBase> thread = - scheduler::WebThreadBase::CreateWorkerThread(params); - thread->Init(); - WaitUntilThreadTLSUpdate(thread.get()); - return std::move(thread); + return Thread::CreateThread(params); } std::unique_ptr<Thread> Platform::CreateWebAudioThread() { - ThreadCreationParams params(WebThreadType::kWebAudioThread); - // WebAudio uses a thread with |DISPLAY| priority to avoid glitch when the - // system is under the high pressure. Note that the main browser thread also - // runs with same priority. (see: crbug.com/734539) - params.thread_options.priority = base::ThreadPriority::DISPLAY; - return CreateThread(params); + return Thread::CreateWebAudioThread(); } -void Platform::WaitUntilThreadTLSUpdate(Thread* thread) { - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); - // This cross-thread posting is guaranteed to be safe. - PostCrossThreadTask(*thread->GetTaskRunner(), FROM_HERE, - CrossThreadBind(&Platform::UpdateThreadTLS, - WTF::CrossThreadUnretained(this), - WTF::CrossThreadUnretained(thread), - WTF::CrossThreadUnretained(&event))); - event.Wait(); -} - -void Platform::UpdateThreadTLS(Thread* thread, base::WaitableEvent* event) { - DCHECK(!current_thread_slot_.Get()); - current_thread_slot_.Set(thread); - event->Signal(); -} - -void Platform::InitializeCompositorThread() { - DCHECK(!compositor_thread_); - - ThreadCreationParams params(WebThreadType::kCompositorThread); -#if defined(OS_ANDROID) - params.thread_options.priority = base::ThreadPriority::DISPLAY; -#endif - std::unique_ptr<scheduler::WebThreadBase> compositor_thread = - scheduler::WebThreadBase::CreateCompositorThread(params); - compositor_thread->Init(); - WaitUntilThreadTLSUpdate(compositor_thread.get()); - compositor_thread_ = std::move(compositor_thread); - SetDisplayThreadPriority(compositor_thread_->ThreadId()); +void Platform::CreateAndSetCompositorThread() { + Thread::CreateAndSetCompositorThread(); } Thread* Platform::CompositorThread() { - return compositor_thread_.get(); + return Thread::CompositorThread(); } scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/third_party/blink/renderer/platform/scheduler/common/thread.cc b/third_party/blink/renderer/platform/scheduler/common/thread.cc index bb3b7ad..7875408a 100644 --- a/third_party/blink/renderer/platform/scheduler/common/thread.cc +++ b/third_party/blink/renderer/platform/scheduler/common/thread.cc
@@ -5,8 +5,15 @@ #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" #include "build/build_config.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/scheduler/child/webthread_base.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/web_task_runner.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" +#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" +#include "third_party/blink/renderer/platform/wtf/thread_specific.h" #if defined(OS_WIN) #include <windows.h> @@ -16,6 +23,46 @@ namespace blink { +namespace { + +// Thread-local storage for "blink::Thread"s. +Thread*& ThreadTLSSlot() { + DEFINE_THREAD_SAFE_STATIC_LOCAL(WTF::ThreadSpecific<Thread*>, thread_tls_slot, + ()); + return *thread_tls_slot; +} + +// Update the threads TLS on the newly created thread. +void UpdateThreadTLS(Thread* thread, base::WaitableEvent* event) { + ThreadTLSSlot() = thread; + event->Signal(); +} + +// Post a task to register |thread| to the TLS, and wait until it gets actually +// registered. This is called on a thread that created |thread| (not on +// |thread|.) +void UpdateThreadTLSAndWait(Thread* thread) { + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, + base::WaitableEvent::InitialState::NOT_SIGNALED); + PostCrossThreadTask( + *thread->GetTaskRunner(), FROM_HERE, + CrossThreadBind(&UpdateThreadTLS, WTF::CrossThreadUnretained(thread), + WTF::CrossThreadUnretained(&event))); + event.Wait(); +} + +std::unique_ptr<Thread>& GetMainThread() { + DEFINE_STATIC_LOCAL(std::unique_ptr<Thread>, main_thread, ()); + return main_thread; +} + +std::unique_ptr<Thread>& GetCompositorThread() { + DEFINE_STATIC_LOCAL(std::unique_ptr<Thread>, compositor_thread, ()); + return compositor_thread; +} + +} // namespace + ThreadCreationParams::ThreadCreationParams(WebThreadType thread_type) : thread_type(thread_type), name(GetNameForThreadType(thread_type)), @@ -33,6 +80,59 @@ return *this; } +std::unique_ptr<Thread> Thread::CreateThread( + const ThreadCreationParams& params) { + std::unique_ptr<scheduler::WebThreadBase> thread = + scheduler::WebThreadBase::CreateWorkerThread(params); + thread->Init(); + UpdateThreadTLSAndWait(thread.get()); + return std::move(thread); +} + +std::unique_ptr<Thread> Thread::CreateWebAudioThread() { + ThreadCreationParams params(WebThreadType::kWebAudioThread); + // WebAudio uses a thread with |DISPLAY| priority to avoid glitch when the + // system is under the high pressure. Note that the main browser thread also + // runs with same priority. (see: crbug.com/734539) + params.thread_options.priority = base::ThreadPriority::DISPLAY; + return CreateThread(params); +} + +void Thread::CreateAndSetCompositorThread() { + DCHECK(!GetCompositorThread()); + + ThreadCreationParams params(WebThreadType::kCompositorThread); +#if defined(OS_ANDROID) + params.thread_options.priority = base::ThreadPriority::DISPLAY; +#endif + std::unique_ptr<scheduler::WebThreadBase> compositor_thread = + scheduler::WebThreadBase::CreateCompositorThread(params); + compositor_thread->Init(); + UpdateThreadTLSAndWait(compositor_thread.get()); + GetCompositorThread() = std::move(compositor_thread); + Platform::Current()->SetDisplayThreadPriority( + GetCompositorThread()->ThreadId()); +} + +Thread* Thread::Current() { + return ThreadTLSSlot(); +} + +Thread* Thread::MainThread() { + return GetMainThread().get(); +} + +Thread* Thread::CompositorThread() { + return GetCompositorThread().get(); +} + +std::unique_ptr<Thread> Thread::SetMainThread( + std::unique_ptr<Thread> main_thread) { + ThreadTLSSlot() = main_thread.get(); + std::swap(GetMainThread(), main_thread); + return main_thread; +} + #if defined(OS_WIN) static_assert(sizeof(blink::PlatformThreadId) >= sizeof(DWORD), "size of platform thread id is too small");
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread.h b/third_party/blink/renderer/platform/scheduler/public/thread.h index 61f99d1..8322e98 100644 --- a/third_party/blink/renderer/platform/scheduler/public/thread.h +++ b/third_party/blink/renderer/platform/scheduler/public/thread.h
@@ -70,7 +70,8 @@ // run. class PLATFORM_EXPORT Thread { public: - friend class Platform; // For IsSimpleMainThread(). + friend class Platform; // For SetMainThread() and IsSimpleMainThread(). + friend class ScopedMainThreadOverrider; // For SetMainThread(). // An IdleTask is expected to complete before the deadline it is passed. using IdleTask = base::OnceCallback<void(base::TimeTicks deadline)>; @@ -82,6 +83,28 @@ virtual void DidProcessTask() = 0; }; + // Creates a new thread. This may be called from a non-main thread (e.g. + // nested Web workers). + static std::unique_ptr<Thread> CreateThread(const ThreadCreationParams&); + + // Creates a WebAudio-specific thread with the elevated priority. Do NOT use + // for any other purpose. + static std::unique_ptr<Thread> CreateWebAudioThread(); + + // Create and save (as a global variable) the compositor thread. The thread + // will be accessible through CompositorThread(). + static void CreateAndSetCompositorThread(); + + // Return an interface to the current thread. + static Thread* Current(); + + // Return an interface to the main thread. + static Thread* MainThread(); + + // Return an interface to the compositor thread (if initialized). This can be + // null if the renderer was created with threaded rendering disabled. + static Thread* CompositorThread(); + // DEPRECATED: Returns a task runner bound to the underlying scheduler's // default task queue. // @@ -118,6 +141,13 @@ virtual ~Thread() = default; private: + // For Platform and ScopedMainThreadOverrider. Return the thread object + // previously set (if any). + // + // This is done this way because we need to be able to "override" the main + // thread temporarily for ScopedTestingPlatformSupport. + static std::unique_ptr<Thread> SetMainThread(std::unique_ptr<Thread>); + // This is used to identify the actual Thread instance. This should be // used only in Platform, and other users should ignore this. virtual bool IsSimpleMainThread() const { return false; }
diff --git a/third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.cc b/third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.cc new file mode 100644 index 0000000..cc7d56f --- /dev/null +++ b/third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.cc
@@ -0,0 +1,17 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h" + +namespace blink { + +ScopedMainThreadOverrider::ScopedMainThreadOverrider( + std::unique_ptr<Thread> main_thread) + : original_main_thread_(Thread::SetMainThread(std::move(main_thread))) {} + +ScopedMainThreadOverrider::~ScopedMainThreadOverrider() { + Thread::SetMainThread(std::move(original_main_thread_)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h b/third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h new file mode 100644 index 0000000..dbe1719 --- /dev/null +++ b/third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_MAIN_THREAD_OVERRIDER_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_MAIN_THREAD_OVERRIDER_H_ + +#include <memory> +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" + +namespace blink { + +// This class instance lets you override the main thread (of type blink::Thread) +// temporarily. This is useful when you want to change the main thread scheduler +// during a test (see ScopedSchedulerOverrider). +// +// When ScopedMainThreadOverrider goes out of scope, the main thread is +// reverted back to the original one, and the main thread object passed in +// the constructor gets destructed. + +class ScopedMainThreadOverrider final { + public: + explicit ScopedMainThreadOverrider(std::unique_ptr<Thread> main_thread); + ~ScopedMainThreadOverrider(); + + private: + std::unique_ptr<Thread> original_main_thread_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_MAIN_THREAD_OVERRIDER_H_
diff --git a/third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.cc b/third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.cc new file mode 100644 index 0000000..82ff3d3 --- /dev/null +++ b/third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.cc
@@ -0,0 +1,37 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h" + +#include "third_party/blink/renderer/platform/wtf/wtf.h" + +namespace blink { + +namespace { + +class ThreadWithCustomScheduler : public Thread { + public: + explicit ThreadWithCustomScheduler(ThreadScheduler* scheduler) + : scheduler_(scheduler) {} + ~ThreadWithCustomScheduler() override {} + + bool IsCurrentThread() const override { + DCHECK(WTF::IsMainThread()); + return true; + } + ThreadScheduler* Scheduler() override { return scheduler_; } + + private: + ThreadScheduler* scheduler_; +}; + +} // namespace + +ScopedSchedulerOverrider::ScopedSchedulerOverrider(ThreadScheduler* scheduler) + : main_thread_overrider_( + std::make_unique<ThreadWithCustomScheduler>(scheduler)) {} + +ScopedSchedulerOverrider::~ScopedSchedulerOverrider() {} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h b/third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h new file mode 100644 index 0000000..7f46ea3 --- /dev/null +++ b/third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_SCHEDULER_OVERRIDER_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_SCHEDULER_OVERRIDER_H_ + +#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" +#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h" + +namespace blink { + +// A utility which lets you inject your custom implementation of ThreadScheduler +// on the main thread. This class sets up a very simple instance of +// blink::Thread and overrides the global main thread using ScopedMainThread- +// Overrider. Multi-thread is not supported. + +class ScopedSchedulerOverrider final { + public: + // |scheduler| must be owned by the caller. + explicit ScopedSchedulerOverrider(ThreadScheduler* scheduler); + ~ScopedSchedulerOverrider(); + + private: + ScopedMainThreadOverrider main_thread_overrider_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_SCHEDULER_OVERRIDER_H_
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/third_party/blink/renderer/platform/testing/testing_platform_support.cc index 3eea503..ebceac70 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support.cc +++ b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -96,7 +96,6 @@ interface_provider_(new TestingInterfaceProvider) { DCHECK(old_platform_); DCHECK(WTF::IsMainThread()); - main_thread_ = old_platform_->CurrentThread(); } TestingPlatformSupport::~TestingPlatformSupport() { @@ -159,12 +158,22 @@ base::DiscardableMemoryAllocator::SetInstance( discardable_memory_allocator_.get()); + // TODO(yutak): The initialization steps below are essentially a subset of + // Platform::Initialize() steps with a few modifications for tests. + // We really shouldn't have those initialization steps in two places, + // because they are a very fragile piece of code (the initialization order + // is so sensitive) and we want it to be consistent between tests and + // production. Fix this someday. dummy_platform_ = std::make_unique<Platform>(); Platform::SetCurrentPlatformForTesting(dummy_platform_.get()); WTF::Partitions::Initialize(nullptr); WTF::Initialize(nullptr); + // This must be called after WTF::Initialize(), because ThreadSpecific<> + // used in this function depends on WTF::IsMainThread(). + Platform::CreateMainThreadForTesting(); + testing_platform_support_ = std::make_unique<TestingPlatformSupport>(); Platform::SetCurrentPlatformForTesting(testing_platform_support_.get());
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.cc b/third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.cc deleted file mode 100644 index 1a32b34..0000000 --- a/third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.cc +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h" - -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/wtf/wtf.h" - -namespace blink { - -namespace { - -class ThreadWithCustomScheduler : public Thread { - public: - explicit ThreadWithCustomScheduler(ThreadScheduler* scheduler) - : scheduler_(scheduler) {} - ~ThreadWithCustomScheduler() override {} - - bool IsCurrentThread() const override { - DCHECK(WTF::IsMainThread()); - return true; - } - ThreadScheduler* Scheduler() override { return scheduler_; } - - private: - ThreadScheduler* scheduler_; -}; - -} // namespace - -TestingPlatformSupportWithCustomScheduler:: - TestingPlatformSupportWithCustomScheduler(ThreadScheduler* scheduler) - : thread_(std::make_unique<ThreadWithCustomScheduler>(scheduler)) { - // If main_thread_ is set, Platform::SetCurrentPlatformForTesting() properly - // sets up the platform so Platform::CurrentThread() would return the - // thread specified here. - main_thread_ = thread_.get(); -} - -TestingPlatformSupportWithCustomScheduler:: - ~TestingPlatformSupportWithCustomScheduler() {} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h b/third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h deleted file mode 100644 index 604b8a3..0000000 --- a/third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_CUSTOM_SCHEDULER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_CUSTOM_SCHEDULER_H_ - -#include <memory> -#include "base/macros.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/testing/testing_platform_support.h" - -// Test environment where you can inject your custom implementation of -// ThreadScheduler on the main thread. Multi-thread is not supported. -// -// You would probably like to use this with ScopedTestingPlatformSupport -// class template. See testing_platform_support.h for details. - -namespace blink { - -class TestingPlatformSupportWithCustomScheduler - : public TestingPlatformSupport { - public: - // |scheduler| must be owned by the caller. - explicit TestingPlatformSupportWithCustomScheduler( - ThreadScheduler* scheduler); - ~TestingPlatformSupportWithCustomScheduler() override; - - private: - std::unique_ptr<Thread> thread_; - - DISALLOW_COPY_AND_ASSIGN(TestingPlatformSupportWithCustomScheduler); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_CUSTOM_SCHEDULER_H_
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc b/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc index 0fdccdce..7f0f68e7 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc +++ b/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc
@@ -27,8 +27,8 @@ scheduler_ = std::make_unique<scheduler::MainThreadSchedulerImpl>( std::move(sequence_manager), base::nullopt); - thread_ = scheduler_->CreateMainThread(); - main_thread_ = thread_.get(); + main_thread_overrider_ = std::make_unique<ScopedMainThreadOverrider>( + scheduler_->CreateMainThread()); // Set the work batch size to one so TakePendingTasks behaves as expected. scheduler_->GetSchedulerHelperForTesting()->SetWorkBatchSizeForTesting(1);
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h b/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h index 46027c9..f2b22e5c1 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h +++ b/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/test/test_mock_time_task_runner.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/testing/scoped_main_thread_overrider.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h" @@ -36,6 +37,8 @@ TestingPlatformSupportWithMockScheduler(); ~TestingPlatformSupportWithMockScheduler() override; + std::unique_ptr<Thread> CreateMainThread(); + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner() { return test_task_runner_; } @@ -77,7 +80,7 @@ std::unique_ptr<scheduler::MainThreadSchedulerImpl> scheduler_; base::sequence_manager::SequenceManager* sequence_manager_; // Owned by scheduler_. - std::unique_ptr<Thread> thread_; + std::unique_ptr<ScopedMainThreadOverrider> main_thread_overrider_; }; } // namespace blink
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index 804fbcb..cebec61 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -207,13 +207,9 @@ # https://crbug.com/330260 'win': [ - # These two targets force symbol_level to be at least 1, they will work - # once we've figured out the PDB aging field. - 'crashpad_snapshot_test_image_reader.exe', - 'crashpad_snapshot_test_image_reader_module.dll', - - # TODO(thakis): Figure out what's up with these two. + # TODO(thakis): Figure out what's up with these three. 'mini_installer.exe', + 'mini_installer.exe.pdb', 'previous_version_mini_installer.exe', # These probably have mtimes in the zip headers and the scripts creating @@ -245,7 +241,6 @@ 'content_browsertests.isolated', 'content_shell_crash_test.isolated', 'content_unittests.isolated', - 'crashpad_tests.isolated', 'extensions_browsertests.isolated', 'extensions_unittests.isolated', 'gin_unittests.isolated',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 86138113..00998ee 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -21401,6 +21401,7 @@ <int value="10" label="Toggle show hidden Android folders (on)"/> <int value="11" label="Toggle show hidden Android folders (off)"/> <int value="12" label="Share with Linux"/> + <int value="13" label="Manage Linux sharing"/> </enum> <enum name="FileManagerQuickViewWayToOpen">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index cf23b6cb..0eb1847 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -98535,6 +98535,39 @@ </summary> </histogram> +<histogram name="SignedExchange.Prefetch.LoadResult" + enum="SignedExchangeLoadResult" expires_after="2019-10-11"> + <owner>kinuko@chromium.org</owner> + <owner>kouhei@chromium.org</owner> + <summary> + Records if the prefetched Signed Exchange was properly formatted and passed + verification steps. Reported for each completed SignedExchange prefetch. + </summary> +</histogram> + +<histogram name="SignedExchange.Prefetch.Precision.30Seconds" + enum="BooleanUsage" expires_after="2019-10-11"> + <owner>kinuko@chromium.org</owner> + <owner>kouhei@chromium.org</owner> + <summary> + Records if the prefetched Signed Exchange was actually the target of a + navigation which happened within 30 seconds. Reported when a corresponding + navigation is observed, or from an periodic timer event which cleans up the + unmatched prefetch entries. + </summary> +</histogram> + +<histogram name="SignedExchange.Prefetch.Recall.30Seconds" enum="BooleanUsage" + expires_after="2019-10-11"> + <owner>kinuko@chromium.org</owner> + <owner>kouhei@chromium.org</owner> + <summary> + Records how much Signed Exchange navigations were prefetched and not + prefetched. Matched against 30 seconds window. Reported for each Signed + Exchange navigations. + </summary> +</histogram> + <histogram name="SignedExchange.SignatureVerificationError.Expired" units="seconds" expires_after="2019-09-20"> <owner>kinuko@chromium.org</owner> @@ -124061,6 +124094,9 @@ </histogram_suffixes> <histogram_suffixes name="DataUse.Service.Types" separator="."> + <obsolete> + Deprecated Oct 2018 + </obsolete> <suffix name="Autofill"/> <suffix name="DomainReliability"/> <suffix name="GAIA"/>
diff --git a/ui/file_manager/base/js/BUILD.gn b/ui/file_manager/base/js/BUILD.gn index b717981..db61614 100644 --- a/ui/file_manager/base/js/BUILD.gn +++ b/ui/file_manager/base/js/BUILD.gn
@@ -6,12 +6,25 @@ visibility = [ "//ui/file_manager/*" ] -js_type_check("closure_compile") { +group("closure_compile") { + deps = [ + ":closure_compile_module", + ":test_support_type_check", + ] +} + +js_type_check("closure_compile_module") { deps = [ ":filtered_volume_manager", ] } +js_type_check("test_support_type_check") { + deps = [ + ":test_error_reporting", + ] +} + js_library("filtered_volume_manager") { deps = [ "//ui/file_manager/externs:file_manager_private", @@ -25,3 +38,11 @@ externs_list = [ "//ui/file_manager/externs/background/volume_manager_factory.js" ] } + +js_library("test_error_reporting") { + deps = [ + # Note we allow targets depending on test_error_reporting to access + # webui_resource_test transitively. + "//ui/webui/resources/js:webui_resource_test", + ] +}
diff --git a/ui/file_manager/base/js/test_error_reporting.js b/ui/file_manager/base/js/test_error_reporting.js new file mode 100644 index 0000000..a2798f3 --- /dev/null +++ b/ui/file_manager/base/js/test_error_reporting.js
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Invokes a callback function depending on the result of promise. + * + * @param {Promise} promise Promise. + * @param {function(boolean)} callback Callback function. True is passed if the + * test failed. + */ +function reportPromise(promise, callback) { + promise.then( + () => { + callback(/* error */ false); + }, + (/** Error */ error) => { + console.error(error.stack || error); + callback(/* error */ true); + }); +} + +/** + * Waits until testFunction becomes true. + * @param {function(): boolean} testFunction A function which is tested. + * @return {!Promise} A promise which is fulfilled when the testFunction + * becomes true. + */ +function waitUntil(testFunction) { + const INTERVAL_FOR_WAIT_UNTIL = 100; // ms + + return new Promise((resolve) => { + let tryTestFunction = () => { + if (testFunction()) + resolve(); + else + setTimeout(tryTestFunction, INTERVAL_FOR_WAIT_UNTIL); + }; + + tryTestFunction(); + }); +}
diff --git a/ui/file_manager/file_manager/background/js/device_handler_unittest.html b/ui/file_manager/file_manager/background/js/device_handler_unittest.html index b3027af1..ae81772c 100644 --- a/ui/file_manager/file_manager/background/js/device_handler_unittest.html +++ b/ui/file_manager/file_manager/background/js/device_handler_unittest.html
@@ -15,6 +15,7 @@ <!-- Need to load async_util.js before device_handler.js --> <script src="../../common/js/async_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/mock_entry.js"></script> <script src="../../common/js/volume_manager_common.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.html b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.html index ca77aa9..14fac76 100644 --- a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.html +++ b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.html
@@ -16,6 +16,7 @@ <script src="../../common/js/lru_cache.js"></script> <script src="../../common/js/mock_entry.js"></script> <script src="../../common/js/test_tracker.js"></script> + <script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/files_app_entry_types.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.html b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.html index 3c04a2d..7dd9c2b 100644 --- a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.html +++ b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.html
@@ -11,7 +11,7 @@ <script src="../../../../../ui/webui/resources/js/cr/event_target.js"></script> <script src="../../common/js/async_util.js"></script> -<script src="../../common/js/unittest_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/util.js"></script> <script src="../../common/js/lru_cache.js"></script> <script src="../../common/js/mock_entry.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/import_history_unittest.html b/ui/file_manager/file_manager/background/js/import_history_unittest.html index 2e7b6c0..2204a6a 100644 --- a/ui/file_manager/file_manager/background/js/import_history_unittest.html +++ b/ui/file_manager/file_manager/background/js/import_history_unittest.html
@@ -17,6 +17,7 @@ <script src="../../common/js/metrics_base.js"></script> <script src="../../common/js/metrics_events.js"></script> <script src="../../common/js/mock_entry.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.html b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.html index 993c317..7469576 100644 --- a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.html +++ b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.html
@@ -17,6 +17,7 @@ <script src="../../common/js/metrics_base.js"></script> <script src="../../common/js/metrics_events.js"></script> <script src="../../common/js/mock_entry.js"></script> + <script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/files_app_entry_types.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/media_scanner_unittest.html b/ui/file_manager/file_manager/background/js/media_scanner_unittest.html index 529c8bc..6746b6c 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner_unittest.html +++ b/ui/file_manager/file_manager/background/js/media_scanner_unittest.html
@@ -17,6 +17,7 @@ <script src="../../common/js/lru_cache.js"></script> <script src="../../common/js/mock_entry.js"></script> <script src="../../common/js/mock_file_system.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/util.js"></script> <script src="metadata_proxy.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/task_queue_unittest.html b/ui/file_manager/file_manager/background/js/task_queue_unittest.html index 8e92ecdc..f609d0c 100644 --- a/ui/file_manager/file_manager/background/js/task_queue_unittest.html +++ b/ui/file_manager/file_manager/background/js/task_queue_unittest.html
@@ -12,7 +12,7 @@ <script src="../../common/js/volume_manager_common.js"></script> <script src="../../common/js/importer_common.js"></script> - <script src="../../common/js/unittest_util.js"></script> + <script src="../../../base/js/test_error_reporting.js"></script> <script src="task_queue.js"></script> <script src="task_queue_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/volume_info_impl.js b/ui/file_manager/file_manager/background/js/volume_info_impl.js index d1ecdc8..3dc28d3 100644 --- a/ui/file_manager/file_manager/background/js/volume_info_impl.js +++ b/ui/file_manager/file_manager/background/js/volume_info_impl.js
@@ -65,12 +65,12 @@ this.fakeEntries_[VolumeManagerCommon.RootType.DRIVE_OFFLINE] = new FakeEntry( str('DRIVE_OFFLINE_COLLECTION_LABEL'), - VolumeManagerCommon.RootType.DRIVE_OFFLINE, true); + VolumeManagerCommon.RootType.DRIVE_OFFLINE); this.fakeEntries_[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME] = new FakeEntry( str('DRIVE_SHARED_WITH_ME_COLLECTION_LABEL'), - VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME, true); + VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME); } // Note: This represents if the mounting of the volume is successfully done
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_unittest.html b/ui/file_manager/file_manager/background/js/volume_manager_unittest.html index 4e3aff7..b584ecc 100644 --- a/ui/file_manager/file_manager/background/js/volume_manager_unittest.html +++ b/ui/file_manager/file_manager/background/js/volume_manager_unittest.html
@@ -13,6 +13,7 @@ <script src="../../common/js/async_util.js"></script> <script src="../../common/js/mock_entry.js"></script> + <script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/files_app_entry_types.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn index f4b2fdf..ee9eb4b 100644 --- a/ui/file_manager/file_manager/common/js/BUILD.gn +++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -8,6 +8,14 @@ # TODO(tapted): This entire folder should move to //ui/file_manager/base. visibility = [ "//ui/file_manager/*" ] +group("closure_compile") { + deps = [ + ":closure_compile_module", + ":test_support_type_check", + ":unit_tests_type_check", + ] +} + js_type_check("closure_compile_module") { deps = [ ":async_util", @@ -21,19 +29,25 @@ ":metrics_events", ":mock_entry", ":progress_center_common", - ":unittest_util", ":util", ":volume_manager_common", ] } +js_type_check("test_support_type_check") { + deps = [ + ":test_importer_common", + ":unittest_util", + ] +} + js_library("async_util") { } js_library("async_util_unittest") { deps = [ ":async_util", - ":unittest_util", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -50,8 +64,8 @@ js_library("files_app_entry_types_unittest") { deps = [ ":files_app_entry_types", - ":unittest_util", ":volume_manager_common", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -85,6 +99,7 @@ deps = [ ":importer_common", ":unittest_util", + "//ui/file_manager/base/js:test_error_reporting", ] visibility = [] visibility = [ "//ui/file_manager/file_manager/*" ] @@ -141,6 +156,9 @@ } js_library("unittest_util") { + # Only files app tests use this util file. + visibility = [] + visibility = [ "//ui/file_manager/file_manager/*" ] deps = [ "//ui/webui/resources/js:webui_resource_test", ] @@ -168,8 +186,8 @@ js_library("util_unittest") { deps = [ ":mock_entry", - ":unittest_util", ":util", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -188,17 +206,3 @@ ":util_unittest", ] } - -js_type_check("test_support_type_check") { - deps = [ - ":test_importer_common", - ] -} - -group("closure_compile") { - deps = [ - ":closure_compile_module", - ":test_support_type_check", - ":unit_tests_type_check", - ] -}
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types.js b/ui/file_manager/file_manager/common/js/files_app_entry_types.js index faad490c..c02b0ff2 100644 --- a/ui/file_manager/file_manager/common/js/files_app_entry_types.js +++ b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
@@ -487,17 +487,16 @@ * FakeEntry is used for entries that used only for UI, that weren't generated * by FileSystem API, like Drive, Downloads or Provided. * - * @implements FilesAppEntry + * @implements FilesAppDirEntry */ class FakeEntry { /** * @param {string} label Translated text to be displayed to user. * @param {!VolumeManagerCommon.RootType} rootType Root type of this entry. - * @param {boolean} isDirectory Is this entry a directory-like entry? * @param {chrome.fileManagerPrivate.SourceRestriction=} opt_sourceRestriction * used on Recents to filter the source of recent files/directories. */ - constructor(label, rootType, isDirectory, opt_sourceRestriction) { + constructor(label, rootType, opt_sourceRestriction) { /** * @public {string} label: Label to be used when displaying to user, it * should be already translated. */ @@ -509,13 +508,11 @@ /** @public {!VolumeManagerCommon.RootType} */ this.rootType = rootType; - /** - * @public {boolean} true if this entry represents a Directory-like entry. - */ - this.isDirectory = isDirectory; + /** @public {boolean} true FakeEntry are always directory-like. */ + this.isDirectory = true; - /** @public {boolean} true if this entry represents a File-like entry. */ - this.isFile = !this.isDirectory; + /** @public {boolean} false FakeEntry are always directory-like. */ + this.isFile = false; /** * @public {chrome.fileManagerPrivate.SourceRestriction|undefined} It's used @@ -564,4 +561,13 @@ get isNativeType() { return false; } + + /** + * @return {!StaticReader} Returns a reader compatible with + * DirectoryEntry.createReader (from Web Standards) that reads 0 entries. + * @override + */ + createReader() { + return new StaticReader([]); + } }
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js index ad138317..698dc43 100644 --- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js +++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
@@ -328,8 +328,7 @@ * Test FakeEntry, which is only static data. */ function testFakeEntry(testReportCallback) { - let fakeEntry = - new FakeEntry('label', VolumeManagerCommon.RootType.CROSTINI, true); + let fakeEntry = new FakeEntry('label', VolumeManagerCommon.RootType.CROSTINI); assertEquals(undefined, fakeEntry.sourceRestriction); assertEquals('FakeEntry', fakeEntry.type_name); @@ -342,15 +341,12 @@ assertTrue(fakeEntry.isDirectory); assertFalse(fakeEntry.isFile); - // Check the isDirectory and sourceRestriction constructor args. + // Check sourceRestriction constructor args. const kSourceRestriction = /** @type{chrome.fileManagerPrivate.SourceRestriction} */ ('fake'); fakeEntry = new FakeEntry( - 'label', VolumeManagerCommon.RootType.CROSTINI, false, - kSourceRestriction); + 'label', VolumeManagerCommon.RootType.CROSTINI, kSourceRestriction); assertEquals(kSourceRestriction, fakeEntry.sourceRestriction); - assertFalse(fakeEntry.isDirectory); - assertTrue(fakeEntry.isFile); let callCounter = 0;
diff --git a/ui/file_manager/file_manager/common/js/metrics_unittest.html b/ui/file_manager/file_manager/common/js/metrics_unittest.html index 9d98392..8e0ab645 100644 --- a/ui/file_manager/file_manager/common/js/metrics_unittest.html +++ b/ui/file_manager/file_manager/common/js/metrics_unittest.html
@@ -11,15 +11,11 @@ <script src="../../../../../ui/webui/resources/js/cr/event_target.js"></script> <script src="../../../../../ui/webui/resources/js/cr/ui/array_data_model.js"></script> <script src="../../../../../ui/webui/resources/js/load_time_data.js"></script> - <script src="../../../../../third_party/analytics/google-analytics-bundle.js"></script> - - <script src="unittest_util.js"></script> + <script src="../../../../file_manager/base/js/test_error_reporting.js"></script> <script src="util.js"></script> <script src="metrics_base.js"></script> <script src="metrics.js"></script> - - <script src="metrics_unittest.js"></script> </body> </html>
diff --git a/ui/file_manager/file_manager/common/js/unittest_util.js b/ui/file_manager/file_manager/common/js/unittest_util.js index 413a05b0..b0c4388b 100644 --- a/ui/file_manager/file_manager/common/js/unittest_util.js +++ b/ui/file_manager/file_manager/common/js/unittest_util.js
@@ -2,45 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var INTERVAL_FOR_WAIT_UNTIL = 100; // ms - -/** - * Invokes a callback function depending on the result of promise. - * - * @param {Promise} promise Promise. - * @param {function(boolean)} callback Callback function. True is passed if the - * test failed. - */ -function reportPromise(promise, callback) { - promise.then( - function() { - callback(/* error */ false); - }, - function(/** @type {Error} */ error) { - console.error(error.stack || error); - callback(/* error */ true); - }); -} - -/** - * Waits until testFunction becomes true. - * @param {function(): boolean} testFunction A function which is tested. - * @return {!Promise} A promise which is fullfilled when the testFunction - * becomes true. - */ -function waitUntil(testFunction) { - return new Promise(function(resolve) { - var tryTestFunction = function() { - if (testFunction()) - resolve(); - else - setTimeout(tryTestFunction, INTERVAL_FOR_WAIT_UNTIL); - }; - - tryTestFunction(); - }); -} - /** * Asserts that two lists contain the same set of Entries. Entries are deemed * to be the same if they point to the same full path. @@ -49,7 +10,6 @@ * @param {!Array<!FileEntry>} actual */ function assertFileEntryListEquals(expected, actual) { - var entryToPath = function(entry) { assertTrue(entry.isFile); return entry.fullPath; @@ -77,13 +37,11 @@ expectedPaths = expectedPaths.slice(); expectedPaths.sort(); - assertEquals( - JSON.stringify(expectedPaths), - JSON.stringify(actualPaths)); + assertEquals(JSON.stringify(expectedPaths), JSON.stringify(actualPaths)); } /** - * A class that captures calls to a funtion so that values can be validated. + * A class that captures calls to a function so that values can be validated. * For use in tests only. * * <p>Example: @@ -134,9 +92,8 @@ * or null if the recorder hasn't been called. */ TestCallRecorder.prototype.getLastArguments = function() { - return (this.calls_.length === 0) ? - null : - this.calls_[this.calls_.length - 1]; + return (this.calls_.length === 0) ? null : + this.calls_[this.calls_.length - 1]; }; /** @@ -145,47 +102,7 @@ * by indexd. */ TestCallRecorder.prototype.getArguments = function(index) { - return (index < this.calls_.length) ? - this.calls_[index] : - null; -}; - -/** - * @constructor - * @struct - */ -function MockAPIEvent() { - /** - * @type {!Array<!Function>} - * @const - */ - this.listeners_ = []; -} - -/** - * @param {!Function} callback - */ -MockAPIEvent.prototype.addListener = function(callback) { - this.listeners_.push(callback); -}; - -/** - * @param {!Function} callback - */ -MockAPIEvent.prototype.removeListener = function(callback) { - var index = this.listeners_.indexOf(callback); - if (index < 0) - throw new Error('Tried to remove an unregistered listener.'); - this.listeners_.splice(index, 1); -}; - -/** - * @param {...*} var_args - */ -MockAPIEvent.prototype.dispatch = function(var_args) { - for (var i = 0; i < this.listeners_.length; i++) { - this.listeners_[i].apply(null, arguments); - } + return (index < this.calls_.length) ? this.calls_[index] : null; }; /** @@ -204,7 +121,7 @@ window.chrome.storage = { local: { get: this.get_.bind(this), - set: this.set_.bind(this) + set: this.set_.bind(this), } }; } @@ -217,11 +134,10 @@ MockChromeStorageAPI.prototype.get_ = function(keys, callback) { var keys = keys instanceof Array ? keys : [keys]; var result = {}; - keys.forEach( - function(key) { - if (key in this.state) - result[key] = this.state[key]; - }.bind(this)); + keys.forEach((key) => { + if (key in this.state) + result[key] = this.state[key]; + }); callback(result); };
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html index 35eab5a..07e5bcf 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html +++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html
@@ -43,5 +43,5 @@ <script src="../../../../webui/resources/js/assert.js"></script> <script src="../../../../webui/resources/js/util.js"></script> -<script src="../../common/js/unittest_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="files_tooltip_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 2823093..7f8dffa 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -580,8 +580,7 @@ deps = [ ":thumbnail_loader", "../../common/js:mock_entry", - "../../common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] }
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.html b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.html index 4e16461..73c607e1 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.html
@@ -13,6 +13,7 @@ <script src="../../foreground/js/metadata/mock_metadata.js"></script> <script src="../../common/js/mock_entry.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/files_app_entry_types.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model.js b/ui/file_manager/file_manager/foreground/js/directory_model.js index 559e59ea..c8180c9e 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model.js
@@ -875,7 +875,7 @@ // new one. if (util.isSameEntry(oldEntry, this.getCurrentDirEntry())) { this.changeDirectoryEntry( - /** @type {!DirectoryEntry|!FakeEntry} */ (newEntry)); + /** @type {!DirectoryEntry|!FilesAppDirEntry} */ (newEntry)); } // Replace the old item with the new item. oldEntry instance itself may @@ -960,13 +960,18 @@ * activateDirectoryEntry instead of this, which is higher-level function and * cares about the selection. * - * @param {!DirectoryEntry|!FakeEntry} dirEntry The entry of the new directory - * to be opened. + * @param {!DirectoryEntry|!FilesAppDirEntry} dirEntry The entry of the new + * directory to be opened. * @param {function()=} opt_callback Executed if the directory loads * successfully. */ DirectoryModel.prototype.changeDirectoryEntry = function( dirEntry, opt_callback) { + // If it's a VolumeEntry which wraps an actual entry, we should use the + // unwrapped entry. + if (dirEntry instanceof VolumeEntry) + dirEntry = assert(dirEntry.rootEntry); + // Increment the sequence value. this.changeDirectorySequence_++; this.clearSearch_(); @@ -1082,8 +1087,8 @@ * directory. * - Clears the selection, if the given directory is the current directory. * - * @param {!DirectoryEntry|!FakeEntry} dirEntry The entry of the new directory - * to be opened. + * @param {!DirectoryEntry|!FilesAppDirEntry} dirEntry The entry of the new + * directory to be opened. * @param {function()=} opt_callback Executed if the directory loads * successfully. */
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index 0bca2f7..f73e00b 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -1207,7 +1207,7 @@ str('RECENT_ROOT_LABEL'), NavigationModelItemType.RECENT, new FakeEntry( str('RECENT_ROOT_LABEL'), - VolumeManagerCommon.RootType.RECENT, true, + VolumeManagerCommon.RootType.RECENT, this.getSourceRestriction_())) : null, this.commandLineFlags_['disable-my-files-navigation']); @@ -1220,25 +1220,25 @@ * @private */ FileManager.prototype.setupCrostini_ = function() { - chrome.fileManagerPrivate.isCrostiniEnabled((enabled) => { + chrome.fileManagerPrivate.isCrostiniEnabled((crostiniEnabled) => { // Check for 'crostini-files' cmd line flag. chrome.commandLinePrivate.hasSwitch('crostini-files', (filesEnabled) => { - Crostini.IS_CROSTINI_FILES_ENABLED = filesEnabled; + Crostini.IS_CROSTINI_FILES_ENABLED = crostiniEnabled && filesEnabled; }); // Setup Linux files fake root. - this.directoryTree.dataModel.linuxFilesItem = enabled ? + this.directoryTree.dataModel.linuxFilesItem = crostiniEnabled ? new NavigationModelFakeItem( str('LINUX_FILES_ROOT_LABEL'), NavigationModelItemType.CROSTINI, new FakeEntry( str('LINUX_FILES_ROOT_LABEL'), - VolumeManagerCommon.RootType.CROSTINI, true)) : + VolumeManagerCommon.RootType.CROSTINI)) : null; // Redraw the tree even if not enabled. This is required for testing. this.directoryTree.redraw(false); - if (!enabled) + if (!crostiniEnabled) return; // Load any existing shared paths.
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index f8ddc3a..589a5a3 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -395,6 +395,7 @@ HIDDEN_ANDROID_FOLDERS_SHOW: 'toggle-hidden-android-folders-on', HIDDEN_ANDROID_FOLDERS_HIDE: 'toggle-hidden-android-folders-off', SHARE_WITH_LINUX: 'share-with-linux', + MANAGE_LINUX_SHARING: 'manage-linux-sharing', }; /** @@ -420,6 +421,7 @@ CommandHandler.MenuCommandsForUMA.HIDDEN_ANDROID_FOLDERS_SHOW, CommandHandler.MenuCommandsForUMA.HIDDEN_ANDROID_FOLDERS_HIDE, CommandHandler.MenuCommandsForUMA.SHARE_WITH_LINUX, + CommandHandler.MenuCommandsForUMA.MANAGE_LINUX_SHARING, ]; console.assert( Object.keys(CommandHandler.MenuCommandsForUMA).length === @@ -1674,6 +1676,31 @@ }); /** + * Link to settings page to manage files and folders shared with crostini + * container. + * @type {Command} + */ +CommandHandler.COMMANDS_['manage-linux-sharing'] = /** @type {Command} */ ({ + /** + * @param {!Event} event Command event. + * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use. + */ + execute: function(event, fileManager) { + chrome.fileManagerPrivate.openSettingsSubpage('crostini/sharedPaths'); + CommandHandler.recordMenuItemSelected_( + CommandHandler.MenuCommandsForUMA.MANAGE_LINUX_SHARING); + }, + /** + * @param {!Event} event Command event. + * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use. + */ + canExecute: function(event, fileManager) { + event.canExecute = Crostini.IS_CROSTINI_FILES_ENABLED; + event.command.setHidden(!event.canExecute); + } +}); + +/** * Creates a shortcut of the selected folder (single only). * @type {Command} */
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html index 2adea43..05aa0ee 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.html
@@ -10,7 +10,7 @@ <script src="../../common/js/volume_manager_common.js"></script> <script src="../../common/js/mock_entry.js"></script> <script src="../../common/js/file_type.js"></script> -<script src="../../common/js/unittest_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/util.js"></script> <script src="constants.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js index 696a254..d904d435 100644 --- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js +++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -167,7 +167,7 @@ queryRequiredElement('command#cut', this.document_)); /** - * @private {DirectoryEntry|FakeEntry} + * @private {DirectoryEntry|FilesAppDirEntry} */ this.destinationEntry_ = null;
diff --git a/ui/file_manager/file_manager/foreground/js/file_watcher.js b/ui/file_manager/file_manager/foreground/js/file_watcher.js index 59c48d7..fd3949b 100644 --- a/ui/file_manager/file_manager/foreground/js/file_watcher.js +++ b/ui/file_manager/file_manager/foreground/js/file_watcher.js
@@ -69,8 +69,8 @@ * Changes the watched directory. In case of a fake entry, the watch is * just released, since there is no reason to track a fake directory. * - * @param {!DirectoryEntry|!FakeEntry} entry Directory entry to be tracked, or - * the fake entry. + * @param {!DirectoryEntry|!FilesAppEntry} entry Directory entry to be tracked, + * or the fake entry. * @return {!Promise} */ FileWatcher.prototype.changeWatchedDirectory = function(entry) {
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html index 048b501..869b35c4 100644 --- a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html
@@ -16,6 +16,7 @@ <script src="../../common/js/async_util.js"></script> <script src="../../common/js/mock_entry.js"></script> + <script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/files_app_entry_types.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html index 21f19e0..4cb178e 100644 --- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html
@@ -13,7 +13,7 @@ <script src="../../common/js/lru_cache.js"></script> <script src="../../common/js/util.js"></script> <script src="../../common/js/mock_entry.js"></script> -<script src="../../common/js/unittest_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/volume_manager_common.js"></script> <script src="directory_contents.js"></script> <script src="file_list_model.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js index bb35917..1482b0e0 100644 --- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
@@ -3,24 +3,6 @@ // found in the LICENSE file. /** - * Wait until the condition is met. - * - * @param {function()} condition Condition. - * @return {Promise} A promise which is resolved when condition is met. - */ -function waitUntil(condition) { - return new Promise(function(resolve, reject) { - var checkCondition = function() { - if (condition()) - resolve(); - else - setTimeout(checkCondition, 100); - }; - checkCondition(); - }); -} - -/** * Generates a data url of a sample image for testing. * TODO(yawano) Consider to share image generation logic with * gallery/js/image_editor/test_util.js.
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html index 6a576aa7..66638da 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html
@@ -13,7 +13,7 @@ <!-- Others --> <script src="../../../../../webui/resources/js/assert.js"></script> <script src="../../../common/js/lru_cache.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="../../../common/js/file_type.js"></script> <script src="content_metadata_provider.js"></script> <script src="metadata_cache_item.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.html index 682930f..e2edc1af1 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.html
@@ -13,7 +13,7 @@ <!-- Others --> <script src="../../../../../webui/resources/js/assert.js"></script> <script src="../../../common/js/lru_cache.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="external_metadata_provider.js"></script> <script src="metadata_cache_item.js"></script> <script src="metadata_item.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html index 8d123ce..7136ed0 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html
@@ -12,7 +12,7 @@ <!-- Others --> <script src="../../../../../webui/resources/js/assert.js"></script> <script src="../../../common/js/lru_cache.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="file_system_metadata_provider.js"></script> <script src="metadata_cache_item.js"></script> <script src="metadata_item.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.html index da1346c..2f9c70b 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.html
@@ -4,7 +4,7 @@ -- found in the LICENSE file. --> <script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="metadata_cache_item.js"></script> <script src="metadata_item.js"></script> <script src="metadata_request.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html index a783501..b697c34 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html
@@ -10,7 +10,7 @@ <!-- Others --> <script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="../../../common/js/util.js"></script> <script src="metadata_cache_item.js"></script> <script src="metadata_cache_set.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html index f19aeba..3906cb1 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html
@@ -11,7 +11,7 @@ <!-- Others --> <script src="../../../../../webui/resources/js/assert.js"></script> <script src="../../../common/js/lru_cache.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="../../../common/js/util.js"></script> <script src="metadata_cache_item.js"></script> <script src="metadata_item.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html index 446bc5f0..40e15ca 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html
@@ -13,7 +13,7 @@ <!-- Others --> <script src="../../../../../webui/resources/js/assert.js"></script> <script src="../../../common/js/lru_cache.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="../../../common/js/volume_manager_common.js"></script> <script src="content_metadata_provider.js"></script> <script src="external_metadata_provider.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.html index bb10cdcb..e655b9a4 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.html
@@ -4,7 +4,7 @@ -- found in the LICENSE file. --> <script src="../../../common/js/file_type.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="metadata_item.js"></script> <script src="thumbnail_model.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.html b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.html index abcf28d..01953396 100644 --- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.html
@@ -23,6 +23,7 @@ <script src="../../background/js/mock_volume_manager.js"></script> <script src="../../common/js/async_util.js"></script> <script src="../../common/js/mock_entry.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/util.js"></script> <script src="mock_folder_shortcut_data_model.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.html b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.html index 31c71e723..5a865c1 100644 --- a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.html
@@ -14,6 +14,7 @@ <script src="../../../../../ui/webui/resources/js/load_time_data.js"></script> <script src="../../common/js/mock_entry.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/files_app_entry_types.js"></script> <script src="../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.html b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.html index de28607..f6783e5 100644 --- a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.html
@@ -8,6 +8,6 @@ <script src="../../../../webui/resources/js/assert.js"></script> <script src="../../../../webui/resources/js/util.js"></script> -<script src="../../common/js/unittest_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="spinner_controller.js"></script> <script src="spinner_controller_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html index f23b8e0..d6949ef 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html
@@ -17,7 +17,7 @@ <script src="../../common/js/file_type.js"></script> <script src="../../common/js/mock_entry.js"></script> -<script src="../../common/js/unittest_util.js"></script> +<script src="../../../base/js/test_error_reporting.js"></script> <script src="../../common/js/util.js"></script> <script src="../../common/js/volume_manager_common.js"></script> <script src="crostini.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html index 0e7d0d18..e72ad12 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html
@@ -17,6 +17,7 @@ <script src="../../../common/js/async_util.js"></script> <script src="../../../common/js/mock_entry.js"></script> + <script src="../../../../base/js/test_error_reporting.js"></script> <script src="../../../common/js/unittest_util.js"></script> <script src="../../../common/js/files_app_entry_types.js"></script> <script src="../../../common/js/util.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.html b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.html index 146270b8..596df36f 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.html +++ b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.html
@@ -6,7 +6,7 @@ <script src="../../../../../../ui/webui/resources/js/assert.js"></script> -<script src="../../../common/js/unittest_util.js"></script> +<script src="../../../../base/js/test_error_reporting.js"></script> <script src="../../../common/js/util.js"></script> <script src="file_tap_handler.js"></script>
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index 10defcc..2acb28db 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -170,6 +170,7 @@ <command id="manage-in-drive" i18n-values="label:MANAGE_IN_DRIVE_BUTTON_LABEL" disabled hidden> <command id="share-with-linux" i18n-values="label:SHARE_WITH_LINUX_BUTTON_LABEL" disabled hidden> + <command id="manage-linux-sharing" i18n-values="label:MANAGE_LINUX_SHARING_BUTTON_LABEL" disabled hidden> <command id="zoom-in" shortcut="=|Ctrl"> <command id="zoom-out" shortcut="-|Ctrl"> @@ -268,6 +269,8 @@ command="#toggle-hidden-files"></cr-menu-item> <cr-menu-item id="gear-menu-toggle-hidden-android-folders" command="#toggle-hidden-android-folders"></cr-menu-item> + <cr-menu-item id="gear-menu-manage-linux-sharing" + command="#manage-linux-sharing"></cr-menu-item> <cr-menu-item id="gear-menu-drive-sync-settings" command="#drive-sync-settings"></cr-menu-item> <cr-menu-item id="gear-menu-drive-hosted-settings"
diff --git a/ui/file_manager/file_manager/test/BUILD.gn b/ui/file_manager/file_manager/test/BUILD.gn index 7c5254a8c..e3ec2a5 100644 --- a/ui/file_manager/file_manager/test/BUILD.gn +++ b/ui/file_manager/file_manager/test/BUILD.gn
@@ -21,7 +21,9 @@ "//chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc", "//ui/webui/resources/css/text_defaults.css", "check_select.js", - "crostini.js", + "crostini_mount.js", + "crostini_share.js", + "crostini_tasks.js", "js/strings.js", "quick_view.js", "uma.js", @@ -36,7 +38,9 @@ deps = [ ":check_select", ":closure_compile_externs", - ":crostini", + ":crostini_mount", + ":crostini_share", + ":crostini_tasks", ":quick_view", ":uma", ] @@ -68,7 +72,23 @@ ] } -js_library("crostini") { +js_library("crostini_mount") { + deps = [ + "../foreground/js:crostini", + "js:test_util", + "//ui/webui/resources/js:webui_resource_test", + ] +} + +js_library("crostini_share") { + deps = [ + "../foreground/js:crostini", + "js:test_util", + "//ui/webui/resources/js:webui_resource_test", + ] +} + +js_library("crostini_tasks") { deps = [ "../foreground/js:crostini", "js:test_util",
diff --git a/ui/file_manager/file_manager/test/crostini.js b/ui/file_manager/file_manager/test/crostini.js deleted file mode 100644 index 086946a..0000000 --- a/ui/file_manager/file_manager/test/crostini.js +++ /dev/null
@@ -1,436 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -const crostini = {}; - -crostini.testCrostiniNotEnabled = (done) => { - chrome.fileManagerPrivate.crostiniEnabled_ = false; - test.setupAndWaitUntilReady() - .then(() => { - fileManager.setupCrostini_(); - return test.waitForElementLost( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - // Reset crostini back to default enabled=true. - chrome.fileManagerPrivate.crostiniEnabled_ = true; - done(); - }); -}; - -crostini.testMountCrostiniSuccess = (done) => { - const oldMount = chrome.fileManagerPrivate.mountCrostini; - let mountCallback = null; - chrome.fileManagerPrivate.mountCrostini = (callback) => { - mountCallback = callback; - }; - test.setupAndWaitUntilReady() - .then(() => { - // Linux files fake root is shown. - return test.waitForElement( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - // Click on Linux files. - assertTrue( - test.fakeMouseClick( - '#directory-tree .tree-item [root-type-icon="crostini"]'), - 'click linux files'); - return test.waitForElement('paper-progress:not([hidden])'); - }) - .then(() => { - // Ensure mountCrostini is called. - return test.repeatUntil(() => { - if (!mountCallback) - return test.pending('Waiting for mountCrostini'); - return mountCallback; - }); - }) - .then(() => { - // Intercept the fileManagerPrivate.mountCrostini call - // and add crostini disk mount. - test.mountCrostini(); - // Continue from fileManagerPrivate.mountCrostini callback - // and ensure expected files are shown. - mountCallback(); - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET)); - }) - .then(() => { - // Reset fileManagerPrivate.mountCrostini and remove mount. - chrome.fileManagerPrivate.mountCrostini = oldMount; - chrome.fileManagerPrivate.removeMount('crostini'); - // Linux Files fake root is shown. - return test.waitForElement( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - // Downloads folder should be shown when crostini goes away. - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows(test.BASIC_LOCAL_ENTRY_SET)); - }) - .then(() => { - done(); - }); -}; - -crostini.testMountCrostiniError = (done) => { - const oldMount = chrome.fileManagerPrivate.mountCrostini; - // Override fileManagerPrivate.mountCrostini to return error. - chrome.fileManagerPrivate.mountCrostini = (callback) => { - chrome.runtime.lastError = {message: 'test message'}; - callback(); - delete chrome.runtime.lastError; - }; - test.setupAndWaitUntilReady() - .then(() => { - return test.waitForElement( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - // Click on Linux Files, ensure error dialog is shown. - assertTrue(test.fakeMouseClick( - '#directory-tree .tree-item [root-type-icon="crostini"]')); - return test.waitForElement('.cr-dialog-container.shown'); - }) - .then(() => { - // Click OK button to close. - assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); - return test.waitForElementLost('.cr-dialog-container'); - }) - .then(() => { - // Reset chrome.fileManagerPrivate.mountCrostini. - chrome.fileManagerPrivate.mountCrostini = oldMount; - done(); - }); -}; - -crostini.testCrostiniMountOnDrag = (done) => { - chrome.fileManagerPrivate.mountCrostiniDelay_ = 0; - test.setupAndWaitUntilReady() - .then(() => { - return test.waitForElement( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - assertTrue(test.sendEvent( - '#directory-tree .tree-item [root-type-icon="crostini"]', - new Event('dragenter', {bubbles: true}))); - assertTrue(test.sendEvent( - '#directory-tree .tree-item [root-type-icon="crostini"]', - new Event('dragleave', {bubbles: true}))); - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET)); - }) - .then(() => { - chrome.fileManagerPrivate.removeMount('crostini'); - return test.waitForElement( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - done(); - }); -}; - -crostini.testShareBeforeOpeningDownloadsWithCrostiniApp = (done) => { - // Save old fmp.getFileTasks and replace with version that returns - // crostini app and chrome Text app. - let oldGetFileTasks = chrome.fileManagerPrivate.getFileTasks; - chrome.fileManagerPrivate.getFileTasks = (entries, callback) => { - setTimeout(callback, 0, [ - { - taskId: 'text-app-id|app|text', - title: 'Text', - verb: 'open_with', - }, - { - taskId: 'crostini-app-id|crostini|open-with', - title: 'Crostini App', - verb: 'open_with', - } - ]); - }; - - // Save old fmp.sharePathWitCrostini. - const oldSharePath = chrome.fileManagerPrivate.sharePathWithCrostini; - let sharePathCalled = false; - chrome.fileManagerPrivate.sharePathWithCrostini = (entry, callback) => { - sharePathCalled = true; - oldSharePath(entry, callback); - }; - - // Save old fmp.executeTask. - const oldExecuteTask = chrome.fileManagerPrivate.executeTask; - let executeTaskCalled = false; - chrome.fileManagerPrivate.executeTask = (taskId, entries, callback) => { - executeTaskCalled = true; - oldExecuteTask(taskId, entries, callback); - }; - chrome.metricsPrivate.values_ = []; - - test.setupAndWaitUntilReady([], [], []) - .then(() => { - // Add '/A', and '/A/hello.txt', refresh, 'A' is shown. - test.addEntries( - [test.ENTRIES.directoryA, test.ENTRIES.helloInA], [], []); - assertTrue(test.fakeMouseClick('#refresh-button'), 'click refresh'); - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows([test.ENTRIES.directoryA])); - }) - .then(() => { - // Change to 'A' directory, hello.txt is shown. - assertTrue(test.fakeMouseDoubleClick('[file-name="A"]')); - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows([test.ENTRIES.hello])); - }) - .then(() => { - // Right click on 'hello.txt' file, wait for dialog with 'Open with'. - assertTrue(test.fakeMouseRightClick('[file-name="hello.txt"]')); - return test.waitForElement( - 'cr-menu-item[command="#open-with"]:not([hidden]'); - }) - .then(() => { - // Click 'Open with', wait for picker. - assertTrue(test.fakeMouseClick('cr-menu-item[command="#open-with"]')); - return test.waitForElement('#default-tasks-list'); - }) - .then(() => { - // Ensure picker shows both options. Click on 'Crostini App'. Ensure - // share path dialog is shown. - const list = document.querySelectorAll('#default-tasks-list li div'); - assertEquals(2, list.length); - assertEquals('Open with Crostini App', list[0].innerText); - assertEquals('Open with Text', list[1].innerText); - assertTrue(test.fakeMouseClick('#default-tasks-list li')); - return test.repeatUntil(() => { - return document.querySelector('.cr-dialog-title').innerText === - 'Share files with Linux' || - test.pending('Waiting for share before open dialog'); - }); - }) - .then(() => { - // Validate dialog messages, click 'OK' to share and open. Ensure - // dialog closes. - assertEquals( - 'Let Linux apps open <b>hello.txt</b>.', - document.querySelector('.cr-dialog-text').innerHTML); - assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); - return test.waitForElementLost('.cr-dialog-container'); - }) - .then(() => { - // Ensure fmp.sharePathWithCrostini, fmp.executeTask called. - return test.repeatUntil(() => { - return sharePathCalled && executeTaskCalled || - test.pending('Waiting to share and open'); - }); - }) - .then(() => { - // Validate UMAs. - const lastEnumUma = chrome.metricsPrivate.values_.pop(); - assertEquals( - 'FileBrowser.CrostiniShareDialog', lastEnumUma[0].metricName); - assertEquals(1 /* ShareBeforeOpen */, lastEnumUma[1]); - - // Restore fmp.*. - chrome.fileManagerPrivate.getFileTasks = oldGetFileTasks; - chrome.fileManagerPrivate.sharePathWithCrostini = oldSharePath; - chrome.fileManagerPrivate.executeTask = oldExecuteTask; - done(); - }); -}; - -crostini.testErrorOpeningDownloadsRootWithDefaultCrostiniApp = (done) => { - // Save old fmp.getFileTasks and replace with version that returns - // crostini app and chrome Text app. - let oldGetFileTasks = chrome.fileManagerPrivate.getFileTasks; - chrome.fileManagerPrivate.getFileTasks = (entries, callback) => { - setTimeout(callback, 0, [{ - taskId: 'crostini-app-id|crostini|open-with', - title: 'Crostini App', - verb: 'open_with', - isDefault: true, - }]); - }; - - test.setupAndWaitUntilReady() - .then(() => { - // Right click on 'world.ogv' file, wait for dialog with the default - // task action. - assertTrue(test.fakeMouseRightClick('[file-name="world.ogv"]')); - return test.repeatUntil(() => { - return document - .querySelector( - 'cr-menu-item[command="#default-task"]:not([hidden])') - .label === 'Crostini App' || - test.pending('Waiting for default task menu item'); - }); - }) - .then(() => { - // Click 'Open with', wait for picker. - assertTrue( - test.fakeMouseClick('cr-menu-item[command="#default-task"]')); - return test.waitForElement('.cr-dialog-container'); - }) - .then(() => { - // Validate error messages, click 'OK' to close. Ensure dialog closes. - assertEquals( - 'Unable to open with Crostini App', - document.querySelector('.cr-dialog-title').innerText); - assertEquals( - 'To open files with Crostini App, ' + - 'first copy to Linux files folder.', - document.querySelector('.cr-dialog-text').innerText); - assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); - return test.waitForElementLost('.cr-dialog-container'); - }) - .then(() => { - // Restore fmp.getFileTasks. - chrome.fileManagerPrivate.getFileTasks = oldGetFileTasks; - done(); - }); -}; - -crostini.testSharePathCrostiniSuccess = (done) => { - const oldSharePath = chrome.fileManagerPrivate.sharePathWithCrostini; - let sharePathCalled = false; - chrome.fileManagerPrivate.sharePathWithCrostini = (entry, callback) => { - oldSharePath(entry, () => { - sharePathCalled = true; - callback(); - }); - }; - chrome.metricsPrivate.smallCounts_ = []; - chrome.metricsPrivate.values_ = []; - - test.setupAndWaitUntilReady() - .then(() => { - // Right-click 'photos' directory. - // Check 'Share with Linux' is shown in menu. - assertTrue( - test.fakeMouseRightClick('#file-list [file-name="photos"]'), - 'right-click photos'); - return test.waitForElement( - '#file-context-menu:not([hidden]) ' + - '[command="#share-with-linux"]:not([hidden]):not([disabled])'); - }) - .then(() => { - // Click on 'Share with Linux'. - assertTrue( - test.fakeMouseClick( - '#file-context-menu [command="#share-with-linux"]'), - 'Share with Linux'); - // Check sharePathWithCrostini is called. - return test.repeatUntil(() => { - return sharePathCalled || test.pending('wait for sharePathCalled'); - }); - }) - .then(() => { - // Validate UMAs. - assertEquals(1, chrome.metricsPrivate.smallCounts_.length); - assertArrayEquals( - ['FileBrowser.CrostiniSharedPaths.Depth.downloads', 1], - chrome.metricsPrivate.smallCounts_[0]); - const lastEnumUma = chrome.metricsPrivate.values_.pop(); - assertEquals('FileBrowser.MenuItemSelected', lastEnumUma[0].metricName); - assertEquals(12 /* Share with Linux */, lastEnumUma[1]); - - // Restore fmp.*. - chrome.fileManagerPrivate.sharePathWithCrostini = oldSharePath; - done(); - }); -}; - -// Verify right-click menu with 'Share with Linux' is not shown for: -// * Files (not directory) -// * Any folder already shared -// * Root Downloads folder -// * Any folder outside of downloads (e.g. crostini or orive) -crostini.testSharePathNotShown = (done) => { - const myFiles = '#directory-tree .tree-item [root-type-icon="my_files"]'; - const downloads = '#file-list li [file-type-icon="downloads"]'; - const linuxFiles = '#directory-tree .tree-item [root-type-icon="crostini"]'; - const googleDrive = '#directory-tree .tree-item [volume-type-icon="drive"]'; - const menuNoShareWithLinux = '#file-context-menu:not([hidden]) ' + - '[command="#share-with-linux"][hidden][disabled="disabled"]'; - let alreadySharedPhotosDir; - - test.setupAndWaitUntilReady() - .then(() => { - // Right-click 'hello.txt' file. - // Check 'Share with Linux' is not shown in menu. - assertTrue( - test.fakeMouseRightClick('#file-list [file-name="hello.txt"]'), - 'right-click hello.txt'); - return test.waitForElement(menuNoShareWithLinux); - }) - .then(() => { - // Set a folder as already shared. - alreadySharedPhotosDir = - mockVolumeManager - .getCurrentProfileVolumeInfo( - VolumeManagerCommon.VolumeType.DOWNLOADS) - .fileSystem.entries['/photos']; - Crostini.registerSharedPath(alreadySharedPhotosDir, mockVolumeManager); - assertTrue( - test.fakeMouseRightClick('#file-list [file-name="photos"]'), - 'right-click hello.txt'); - return test.waitForElement(menuNoShareWithLinux); - }) - .then(() => { - // Select 'My files' in directory tree to show Downloads in file list. - assertTrue(test.fakeMouseClick(myFiles), 'click My files'); - return test.waitForElement(downloads); - }) - .then(() => { - // Right-click 'Downloads' directory. - // Check 'Share with Linux' is not shown in menu. - assertTrue( - test.fakeMouseRightClick(downloads), 'right-click downloads'); - return test.waitForElement(menuNoShareWithLinux); - }) - .then(() => { - // Select 'Linux files' in directory tree to show dir A in file list. - return test.waitForElement(linuxFiles); - }) - .then(() => { - assertTrue(test.fakeMouseClick(linuxFiles), 'click Linux files'); - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET)); - }) - .then(() => { - // Check 'Share with Linux' is not shown in menu. - assertTrue( - test.fakeMouseRightClick('#file-list [file-name="A"]'), - 'right-click directory A'); - return test.waitForElement(menuNoShareWithLinux); - }) - .then(() => { - // Select 'Google Drive' to show dir photos in file list. - return test.waitForElement(googleDrive); - }) - .then(() => { - assertTrue(test.fakeMouseClick(googleDrive), 'click Google Drive'); - return test.waitForFiles( - test.TestEntryInfo.getExpectedRows(test.BASIC_DRIVE_ENTRY_SET)); - }) - .then(() => { - // Check 'Share with Linux' is not shown in menu. - assertTrue( - test.fakeMouseRightClick('#file-list [file-name="photos"]'), - 'right-click photos'); - return test.waitForElement(menuNoShareWithLinux); - }) - .then(() => { - // Reset Linux files back to unmounted. - chrome.fileManagerPrivate.removeMount('crostini'); - return test.waitForElement( - '#directory-tree .tree-item [root-type-icon="crostini"]'); - }) - .then(() => { - // Clear Crostini shared folders. - Crostini.unregisterSharedPath( - alreadySharedPhotosDir, mockVolumeManager); - done(); - }); -};
diff --git a/ui/file_manager/file_manager/test/crostini_mount.js b/ui/file_manager/file_manager/test/crostini_mount.js new file mode 100644 index 0000000..89138d9 --- /dev/null +++ b/ui/file_manager/file_manager/test/crostini_mount.js
@@ -0,0 +1,134 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +const crostiniMount = {}; + +crostiniMount.testCrostiniNotEnabled = (done) => { + chrome.fileManagerPrivate.crostiniEnabled_ = false; + test.setupAndWaitUntilReady() + .then(() => { + fileManager.setupCrostini_(); + return test.waitForElementLost( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + // Reset crostini back to default enabled=true. + chrome.fileManagerPrivate.crostiniEnabled_ = true; + done(); + }); +}; + +crostiniMount.testMountCrostiniSuccess = (done) => { + const oldMount = chrome.fileManagerPrivate.mountCrostini; + let mountCallback = null; + chrome.fileManagerPrivate.mountCrostini = (callback) => { + mountCallback = callback; + }; + test.setupAndWaitUntilReady() + .then(() => { + // Linux files fake root is shown. + return test.waitForElement( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + // Click on Linux files. + assertTrue( + test.fakeMouseClick( + '#directory-tree .tree-item [root-type-icon="crostini"]'), + 'click linux files'); + return test.waitForElement('paper-progress:not([hidden])'); + }) + .then(() => { + // Ensure mountCrostini is called. + return test.repeatUntil(() => { + if (!mountCallback) + return test.pending('Waiting for mountCrostini'); + return mountCallback; + }); + }) + .then(() => { + // Intercept the fileManagerPrivate.mountCrostini call + // and add crostini disk mount. + test.mountCrostini(); + // Continue from fileManagerPrivate.mountCrostini callback + // and ensure expected files are shown. + mountCallback(); + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET)); + }) + .then(() => { + // Reset fileManagerPrivate.mountCrostini and remove mount. + chrome.fileManagerPrivate.mountCrostini = oldMount; + chrome.fileManagerPrivate.removeMount('crostini'); + // Linux Files fake root is shown. + return test.waitForElement( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + // Downloads folder should be shown when crostini goes away. + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows(test.BASIC_LOCAL_ENTRY_SET)); + }) + .then(() => { + done(); + }); +}; + +crostiniMount.testMountCrostiniError = (done) => { + const oldMount = chrome.fileManagerPrivate.mountCrostini; + // Override fileManagerPrivate.mountCrostini to return error. + chrome.fileManagerPrivate.mountCrostini = (callback) => { + chrome.runtime.lastError = {message: 'test message'}; + callback(); + delete chrome.runtime.lastError; + }; + test.setupAndWaitUntilReady() + .then(() => { + return test.waitForElement( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + // Click on Linux Files, ensure error dialog is shown. + assertTrue(test.fakeMouseClick( + '#directory-tree .tree-item [root-type-icon="crostini"]')); + return test.waitForElement('.cr-dialog-container.shown'); + }) + .then(() => { + // Click OK button to close. + assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); + return test.waitForElementLost('.cr-dialog-container'); + }) + .then(() => { + // Reset chrome.fileManagerPrivate.mountCrostini. + chrome.fileManagerPrivate.mountCrostini = oldMount; + done(); + }); +}; + +crostiniMount.testCrostiniMountOnDrag = (done) => { + chrome.fileManagerPrivate.mountCrostiniDelay_ = 0; + test.setupAndWaitUntilReady() + .then(() => { + return test.waitForElement( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + assertTrue(test.sendEvent( + '#directory-tree .tree-item [root-type-icon="crostini"]', + new Event('dragenter', {bubbles: true}))); + assertTrue(test.sendEvent( + '#directory-tree .tree-item [root-type-icon="crostini"]', + new Event('dragleave', {bubbles: true}))); + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET)); + }) + .then(() => { + chrome.fileManagerPrivate.removeMount('crostini'); + return test.waitForElement( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + done(); + }); +};
diff --git a/ui/file_manager/file_manager/test/crostini_share.js b/ui/file_manager/file_manager/test/crostini_share.js new file mode 100644 index 0000000..c52f657 --- /dev/null +++ b/ui/file_manager/file_manager/test/crostini_share.js
@@ -0,0 +1,204 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +const crostiniShare = {}; + +crostiniShare.testSharePathCrostiniSuccess = (done) => { + const oldSharePath = chrome.fileManagerPrivate.sharePathWithCrostini; + let sharePathCalled = false; + chrome.fileManagerPrivate.sharePathWithCrostini = (entry, callback) => { + oldSharePath(entry, () => { + sharePathCalled = true; + callback(); + }); + }; + chrome.metricsPrivate.smallCounts_ = []; + chrome.metricsPrivate.values_ = []; + + test.setupAndWaitUntilReady() + .then(() => { + // Right-click 'photos' directory. + // Check 'Share with Linux' is shown in menu. + assertTrue( + test.fakeMouseRightClick('#file-list [file-name="photos"]'), + 'right-click photos'); + return test.waitForElement( + '#file-context-menu:not([hidden]) ' + + '[command="#share-with-linux"]:not([hidden]):not([disabled])'); + }) + .then(() => { + // Click on 'Share with Linux'. + assertTrue( + test.fakeMouseClick( + '#file-context-menu [command="#share-with-linux"]'), + 'Share with Linux'); + // Check sharePathWithCrostini is called. + return test.repeatUntil(() => { + return sharePathCalled || test.pending('wait for sharePathCalled'); + }); + }) + .then(() => { + // Validate UMAs. + assertEquals(1, chrome.metricsPrivate.smallCounts_.length); + assertArrayEquals( + ['FileBrowser.CrostiniSharedPaths.Depth.downloads', 1], + chrome.metricsPrivate.smallCounts_[0]); + const lastEnumUma = chrome.metricsPrivate.values_.pop(); + assertEquals('FileBrowser.MenuItemSelected', lastEnumUma[0].metricName); + assertEquals(12 /* Share with Linux */, lastEnumUma[1]); + + // Restore fmp.*. + chrome.fileManagerPrivate.sharePathWithCrostini = oldSharePath; + done(); + }); +}; + +// Verify right-click menu with 'Share with Linux' is not shown for: +// * Files (not directory) +// * Any folder already shared +// * Root Downloads folder +// * Any folder outside of downloads (e.g. crostini or orive) +crostiniShare.testSharePathNotShown = (done) => { + const myFiles = '#directory-tree .tree-item [root-type-icon="my_files"]'; + const downloads = '#file-list li [file-type-icon="downloads"]'; + const linuxFiles = '#directory-tree .tree-item [root-type-icon="crostini"]'; + const googleDrive = '#directory-tree .tree-item [volume-type-icon="drive"]'; + const menuNoShareWithLinux = '#file-context-menu:not([hidden]) ' + + '[command="#share-with-linux"][hidden][disabled="disabled"]'; + let alreadySharedPhotosDir; + + test.setupAndWaitUntilReady() + .then(() => { + // Right-click 'hello.txt' file. + // Check 'Share with Linux' is not shown in menu. + assertTrue( + test.fakeMouseRightClick('#file-list [file-name="hello.txt"]'), + 'right-click hello.txt'); + return test.waitForElement(menuNoShareWithLinux); + }) + .then(() => { + // Set a folder as already shared. + alreadySharedPhotosDir = + mockVolumeManager + .getCurrentProfileVolumeInfo( + VolumeManagerCommon.VolumeType.DOWNLOADS) + .fileSystem.entries['/photos']; + Crostini.registerSharedPath(alreadySharedPhotosDir, mockVolumeManager); + assertTrue( + test.fakeMouseRightClick('#file-list [file-name="photos"]'), + 'right-click hello.txt'); + return test.waitForElement(menuNoShareWithLinux); + }) + .then(() => { + // Select 'My files' in directory tree to show Downloads in file list. + assertTrue(test.fakeMouseClick(myFiles), 'click My files'); + return test.waitForElement(downloads); + }) + .then(() => { + // Right-click 'Downloads' directory. + // Check 'Share with Linux' is not shown in menu. + assertTrue( + test.fakeMouseRightClick(downloads), 'right-click downloads'); + return test.waitForElement(menuNoShareWithLinux); + }) + .then(() => { + // Select 'Linux files' in directory tree to show dir A in file list. + return test.waitForElement(linuxFiles); + }) + .then(() => { + assertTrue(test.fakeMouseClick(linuxFiles), 'click Linux files'); + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET)); + }) + .then(() => { + // Check 'Share with Linux' is not shown in menu. + assertTrue( + test.fakeMouseRightClick('#file-list [file-name="A"]'), + 'right-click directory A'); + return test.waitForElement(menuNoShareWithLinux); + }) + .then(() => { + // Select 'Google Drive' to show dir photos in file list. + return test.waitForElement(googleDrive); + }) + .then(() => { + assertTrue(test.fakeMouseClick(googleDrive), 'click Google Drive'); + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows(test.BASIC_DRIVE_ENTRY_SET)); + }) + .then(() => { + // Check 'Share with Linux' is not shown in menu. + assertTrue( + test.fakeMouseRightClick('#file-list [file-name="photos"]'), + 'right-click photos'); + return test.waitForElement(menuNoShareWithLinux); + }) + .then(() => { + // Reset Linux files back to unmounted. + chrome.fileManagerPrivate.removeMount('crostini'); + return test.waitForElement( + '#directory-tree .tree-item [root-type-icon="crostini"]'); + }) + .then(() => { + // Clear Crostini shared folders. + Crostini.unregisterSharedPath( + alreadySharedPhotosDir, mockVolumeManager); + done(); + }); +}; + +// Verify gear menu 'Manage Linux sharing'. +crostiniShare.testGearMenuManageLinuxSharing = (done) => { + const gearMenuClosed = '#gear-menu[hidden]'; + const manageLinuxSharingOptionHidden = + '#gear-menu:not([hidden]) #gear-menu-manage-linux-sharing[hidden]'; + const manageLinuxSharingOptionShown = + '#gear-menu:not([hidden]) #gear-menu-manage-linux-sharing:not([hidden])'; + chrome.metricsPrivate.values_ = []; + + test.setupAndWaitUntilReady() + .then(() => { + // Setup with crostini disabled. + chrome.fileManagerPrivate.crostiniEnabled_ = false; + fileManager.setupCrostini_(); + return test.repeatUntil( + () => !Crostini.IS_CROSTINI_FILES_ENABLED || + test.pending('crostini setup')); + }) + .then(() => { + // Click gear menu, ensure 'Manage Linux sharing' is hidden. + assertTrue(test.fakeMouseClick('#gear-button')); + return test.waitForElement(manageLinuxSharingOptionHidden); + }) + .then(() => { + // Close gear menu. + assertTrue(test.fakeMouseClick('#gear-button')); + return test.waitForElement(gearMenuClosed); + }) + .then(() => { + // Setup with crostini enabled. + chrome.fileManagerPrivate.crostiniEnabled_ = true; + fileManager.setupCrostini_(); + return test.repeatUntil( + () => Crostini.IS_CROSTINI_FILES_ENABLED || + test.pending('crostini setup')); + }) + .then(() => { + // Click gear menu, ensure 'Manage Linux sharing' is shown. + assertTrue(test.fakeMouseClick('#gear-button')); + return test.waitForElement(manageLinuxSharingOptionShown); + }) + .then(() => { + // Click 'Manage Linux sharing'. + assertTrue(test.fakeMouseClick('#gear-menu-manage-linux-sharing')); + return test.waitForElement(gearMenuClosed); + }) + .then(() => { + // Verify UMA. + const lastEnumUma = chrome.metricsPrivate.values_.pop(); + assertEquals('FileBrowser.MenuItemSelected', lastEnumUma[0].metricName); + assertEquals(13 /* Manage Linux sharing */, lastEnumUma[1]); + done(); + }); +};
diff --git a/ui/file_manager/file_manager/test/crostini_tasks.js b/ui/file_manager/file_manager/test/crostini_tasks.js new file mode 100644 index 0000000..36366e5 --- /dev/null +++ b/ui/file_manager/file_manager/test/crostini_tasks.js
@@ -0,0 +1,163 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +const crostiniTasks = {}; + +crostiniTasks.testShareBeforeOpeningDownloadsWithCrostiniApp = (done) => { + // Save old fmp.getFileTasks and replace with version that returns + // crostini app and chrome Text app. + let oldGetFileTasks = chrome.fileManagerPrivate.getFileTasks; + chrome.fileManagerPrivate.getFileTasks = (entries, callback) => { + setTimeout(callback, 0, [ + { + taskId: 'text-app-id|app|text', + title: 'Text', + verb: 'open_with', + }, + { + taskId: 'crostini-app-id|crostini|open-with', + title: 'Crostini App', + verb: 'open_with', + } + ]); + }; + + // Save old fmp.sharePathWitCrostini. + const oldSharePath = chrome.fileManagerPrivate.sharePathWithCrostini; + let sharePathCalled = false; + chrome.fileManagerPrivate.sharePathWithCrostini = (entry, callback) => { + sharePathCalled = true; + oldSharePath(entry, callback); + }; + + // Save old fmp.executeTask. + const oldExecuteTask = chrome.fileManagerPrivate.executeTask; + let executeTaskCalled = false; + chrome.fileManagerPrivate.executeTask = (taskId, entries, callback) => { + executeTaskCalled = true; + oldExecuteTask(taskId, entries, callback); + }; + chrome.metricsPrivate.values_ = []; + + test.setupAndWaitUntilReady([], [], []) + .then(() => { + // Add '/A', and '/A/hello.txt', refresh, 'A' is shown. + test.addEntries( + [test.ENTRIES.directoryA, test.ENTRIES.helloInA], [], []); + assertTrue(test.fakeMouseClick('#refresh-button'), 'click refresh'); + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows([test.ENTRIES.directoryA])); + }) + .then(() => { + // Change to 'A' directory, hello.txt is shown. + assertTrue(test.fakeMouseDoubleClick('[file-name="A"]')); + return test.waitForFiles( + test.TestEntryInfo.getExpectedRows([test.ENTRIES.hello])); + }) + .then(() => { + // Right click on 'hello.txt' file, wait for dialog with 'Open with'. + assertTrue(test.fakeMouseRightClick('[file-name="hello.txt"]')); + return test.waitForElement( + 'cr-menu-item[command="#open-with"]:not([hidden]'); + }) + .then(() => { + // Click 'Open with', wait for picker. + assertTrue(test.fakeMouseClick('cr-menu-item[command="#open-with"]')); + return test.waitForElement('#default-tasks-list'); + }) + .then(() => { + // Ensure picker shows both options. Click on 'Crostini App'. Ensure + // share path dialog is shown. + const list = document.querySelectorAll('#default-tasks-list li div'); + assertEquals(2, list.length); + assertEquals('Open with Crostini App', list[0].innerText); + assertEquals('Open with Text', list[1].innerText); + assertTrue(test.fakeMouseClick('#default-tasks-list li')); + return test.repeatUntil(() => { + return document.querySelector('.cr-dialog-title').innerText === + 'Share files with Linux' || + test.pending('Waiting for share before open dialog'); + }); + }) + .then(() => { + // Validate dialog messages, click 'OK' to share and open. Ensure + // dialog closes. + assertEquals( + 'Let Linux apps open <b>hello.txt</b>.', + document.querySelector('.cr-dialog-text').innerHTML); + assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); + return test.waitForElementLost('.cr-dialog-container'); + }) + .then(() => { + // Ensure fmp.sharePathWithCrostini, fmp.executeTask called. + return test.repeatUntil(() => { + return sharePathCalled && executeTaskCalled || + test.pending('Waiting to share and open'); + }); + }) + .then(() => { + // Validate UMAs. + const lastEnumUma = chrome.metricsPrivate.values_.pop(); + assertEquals( + 'FileBrowser.CrostiniShareDialog', lastEnumUma[0].metricName); + assertEquals(1 /* ShareBeforeOpen */, lastEnumUma[1]); + + // Restore fmp.*. + chrome.fileManagerPrivate.getFileTasks = oldGetFileTasks; + chrome.fileManagerPrivate.sharePathWithCrostini = oldSharePath; + chrome.fileManagerPrivate.executeTask = oldExecuteTask; + done(); + }); +}; + +crostiniTasks.testErrorOpeningDownloadsRootWithDefaultCrostiniApp = (done) => { + // Save old fmp.getFileTasks and replace with version that returns + // crostini app and chrome Text app. + let oldGetFileTasks = chrome.fileManagerPrivate.getFileTasks; + chrome.fileManagerPrivate.getFileTasks = (entries, callback) => { + setTimeout(callback, 0, [{ + taskId: 'crostini-app-id|crostini|open-with', + title: 'Crostini App', + verb: 'open_with', + isDefault: true, + }]); + }; + + test.setupAndWaitUntilReady() + .then(() => { + // Right click on 'world.ogv' file, wait for dialog with the default + // task action. + assertTrue(test.fakeMouseRightClick('[file-name="world.ogv"]')); + return test.repeatUntil(() => { + return document + .querySelector( + 'cr-menu-item[command="#default-task"]:not([hidden])') + .label === 'Crostini App' || + test.pending('Waiting for default task menu item'); + }); + }) + .then(() => { + // Click 'Open with', wait for picker. + assertTrue( + test.fakeMouseClick('cr-menu-item[command="#default-task"]')); + return test.waitForElement('.cr-dialog-container'); + }) + .then(() => { + // Validate error messages, click 'OK' to close. Ensure dialog closes. + assertEquals( + 'Unable to open with Crostini App', + document.querySelector('.cr-dialog-title').innerText); + assertEquals( + 'To open files with Crostini App, ' + + 'first copy to Linux files folder.', + document.querySelector('.cr-dialog-text').innerText); + assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); + return test.waitForElementLost('.cr-dialog-container'); + }) + .then(() => { + // Restore fmp.getFileTasks. + chrome.fileManagerPrivate.getFileTasks = oldGetFileTasks; + done(); + }); +};
diff --git a/ui/file_manager/gallery/js/BUILD.gn b/ui/file_manager/gallery/js/BUILD.gn index 17e71d7..502bb88 100644 --- a/ui/file_manager/gallery/js/BUILD.gn +++ b/ui/file_manager/gallery/js/BUILD.gn
@@ -62,8 +62,7 @@ deps = [ ":entry_list_watcher", "../../file_manager/common/js:mock_entry", - "../../file_manager/common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -104,7 +103,7 @@ deps = [ ":gallery_data_model", ":mock_gallery_item", - "../../file_manager/common/js:unittest_util", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -125,8 +124,7 @@ deps = [ ":gallery_item", ":mock_gallery_item", - "../../file_manager/common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -143,8 +141,7 @@ deps = [ ":gallery_util", "../../file_manager/common/js:mock_entry", - "../../file_manager/common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -202,8 +199,7 @@ js_library("slide_mode_unittest") { deps = [ ":slide_mode", - "../../file_manager/common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] }
diff --git a/ui/file_manager/gallery/js/entry_list_watcher_unittest.js b/ui/file_manager/gallery/js/entry_list_watcher_unittest.js index 633afe4f..d148fc9 100644 --- a/ui/file_manager/gallery/js/entry_list_watcher_unittest.js +++ b/ui/file_manager/gallery/js/entry_list_watcher_unittest.js
@@ -5,6 +5,44 @@ var chrome; var mockFileSystem; +/** + * @constructor + * @struct + */ +function MockAPIEvent() { + /** + * @type {!Array<!Function>} + * @const + */ + this.listeners_ = []; +} + +/** + * @param {!Function} callback + */ +MockAPIEvent.prototype.addListener = function(callback) { + this.listeners_.push(callback); +}; + +/** + * @param {!Function} callback + */ +MockAPIEvent.prototype.removeListener = function(callback) { + var index = this.listeners_.indexOf(callback); + if (index < 0) + throw new Error('Tried to remove an unregistered listener.'); + this.listeners_.splice(index, 1); +}; + +/** + * @param {...*} var_args + */ +MockAPIEvent.prototype.dispatch = function(var_args) { + for (var i = 0; i < this.listeners_.length; i++) { + this.listeners_[i].apply(null, arguments); + } +}; + function webkitResolveLocalFileSystemURL(url, callback) { var paths = Object.keys(mockFileSystem.entries); for (var i = 0; i < paths.length; i++) {
diff --git a/ui/file_manager/gallery/js/image_editor/BUILD.gn b/ui/file_manager/gallery/js/image_editor/BUILD.gn index e7a6675..1ef2fd38 100644 --- a/ui/file_manager/gallery/js/image_editor/BUILD.gn +++ b/ui/file_manager/gallery/js/image_editor/BUILD.gn
@@ -124,8 +124,8 @@ deps = [ ":image_encoder", ":test_util", - "../../../file_manager/common/js:unittest_util", "../../../file_manager/foreground/js/metadata:metadata_parser", + "//ui/file_manager/base/js:test_error_reporting", ] externs_list = [ "../../../externs/metadata_worker_window.js" ] }
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn index f883211..b0f9ceb 100644 --- a/ui/file_manager/image_loader/BUILD.gn +++ b/ui/file_manager/image_loader/BUILD.gn
@@ -85,8 +85,7 @@ js_library("image_loader_client_unittest") { deps = [ ":image_loader_client", - "../file_manager/common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] } @@ -100,8 +99,7 @@ js_library("piex_loader_unittest") { deps = [ ":piex_loader", - "../file_manager/common/js:unittest_util", - "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/base/js:test_error_reporting", ] }
diff --git a/ui/file_manager/integration_tests/file_manager/my_files.js b/ui/file_manager/integration_tests/file_manager/my_files.js index 4ad283f..fc7bc54 100644 --- a/ui/file_manager/integration_tests/file_manager/my_files.js +++ b/ui/file_manager/integration_tests/file_manager/my_files.js
@@ -325,3 +325,107 @@ }, ]); }; + +/** + * Check naming a folder after navigating inside MyFiles using file list (RHS). + * crbug.com/889636. + */ +testcase.myFilesFolderRename = function() { + let appId; + const textInput = '#file-list .table-row[renaming] input.rename'; + StepsRunner.run([ + // Open Files app on local Downloads. + function() { + setupAndWaitUntilReady( + null, RootPath.DOWNLOADS, this.next, [ENTRIES.photos], []); + }, + // Select "My files" folder via directory tree. + function(result) { + appId = result.windowId; + const myFilesQuery = '#directory-tree [entry-label="My files"]'; + const isDriveQuery = false; + remoteCall.callRemoteTestUtil( + 'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery], + this.next); + }, + // Wait for Downloads to load. + function(result) { + chrome.test.assertTrue(!!result, 'selectInDirectoryTree failed'); + const expectedRows = [ + ['Downloads', '--', 'Folder'], + ['Play files', '--', 'Folder'], + ['Linux files', '--', 'Folder'], + ]; + remoteCall + .waitForFiles( + appId, expectedRows, + {ignoreFileSize: true, ignoreLastModifiedTime: true}) + .then(this.next); + }, + // Select Downloads via file list. + function() { + const downloads = ['Downloads']; + remoteCall.callRemoteTestUtil('selectFile', appId, downloads) + .then(result => { + chrome.test.assertTrue(!!result, 'selectFile failed'); + this.next(); + }); + }, + // Open Downloads via file list. + function() { + const fileListItem = '#file-list .table-row'; + const key = [fileListItem, 'Enter', false, false, false]; + remoteCall.callRemoteTestUtil('fakeKeyDown', appId, key).then(this.next); + }, + // Wait for Downloads to load. + function(result) { + chrome.test.assertTrue(!!result, 'fakeKeyDown failed'); + remoteCall.waitForFiles(appId, [ENTRIES.photos.getExpectedRow()]) + .then(this.next); + }, + // Select photos via file list. + function() { + const folder = ['photos']; + remoteCall.callRemoteTestUtil('selectFile', appId, folder) + .then(result => { + chrome.test.assertTrue(!!result, 'selectFile failed'); + this.next(); + }); + }, + // Press Ctrl+Enter for start renaming. + function() { + const fileListItem = '#file-list .table-row'; + const key = [fileListItem, 'Enter', true, false, false]; + remoteCall.callRemoteTestUtil('fakeKeyDown', appId, key).then(this.next); + }, + // Wait for input for renaming to appear. + function(result) { + chrome.test.assertTrue(result, 'fakeKeyDown ctrl+Enter failed'); + // Check: the renaming text input should be shown in the file list. + remoteCall.waitForElement(appId, textInput).then(this.next); + }, + // Type new name. + function() { + remoteCall.callRemoteTestUtil('inputText', appId, [textInput, 'new name']) + .then(this.next); + }, + // Send Enter key to the text input. + function() { + const key = [textInput, 'Enter', false, false, false]; + remoteCall.callRemoteTestUtil('fakeKeyDown', appId, key).then(this.next); + }, + // Wait for new name to appear on the file list. + function(result) { + chrome.test.assertTrue(result, 'fakeKeyDown failed'); + const expectedRows = [['new name', '--', 'Folder', '']]; + remoteCall + .waitForFiles( + appId, expectedRows, + {ignoreFileSize: true, ignoreLastModifiedTime: true}) + .then(this.next); + }, + function() { + checkIfNoErrorsOccured(this.next); + }, + ]); +};
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js index 1f15419..e351fffb 100644 --- a/ui/file_manager/integration_tests/file_manager/quick_view.js +++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -723,6 +723,68 @@ }; /** + * Tests opening Quick View containing an audio file. + */ +testcase.openQuickViewAudio = function() { + const caller = getCaller(); + let appId; + + /** + * The <webview> resides in the <files-safe-media type="audio"> shadow DOM, + * which is a child of the #quick-view shadow DOM. + */ + const webView = ['#quick-view', 'files-safe-media[type="audio"]', 'webview']; + + StepsRunner.run([ + // Open Files app on Downloads containing ENTRIES.beautiful song. + function() { + setupAndWaitUntilReady( + null, RootPath.DOWNLOADS, this.next, [ENTRIES.beautiful], []); + }, + // Open the file in Quick View. + function(results) { + appId = results.windowId; + const openSteps = openQuickViewSteps(appId, ENTRIES.beautiful.nameText); + StepsRunner.run(openSteps).then(this.next); + }, + // Wait for the Quick View <webview> to load and display its content. + function() { + function checkWebViewAudioLoaded(elements) { + let haveElements = Array.isArray(elements) && elements.length === 1; + if (haveElements) + haveElements = elements[0].styles.display.includes('block'); + if (!haveElements || elements[0].attributes.loaded !== '') + return pending(caller, 'Waiting for <webview> to load.'); + return; + } + repeatUntil(function() { + return remoteCall + .callRemoteTestUtil( + 'deepQueryAllElements', appId, [webView, ['display']]) + .then(checkWebViewAudioLoaded); + }).then(this.next); + }, + // Get the <webview> document.body backgroundColor style. + function() { + const getBackgroundStyle = + 'window.getComputedStyle(document.body).backgroundColor'; + remoteCall + .callRemoteTestUtil( + 'deepExecuteScriptInWebView', appId, [webView, getBackgroundStyle]) + .then(this.next); + }, + // Check: the <webview> body backgroundColor should be transparent black. + function(backgroundColor) { + chrome.test.assertEq('rgba(0, 0, 0, 0)', backgroundColor[0]); + this.next(); + }, + function() { + checkIfNoErrorsOccured(this.next); + }, + ]); +}; + +/** * Tests opening Quick View containing an image. */ testcase.openQuickViewImage = function() {
diff --git a/ui/ozone/platform/wayland/wayland_window.cc b/ui/ozone/platform/wayland/wayland_window.cc index 27ddd18..0d02721 100644 --- a/ui/ozone/platform/wayland/wayland_window.cc +++ b/ui/ozone/platform/wayland/wayland_window.cc
@@ -74,7 +74,8 @@ : delegate_(delegate), connection_(connection), xdg_shell_objects_factory_(new XDGShellObjectFactory()), - state_(PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL) { + state_(PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL), + pending_state_(PlatformWindowState::PLATFORM_WINDOW_STATE_UNKNOWN) { // Set a class property key, which allows |this| to be used for interactive // events, e.g. move or resize. SetWmMoveResizeHandler(this, AsWmMoveResizeHandler()); @@ -296,6 +297,17 @@ void WaylandWindow::ToggleFullscreen() { DCHECK(xdg_surface_); + // There are some cases, when Chromium triggers a fullscreen state change + // before the surface is activated. In such cases, Wayland may ignore state + // changes and such flags as --kiosk or --start-fullscreen will be ignored. + // To overcome this, set a pending state, and once the surface is activated, + // trigger the change. + if (!is_active_) { + DCHECK(!IsFullscreen()); + pending_state_ = PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN; + return; + } + // TODO(msisov, tonikitoo): add multiscreen support. As the documentation says // if xdg_surface_set_fullscreen() is not provided with wl_output, it's up to // the compositor to choose which display will be used to map this surface. @@ -468,7 +480,7 @@ // Ensure that manually handled state changes to fullscreen correspond to the // configuration events from a compositor. - DCHECK(is_fullscreen == IsFullscreen()); + DCHECK_EQ(is_fullscreen, IsFullscreen()); // There are two cases, which must be handled for the minimized state. // The first one is the case, when the surface goes into the minimized state @@ -525,6 +537,8 @@ if (did_active_change) delegate_->OnActivationChanged(is_active_); + + MaybeTriggerPendingStateChange(); } void WaylandWindow::OnCloseRequest() { @@ -571,6 +585,16 @@ return state_ == PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN; } +void WaylandWindow::MaybeTriggerPendingStateChange() { + if (pending_state_ == PlatformWindowState::PLATFORM_WINDOW_STATE_UNKNOWN || + !is_active_) + return; + DCHECK_EQ(pending_state_, + PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN); + pending_state_ = PlatformWindowState::PLATFORM_WINDOW_STATE_UNKNOWN; + ToggleFullscreen(); +} + WaylandWindow* WaylandWindow::GetParentWindow( gfx::AcceleratedWidget parent_widget) { WaylandWindow* parent_window = connection_->GetWindow(parent_widget);
diff --git a/ui/ozone/platform/wayland/wayland_window.h b/ui/ozone/platform/wayland/wayland_window.h index e1cb0f6..ad9eb0c 100644 --- a/ui/ozone/platform/wayland/wayland_window.h +++ b/ui/ozone/platform/wayland/wayland_window.h
@@ -129,6 +129,8 @@ bool IsMaximized() const; bool IsFullscreen() const; + void MaybeTriggerPendingStateChange(); + // Creates a popup window, which is visible as a menu window. void CreateXdgPopup(); // Creates a surface window, which is visible as a main window. @@ -171,6 +173,9 @@ // Stores current states of the window. ui::PlatformWindowState state_; + // Stores a pending state of the window, which is used before the surface is + // activated. + ui::PlatformWindowState pending_state_; bool is_active_ = false; bool is_minimizing_ = false;
diff --git a/ui/ozone/platform/wayland/wayland_window_unittest.cc b/ui/ozone/platform/wayland/wayland_window_unittest.cc index a97b92eb..abc14e6 100644 --- a/ui/ozone/platform/wayland/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/wayland_window_unittest.cc
@@ -219,6 +219,8 @@ EXPECT_EQ(PLATFORM_WINDOW_STATE_NORMAL, window_->GetPlatformWindowState()); ScopedWlArray states = InitializeWlArrayWithActivatedState(); + SendConfigureEvent(0, 0, 1, states.get()); + Sync(); AddStateToWlArray(XDG_SURFACE_STATE_FULLSCREEN, states.get()); @@ -230,7 +232,7 @@ // comment in the WaylandWindow::ToggleFullscreen. EXPECT_EQ(window_->GetPlatformWindowState(), PLATFORM_WINDOW_STATE_FULLSCREEN); - SendConfigureEvent(0, 0, 1, states.get()); + SendConfigureEvent(0, 0, 2, states.get()); Sync(); EXPECT_CALL(*GetXdgSurface(), UnsetFullscreen()); @@ -240,7 +242,45 @@ EXPECT_EQ(window_->GetPlatformWindowState(), PLATFORM_WINDOW_STATE_UNKNOWN); // Reinitialize wl_array, which removes previous old states. states = InitializeWlArrayWithActivatedState(); + SendConfigureEvent(0, 0, 3, states.get()); + Sync(); +} + +TEST_P(WaylandWindowTest, StartWithFullscreen) { + // Make sure the window is initialized to normal state from the beginning. + EXPECT_EQ(PLATFORM_WINDOW_STATE_NORMAL, window_->GetPlatformWindowState()); + + // The state must not be changed to the fullscreen before the surface is + // activated. + EXPECT_CALL(*GetXdgSurface(), SetFullscreen()).Times(0); + EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(0); + window_->ToggleFullscreen(); + // The state of the window must still be a normal one. + EXPECT_EQ(window_->GetPlatformWindowState(), PLATFORM_WINDOW_STATE_NORMAL); + + Sync(); + + // Once the surface will be activated, the window will automatically trigger + // the state change. + EXPECT_CALL(*GetXdgSurface(), SetFullscreen()); + EXPECT_CALL(delegate_, + OnWindowStateChanged(Eq(PLATFORM_WINDOW_STATE_FULLSCREEN))); + + // Activate the surface. + ScopedWlArray states = InitializeWlArrayWithActivatedState(); + SendConfigureEvent(0, 0, 1, states.get()); + + Sync(); + + // The wayland window manually handles the fullscreen state changes, and it + // must change to a fullscreen before the state change is confirmed by the + // wayland. See comment in the WaylandWindow::ToggleFullscreen. + EXPECT_EQ(window_->GetPlatformWindowState(), + PLATFORM_WINDOW_STATE_FULLSCREEN); + + AddStateToWlArray(XDG_SURFACE_STATE_FULLSCREEN, states.get()); SendConfigureEvent(0, 0, 2, states.get()); + Sync(); } @@ -314,6 +354,8 @@ const gfx::Rect current_bounds = window_->GetBounds(); ScopedWlArray states = InitializeWlArrayWithActivatedState(); + SendConfigureEvent(0, 0, 1, states.get()); + Sync(); gfx::Rect restored_bounds = window_->GetRestoredBoundsInPixels(); EXPECT_EQ(restored_bounds, gfx::Rect()); @@ -323,7 +365,7 @@ EXPECT_CALL(delegate_, OnBoundsChanged(Eq(fullscreen_bounds))); window_->ToggleFullscreen(); AddStateToWlArray(XDG_SURFACE_STATE_FULLSCREEN, states.get()); - SendConfigureEvent(fullscreen_bounds.width(), fullscreen_bounds.height(), 1, + SendConfigureEvent(fullscreen_bounds.width(), fullscreen_bounds.height(), 2, states.get()); Sync(); restored_bounds = window_->GetRestoredBoundsInPixels(); @@ -338,7 +380,7 @@ window_->Restore(); // Reinitialize wl_array, which removes previous old states. states = InitializeWlArrayWithActivatedState(); - SendConfigureEvent(0, 0, 2, states.get()); + SendConfigureEvent(0, 0, 3, states.get()); Sync(); bounds = window_->GetBounds(); EXPECT_EQ(bounds, restored_bounds);
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn index 86fda9f..616ad6e 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
@@ -18,6 +18,7 @@ ":setup_succeeded_page", ":start_setup_page", ":ui_page_container_behavior", + "//ui/webui/resources/js:web_ui_listener_behavior", ] } @@ -116,6 +117,7 @@ js_library("start_setup_page") { deps = [ ":ui_page_container_behavior", + "//ui/webui/resources/js:web_ui_listener_behavior", ] }
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html index 7a3325d24..a410816b 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html
@@ -5,6 +5,8 @@ <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html"> <link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <dom-module id="start-setup-page"> @@ -78,7 +80,7 @@ </style> <ui-page header-text="[[headerText]]" icon-name="google-g"> - <span slot="message" inner-h-t-m-l="[[messageHtml]]"></span> + <span slot="message" id="multidevice-summary-message" inner-h-t-m-l="[[messageHtml]]"></span> <div slot="additional-content"> <div id="selector-and-details-container"> <div id="deviceSelectionContainer" class="flex"> @@ -109,7 +111,7 @@ </div> <div class="feature-detail"> <iron-icon icon="multidevice-setup-icons-20:messages"></iron-icon> - <span inner-h-t-m-l=" + <span id="awm-summary-message" inner-h-t-m-l=" [[i18nAdvanced('startSetupPageFeatureListAwm')]]"> </span> </div>
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js index 949fc8e..85437ce 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js
@@ -58,8 +58,31 @@ behaviors: [ UiPageContainerBehavior, I18nBehavior, + WebUIListenerBehavior, ], + /** @override */ + attached: function() { + this.addWebUIListener( + 'multidevice_setup.initializeSetupFlow', + this.initializeSetupFlow_.bind(this)); + }, + + /** @private */ + initializeSetupFlow_: function() { + // The "Learn More" links are inside a grdp string, so we cannot actually + // add an onclick handler directly to the html. Instead, grab the two and + // manaully add onclick handlers. + let helpArticleLinks = [ + this.$$('#multidevice-summary-message a'), + this.$$('#awm-summary-message a') + ]; + for (let i = 0; i < helpArticleLinks.length; i++) { + helpArticleLinks[i].onclick = this.fire.bind( + this, 'open-learn-more-webview-requested', helpArticleLinks[i].href); + } + }, + /** * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices * @return {string} Label for devices selection content.